Emmanuel Buckley
Emmanuel Buckley

Reputation: 161

Binary search of a sorted array

I am trying to search a descending sorted array using this binary search code. However, after I sort it, and try to search, it doesn't come back with any result, just a loading icon that never goes away as if it has an infinite loop. I'm not sure what the problem is because the code looks logical.

This is aspx with 4.0 framework, c#. Thanks in advance!

    protected void Button2_Click(object sender, EventArgs e)
    {
        String item = TextBox1.Text;
        int target = Convert.ToInt16(item);
        int mid, first = 0, last = mynumbers.Length - 1;

        //for a sorted array with descending values
        while (first<=last)
        {
            mid = (first + last) / 2;
            if (target < mynumbers[mid])
                first = mid + 1;
            if (target > mynumbers[mid])
                last = mid - 1;
            else
                Label11.Text = "Target " + item + " was found at index " + mynumbers[mid];

        }

Upvotes: 14

Views: 58810

Answers (7)

Ash K
Ash K

Reputation: 3651

Binary search using C# 12 in .NET 8.

public static class BinarySearcher
{
    public static int FindIndex(int[] sortedData, int item)
    {
        // leftIndex and rightIndex keep track of which part of the array you’ll search in.
        var leftIndex = 0;
        var rightIndex = sortedData.Length - 1;

        // While you haven’t narrowed it down to one element
        while (leftIndex <= rightIndex)
        {
            // Check the middle element
            var midIndex = (leftIndex + rightIndex) / 2;
            var guess = sortedData[midIndex];
            
            if (guess == item) return midIndex;

            // The guess was too high
            if (guess > item)
            {
                rightIndex = midIndex - 1;
            }
            // The guess was too low
            else
            {
                leftIndex = midIndex + 1;
            }
        }
        
        return -1; // The item does not exist.
    }
}

Tested using NUnit 3.

using NUnit.Framework;

public class BinarySearcherTests
{
    [Test]
    public void BinarySearcher_Finds_Item()
    {
        // Arrange
        int[] myList = [1, 3, 5, 7, 9];
        var myListItem = myList[3];
        // Act
        var searchedItemIndex = BinarySearcher.FindIndex(myList, myListItem);
        // Assert
        Assert.That(searchedItemIndex, Is.EqualTo(3));
    }

    [Test]
    public void BinarySearcher_Doesnt_Find_Item()
    {
        // Arrange
        int[] myList = [1, 3, 5, 7, 9];
        // Act
        var searchedItemIndex = BinarySearcher.FindIndex(myList, 10);
        // Assert
        Assert.That(searchedItemIndex, Is.EqualTo(-1));
    }
}

Upvotes: 0

Tural_M
Tural_M

Reputation: 1

public static object BinnarySearch(int[] array,int SearchKey)
    {
        int min = 0;
        int max = array.Length - 1;
        while (min <= max)
        {
            int mid = (min + max) / 2;
            if (SearchKey == array[mid])
            {
                return mid;
            }
            else if (SearchKey < array[mid])
            {
                max = mid - 1;
            }
            else
                min = mid + 1;
        }
        return "Not Found";
    }

Upvotes: -1

dprotopopov
dprotopopov

Reputation: 3

Its worked for me

public static int search(int[] arr, int value)
{
    Debug.Assert(arr.Length>0);
    var left = 0;
    var right = arr.Length - 1;

    while (((right - left)/2) > 0)
    {
        var middle = left + (right - left)/2;
        if (arr[middle] < value)
            left = middle + 1;
        else
            right = middle;
    }
    return arr[left] >= value ? left : right;
}

Upvotes: 0

Jean
Jean

Reputation: 1

//this works fine with these Test cases    
// has to check if (target == mynumbers[mid])    
// this is for an array with ascending order.
class Program
{

    static void Main(string[] args)
    {
        // TEST cases:
        // for 8: item 8 was not found
        // for 4: item 4 found at Position 3
        // for 1: item 1 found at position 0
        // for 0: item 0 was not found


        int target =8;
        int searchkey = target;

        int[] mynumbers = { 1, 2, 3, 4, 5 };

        int mid=0, first = 0, last = mynumbers.Length - 1;

        bool found = false;

        //for a sorted array with ascending values
        while (!found && first <= last)
        {
            mid = (first + last) / 2;

            if (target == mynumbers[mid])
                found = true;
            else
            {

                if (target > mynumbers[mid])
                {
                    first = mid + 1;
                }

                if (target < mynumbers[mid])
                {
                    last = mid - 1;
                }

            }

        }

        String foundmsg = found
            ? "Item " + searchkey + " was found at position " + mid
            : "Item " + searchkey + " was not found";
        Console.WriteLine(foundmsg);
     }
}

Upvotes: 0

Ravindra Bagale
Ravindra Bagale

Reputation: 17655

This is one correct :

if target< mynumbers[mid] then you have to take last to mid-1, because we have to search in lower range i.e. first to mid-1

while (first<=last)
        {
            mid = (first + last) / 2;
            if (target == mynumbers[mid])
            Label11.Text = "Target " + item + " was found at index " + mynumbers[mid];

            else if (target < mynumbers[mid])
                last = mid - 1;
            else (target > mynumbers[mid])
                first = mid + 1;

            }

Upvotes: 1

James Michael Hare
James Michael Hare

Reputation: 38397

There is a binary search in the Array class:

int index = Array.BinarySearch(mynumbers, target);

For descending order, this can be easily accomplished with a ReverseComparer which is easy to write like:

    public class ReverseComparer<T> : IComparer<T>
    {
        public int Compare(T x, T y)
        {
            return Comparer<T>.Default.Compare(y, x);
        }
    }

Then:

int index = Array.BinarySearch(numbers, 7, new ReverseComparer<int>());

If this is an academic exercise and you must use a custom search, of course, this won't apply. If it's got to be a custom algorithm for a class, then the problems are that you must break out of the loop when found, and the index is at mid, not at mynumbers[mid]:

    //for a sorted array with descending values
    while (first<=last)
    {
        mid = (first + last) / 2;

        if (target < mynumbers[mid])
        {
            first = mid + 1;
        }

        if (target > mynumbers[mid])
        {
            last = mid - 1;
        }

        else
        {
            // the index is mid, not mynumbers[mid], and you need to break here
            // once found or it's an infinite loop once it finds it.
            Label11.Text = "Target " + item + " was found at index " + mid;
            break;
        }
    }

And actually, I'd probably set a bool flag instead to keep the algorithm pure and not mix the find with the output concerns, this will also make it easier to tell what happened if you exit the loop with not found:

    bool found = false;

    //for a sorted array with descending values
    while (!found && first<=last)
    {
        mid = (first + last) / 2;

        if (target < mynumbers[mid])
        {
            first = mid + 1;
        }

        if (target > mynumbers[mid])
        {
            last = mid - 1;
        }

        else
        {
            // You need to stop here once found or it's an infinite loop once it finds it.
            found = true;
        }
    }

    Label11.Text = found 
        ? "Item " + item + " was found at position " + mid
        : "Item " + item + " was not found";

Upvotes: 24

n8wrl
n8wrl

Reputation: 19765

Shot in the dark:

if (target < mynumbers[mid]) 
   first = mid + 1; 
else if (target > mynumbers[mid]) 
   last = mid - 1; 
else 
{
    ....
    break;
}

I suspect you're bouncing back and forth between mid+1 and mid-1

Upvotes: 1

Related Questions