web-dev-qa-db-fra.com

Recherche binaire d'un tableau trié

J'essaie de rechercher un tableau trié décroissant en utilisant ce code de recherche binaire. Cependant, une fois que je l'ai trié et que j'ai essayé de chercher, il ne renvoie aucun résultat, il ne s'agit que d'une icône de chargement qui ne disparaît jamais comme si elle avait une boucle infinie. Je ne sais pas quel est le problème car le code semble logique.

C'est aspx avec 4.0 framework, c #. Merci d'avance!

    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];

        }
9
Emmanuel Buckley

Il existe une recherche binaire dans la classe Array:

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

Pour un ordre décroissant, ceci peut être facilement accompli avec une ReverseComparer qui est facile à écrire comme:

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

Ensuite:

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

S'il s'agit d'un exercice académique et que vous devez utiliser une recherche personnalisée, cela ne s'appliquera bien sûr pas. S'il doit s'agir d'un algorithme personnalisé pour une classe, le problème est que vous devez sortir de la boucle une fois trouvé et que l'index est à mid, pas à 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;
        }
    }

Et en fait, je mettrais probablement un drapeau bool à la place pour garder l'algorithme pur et ne pas mélanger la recherche avec les préoccupations de sortie, cela facilitera également la tâche de savoir ce qui s'est passé si vous quittez la boucle avec non trouvé

    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";
20

Une balle dans l'obscurité:

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

Je soupçonne que vous sautez entre mi-1 et mi-1

1
n8wrl
//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);
     }
}
0
Jean

Cela a fonctionné pour moi

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;
}
0
dprotopopov

C'est un correct:

si target< mynumbers[mid], vous devez prendre dernier au milieu de 1, , car nous devons chercher dans la plage inférieure, c’est-à-dire du premier au milieu de 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;

            }
0
Ravindra Bagale
        int num = 2;
        int[] value = { 1, 2, 3, 4, 5, 6,7,8,9,10,11,12,13,14,15,16,17,18,19,20 };
        int s = 0;
        int e = value.Length - 1;
        int m = (s + e) / 2;
        bool find = false;
        do
        {
            if (value[m] == num)
            {
                Console.WriteLine("We have found the given number");
                find = true;
            }
            else if (num < value[m])
            {
                e = m - 1;
            }
            else 
            {
                s = m + 1;
            }
            m = (s + e) / 2;
        } while (find != true);
0
Elvis Sylejmani