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];
}
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";
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
//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);
}
}
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;
}
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;
}
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);