web-dev-qa-db-fra.com

Algorithme de recherche binaire en python

J'essaie d'implémenter la recherche binaire en python et je l'ai écrit comme suit. Cependant, je ne peux pas le faire arrêter chaque fois que needle_element est plus grand que le plus grand élément du tableau.

Pouvez vous aider? Merci.

def binary_search(array, needle_element):
    mid = (len(array)) / 2
    if not len(array):
        raise "Error"
    if needle_element == array[mid]:
        return mid
    Elif needle_element > array[mid]:
        return mid + binary_search(array[mid:],needle_element)
    Elif needle_element < array[mid]:
        return binary_search(array[:mid],needle_element)
    else:
        raise "Error"
10
AbdulFattah Popoola

Dans le cas où needle_element > array[mid], vous transmettez actuellement array[mid:] à l'appel récursif. Mais vous savez que array[mid] est trop petit, vous pouvez donc passer array[mid+1:] à la place (et ajuster l'index renvoyé en conséquence).

Si l'aiguille est plus grande que tous les éléments du tableau, cette procédure vous donnera éventuellement un tableau vide et une erreur sera générée comme prévu.

Remarque: la création d'un sous-tableau à chaque fois entraînera de mauvaises performances pour les grands tableaux. Il vaut mieux passer dans les limites du tableau à la place.

8
interjay

Il serait bien préférable de travailler avec les index lower et upper comme Lasse V. Karlsen suggéraient dans un commentaire à la question.

Ce serait le code:

def binary_search(array, target):
    lower = 0
    upper = len(array)
    while lower < upper:   # use < instead of <=
        x = lower + (upper - lower) // 2
        val = array[x]
        if target == val:
            return x
        Elif target > val:
            if lower == x:   # these two are the actual lines
                break        # you're looking for
            lower = x
        Elif target < val:
            upper = x
  • lower < upper s'arrêtera une fois que vous aurez atteint le plus petit nombre (en partant de la gauche)
  • if lower == x: break s'arrêtera une fois que vous avez atteint le nombre le plus élevé (à droite)

Exemple:

>>> binary_search([1,5,8,10], 5)   # return 1
1
>>> binary_search([1,5,8,10], 0)   # return None
>>> binary_search([1,5,8,10], 15)  # return None
14
Rik Poggi

array [mid:] crée une nouvelle sous-copie à chaque fois que vous l'appelez = slow. Vous utilisez également la récursivité, qui, en Python, est lente.

Essaye ça:

def binarysearch(sequence, value):
    lo, hi = 0, len(sequence) - 1
    while lo <= hi:
        mid = (lo + hi) // 2
        if sequence[mid] < value:
            lo = mid + 1
        Elif value < sequence[mid]:
            hi = mid - 1
        else:
            return mid
    return None
6
Ecir Hana

Pourquoi ne pas utiliser le module bissect? Il devrait faire le travail dont vous avez besoin - moins de code à maintenir et à tester.

6
Pierce

Vous pouvez améliorer votre algorithme comme le suggèrent les autres, mais voyons d'abord pourquoi cela ne fonctionne pas:

Vous êtes bloqué dans une boucle parce que si needle_element > array[mid], vous incluez l'élément mid dans le tableau divisé en deux que vous recherchez ensuite. Donc si aiguille n’est pas dans le tableau, vous allez éventuellement chercher un tableau de longueur un pour toujours. Passez plutôt array[mid+1:] (c'est légal même si mid+1 n'est pas un index valide) et vous appellerez éventuellement votre fonction avec un tableau de longueur zéro. Donc, len(array) == 0 signifie "non trouvé", pas une erreur. Manipulez-le de manière appropriée.

2
alexis
def binary_search(array, target):
    low = 0
    mid = len(array) / 2
    upper = len(array)

    if len(array) == 1:
        if array[0] == target:
            print target
            return array[0]
        else:
            return False
    if target == array[mid]:
        print array[mid]
        return mid
    else:
        if mid > low:
            arrayl = array[0:mid]
            binary_search(arrayl, target)

        if upper > mid:
            arrayu = array[mid:len(array)]
            binary_search(arrayu, target)

if __== "__main__":
    a = [3,2,9,8,4,1,9,6,5,9,7]
    binary_search(a,9)
1
user1342336

Toutes les réponses ci-dessus sont vraies, mais je pense que cela aiderait à partager mon code 

def binary_search(number):
numbers_list = range(20, 100)
i = 0
j = len(numbers_list)
while i < j:
    middle = int((i + j) / 2)
    if number > numbers_list[middle]:
        i = middle + 1
    else:
        j = middle
return 'the index is '+str(i)
0
Maysara Alhindi

Utilisation de la récursivité:

def binarySearch(arr,item):
    c = len(arr)//2
    if item > arr[c]:
       ans = binarySearch(arr[c+1:],item)
       if ans:
          return binarySearch(arr[c+1],item)+c+1
    Elif item < arr[c]:
       return binarySearch(arr[:c],item)
    else:
       return c

binarySearch([1,5,8,10,20,50,60],10)
0
Aysun

Sans les index inférieur/supérieur, cela devrait également faire:

def exists_element(element, array):
    if not array:
        yield False

    mid = len(array) // 2
    if element == array[mid]:
        yield True
    Elif element < array[mid]:
        yield from exists_element(element, array[:mid])
    else:
        yield from exists_element(element, array[mid + 1:])
0
nettrino

C'est une solution récursive, je pense que c'est plus propre que de copier des tableaux partiels et de garder une trace des index pour le retour

def binarySearch(elem, arr):
    # return the index at which elem lies, or return false
    # if elem is not found
    # pre: array must be sorted
    return binarySearchHelper(elem, arr, 0, len(arr) - 1)

def binarySearchHelper(elem, arr, start, end):
    if start > end:
        return False
    mid = (start + end)//2
    if arr[mid] == elem:
        return mid
    Elif arr[mid] > elem:
        # recurse to the left of mid
        return binarySearchHelper(elem, arr, start, mid - 1)
    else:
        # recurse to the right of mid
        return binarySearchHelper(elem, arr, mid + 1, end)
0
Sean

Il retourne l'index de la clé dans le tableau en utilisant récursif.

round () est une fonction qui convertit float en entier, rend le code rapide et va au cas attendu [O (logn)].

A=[1,2,3,4,5,6,7,8,9,10]
low = 0
hi = len(A)
v=3
def BS(A,low,hi,v):
    mid = round((hi+low)/2.0)
    if v == mid:
        print ("You have found dude!" + " " + "Index of v is ", A.index(v))
    Elif v < mid:
        print ("Item is smaller than mid")
        hi = mid-1
        BS(A,low,hi,v)
    else :
        print ("Item is greater than mid")
        low = mid + 1
        BS(A,low,hi,v)
BS(A,low,hi,v)
0
Anıl Selvi

Si vous effectuez une recherche binaire, je suppose que le tableau est trié. Si cela est vrai, vous devriez pouvoir comparer le dernier élément du tableau au needle_element. Comme le dit la pieuvre, cela peut être fait avant le début de la recherche.

0
macduff

Vous pouvez simplement vérifier que needle_element est dans les limites du tableau avant de commencer. Cela le rendra plus efficace aussi, puisque vous n’aurez pas à faire plusieurs étapes pour arriver à la fin.

if needle_element < array[0] or needle_element > array[-1]:
    # do something, raise error perhaps?
0
Donald Miner