5

I have the task of creating two seperate programs, one linear search program, which I have already completed, and a binary search program. These programs must also count the number of comparisons made during the search process. My linear search program already counts the number of comparisons made while my binary search program cannot. The code for the binary search looks like this:

using System;
using System.Collections.Generic;

public class Example
{
public static void Main()
{

    Console.WriteLine("Input number you would like to search for");

    String Look_for = Console.ReadLine();

    int Lookfor;

    int.TryParse(Look_for, out Lookfor);

    {
        List<int> numbers = new List<int>();

        numbers.Add(1); 
        numbers.Add(2); 
        numbers.Add(3); 
        numbers.Add(4); 
        numbers.Add(5); 
        numbers.Add(6); 
        numbers.Add(7); 
        numbers.Add(8); 

        Console.WriteLine();
        foreach (int number in numbers)
        {
            Console.WriteLine(number);
        }

        int answer = numbers.BinarySearch(Lookfor);

        Console.WriteLine("The numbers was found at:");

        Console.WriteLine(answer);

    }
 }
}

If anybody can tell me how to modify it to count comparisons it would be greatly appreciated.

Many thanks, Matthew.

dash
  • 89,546
  • 4
  • 51
  • 71
Matthew Morgan
  • 199
  • 2
  • 10
  • Do you have access to the BinarySearch extension method? – dwonisch Oct 05 '12 at 08:16
  • 3
    Are you sure you are supposed to complete this task using the built-in [BinarySearch](http://msdn.microsoft.com/en-us/library/w4e7fxsh(v=vs.100).aspx)? You could write a custom comparer that counts the number of invocations but usually the point of such exercises is to implement the functionality yourself... – verdesmarald Oct 05 '12 at 08:18
  • The task was to compare the efficiency of both searches using different sized lists, would that be easier if I made own binary search rather then using the built in one? – Matthew Morgan Oct 05 '12 at 08:40

4 Answers4

5

Implement an IComparer<int> that counts the comparisons:

private class CountComparer : IComparer<int> {

  public int Count { get; private set; }

  public CountComparer() {
    Count = 0;
  }

  public int Compare(int x, int y) {
    Count++;
    return x.CompareTo(y);
  }

}

Then use it as comparer in the overload of BinarySearch that takes a comparer:

CountComparer comparer = new CountComparer();
int answer = numbers.BinarySearch(Lookfor, comparer);

The comparer then contains the count:

Console.WriteLine("The binary search made {0} comparisons.", comparer.Count);

Bonus: A generic counting comparer for any comparable type:

private class CountComparer<T> : IComparer<T> where T : IComparable<T> {

  public int Count { get; private set; }

  public CountComparer() {
    Count = 0;
  }

  public int Compare(T x, T y) {
    Count++;
    return x.CompareTo(y);
  }

}
Guffa
  • 687,336
  • 108
  • 737
  • 1,005
3

You could write a custom IComparer<int> that counts the number of times it is used, then use this in your search methods. (Or a custom IEqualityComparer<int> for your linear search, I suppose.)

Rawling
  • 49,248
  • 7
  • 89
  • 127
3

You can use this extension method (code based on this answer)

public static class ListEx
{
    public static Tuple<int, int> BinarySearchWithCount<T>(
        this IList<T> list, T key)
    {
        int min = 0;
        int max = list.Count - 1;
        int counter = 0;

        while (min <= max)
        {
            counter++;
            int mid = (min + max) / 2;
            int comparison = Comparer<T>.Default.Compare(list[mid], key);
            if (comparison == 0)
            {
                return new Tuple<int, int>(mid, counter);
            }
            if (comparison < 0)
            {
                min = mid + 1;
            }
            else
            {
                max = mid - 1;
            }
        }

        return new Tuple<int, int>(~min, counter);
    }
}

//Which returns a tuple with the item and a number of comparisons. 
//Here is how you can use it:

class Program
{
    static void Main(string[] args)
    {
        var numbers = new List<int>();
        numbers.AddRange(Enumerable.Range(0, 100000));

        var answer = numbers.BinarySearchWithCount(2);
        Console.WriteLine("item: " + answer.Item1);   // item: 2
        Console.WriteLine("count: " + answer.Item2);  // count: 15

    }
}
Community
  • 1
  • 1
oleksii
  • 35,458
  • 16
  • 93
  • 163
  • Hi, thanks for the answer but I'm having trouble piecing it together into a functioning program. Before C# which I started learning very recently I've only done programming in Real Basic which is much more simple. Would it be possible to get this in a functioning form which I could then study? If so, I would be forever in your debt because this has been driving me insane for over a week now :P – Matthew Morgan Oct 07 '12 at 22:08
  • @MatthewMorgan Sorry, my bet, I didn't learn how to copy-paste code from VS properly! That's it fixed: 2 lines added at the top. This shall work for .net 4 and up. Let me know if you need this for another version. – oleksii Oct 08 '12 at 16:59
  • I cannot thanks you enough, I find it so much easier to figure out how a program works with a full example. This has helped me a massive ammount with learning how to use class' which I have also been a little puzzled about :] – Matthew Morgan Oct 09 '12 at 09:40
0

Is this some kind of homework-task? The List<T>.BinarySearch Method does not provide such information.

If you want the number of comparisons you either have to write your own IComparer binary search or you still use the .NET method and calculate the counts from the length of the list and the position of the element.

anscheinbar
  • 288
  • 1
  • 6