Üdvözöljük
Ebben a cikkben megtudhatja, hogyan működik a bináris keresés algoritmus a kulisszák mögött, és hogyan tudja megvalósítani a Pythonban.
Különösen megtanulja:
- Hogyan működik az algoritmus a színfalak mögött, hogy megtalálja a célelemet.
- Hogyan működik Python-implementációja soronként.
- Miért nagyon hatékony algoritmus a lineáris kereséshez képest?
- Előnyei és követelményei.
Kezdjük! ✨
? Bevezetés a bináris keresésbe
Ezt az algoritmust arra használják, hogy egy rendezett sorrendben elemet találjon (például: listát, duplát vagy karakterláncot).
Követelmények
A bináris keresési algoritmus szekvenciához való alkalmazásához a szekvenciát már növekvő sorrendben kell rendezni. Ellenkező esetben az algoritmus nem fogja megtalálni a helyes választ. Ha mégis megtörténik, akkor véletlenszerűen történik.
? Tipp: A bináris keresés alkalmazása előtt rendezheti a sorrendet az Ön igényeinek megfelelő rendezési algoritmussal.
Bemenet és kimenet
A függvényként megvalósított algoritmusnak szüksége van ezekre az adatokra:
- Rendezett elemsorozat (például: lista, páros, karakterlánc).
- A keresett célelem.
Visszaadja a keresett elem indexét , ha megtalálható. Ha az elem nem található, akkor -1 adódik vissza.
Hatékonyság
Nagyon hatékony a lineáris kereséshez képest (elem keresése egyesével, az elsőtől kezdve), mert minden lépésnél képesek vagyunk a lista felét "elvetni".
Kezdjük el merülni ezt az algoritmust.
? Visual Walkthrough
A Binary Search algoritmust erre a listára alkalmazzuk:

? Tipp: Vegye figyelembe, hogy a lista már rendezve van. Az indexeket vizuális referenciaként tartalmazta.
Cél
Meg akarjuk találni a 67 egész indexét .
Intervallum
Tegyünk úgy, mintha mi lennénk az algoritmus. Hogyan kezdjük el a folyamatot?
Kezdjük azzal, hogy kiválasztjuk az intervallum két határát, ahol keresni akarunk. Meg akarjuk keresni a teljes listát, ezért 0
alsó indexként 5
az indexet , felső határként pedig az indexet választjuk :

Középső elem
Most meg kell találnunk a középső elem indexét ebben az intervallumban. Ezt úgy tesszük, hogy összeadjuk az alsó és a felső határt, és az eredményt elosztjuk 2-vel egész osztás segítségével.
Ebben az esetben (0 + 5)//2
is 2
, mert az eredmény 5/2
az, 2.5
és osztás levágja a tizedes rész.
Tehát a középső elem a 2. indexen található , a középső elem pedig a 6. szám :

Összehasonlítások
Most el kell kezdenünk összehasonlítani a középső elemet a célelemmel, hogy lássuk, mit kell tennünk ezután.
Kérünk:
A középső elem megegyezik-e azzal az elemmel, amelyet keresünk?
6 == 67 # False
Nem, nem az.
Tehát azt kérdezzük:
A középső elem nagyobb, mint a keresett elem?
6 > 67 # False
Nem, nem az.
Tehát a középső elem kisebb, mint a keresett elem.
6 < 67 # True
Elveti az elemeket
Mivel a lista már rendezve van, ez valami rendkívül fontosat mond nekünk. Azt mondja nekünk, hogy "eldobhatjuk" a lista alsó felét, mert tudjuk, hogy az összes elem, amely a középső elem elé kerül, kisebb lesz, mint a keresett elem, tehát a célelemünk nincs ott.

Újrakezdés - Válassza ki a határokat
Mi lesz a következő, amit csinálunk? Elvetettük az elemeket, és a ciklus ismétlődik.
Meg kell választanunk az új intervallum határait (lásd alább). De vegye figyelembe, hogy a felső határ sértetlen marad, és csak az alsó határ változik meg.

Ennek oka, hogy a keresett elem a lista felső felében lehet. A felső határt érintetlenül tartják, és az alsó határt megváltoztatják, hogy "összezsugorítsák" az intervallumot egy olyan intervallumra, ahol a célelemünk megtalálható.
? Tipp: Ha a középső elem nagyobb lett volna, mint a keresett elem, akkor a felső határ megváltozott, és az alsó határ érintetlen maradt. Így elvetnénk a lista felső felét, és folytatnánk a keresést az alsó felében.
Középső elem
Most meg kell találnunk a középső elem indexét úgy, hogy hozzáadjuk az alsó határt a felső határhoz, és az eredményt elosztjuk 2-vel egész osztás segítségével.
Az eredmény (3+5)//2
az 4
, hogy a középső elem az indexen található, 4
a középső pedig 67 .

Összehasonlítások
Kérünk:
A középső elem megegyezik-e azzal az elemmel, amelyet keresünk?
67 == 67 # True
Igen, ez az! Tehát megtaláltuk az elemet a 4. indexen . A 4. érték visszaadódik, és az algoritmus sikeresen befejeződött.
? Tipp: Ha az elemet nem találták meg, a folyamat addig folytatódott, amíg az intervallum már nem volt érvényes. Ha az elemet nem találták meg a teljes listában, akkor -1-et adtak volna vissza.
? Kód áttekintés
Most, hogy van egy vizuális megérzése arról, hogy az algoritmus hogyan működik a színfalak mögött, merüljünk el az iteratív Python megvalósításba soronkénti elemzéssel:
def binary_search(data, elem): low = 0 high = len(data) - 1 while low elem: high = middle - 1 else: low = middle + 1 return -1
Fejléc
Itt van a függvény fejléc:
def binary_search(data, elem):
Két érvre van szükség:
- Az elemek sorrendje (például: lista, páros vagy karakterlánc).
- Az elem, amelyet meg akarunk találni.
Kezdeti időköz
A következő sor meghatározza a kezdeti alsó és felső határt:
low = 0 high = len(data) - 1
A kezdeti alsó határ index 0
, a kezdeti felső határ pedig a sorozat utolsó indexe.
Hurok
Megismételjük a folyamatot, amíg érvényes időköz van, míg az alsó határ kisebb vagy egyenlő a felső határral.
while low <= high:
? Tipp: Ne feledje, hogy a határok indexek.
Középső elem
Minden iterációnál meg kell találnunk a középső elem indexét. Ehhez hozzáadjuk az alsó és a felső határt, és az eredményt elosztjuk 2-vel egész osztás segítségével.
middle = (low + high)//2
? Tipp: Egész számfelosztást használunk, ha a lista vagy intervallum páros számú elemet tartalmaz. Például, ha a lista már 6 elemeket és nem használtuk osztás, middle
lenne az eredménye (0 + 5)/2
, ami 2.5
. Az index nem lehet lebegő, ezért megcsonkítjuk a tizedes részt a használatával, //
és kiválasztjuk az elemet az indexen 2
.
Összehasonlítások
Ezekkel a feltételekkel (lásd alább) a középső elem értékétől függően határozzuk meg, hogy mit tegyünk data[middle]
. Összehasonlítjuk a keresett célelemmel.
if data[middle] == elem: return middle elif data[middle] > elem: high = middle - 1 else: low = middle + 1
Három lehetőség van:
- Ha a középső elem megegyezik a keresett elemmel, akkor azonnal visszaadjuk az indexet, mert megtaláltuk az elemet.
if data[middle] == elem: return middle
- Ha a középső elem nagyobb, mint a keresett elem, akkor hozzárendeljük a felső határt, mert tudjuk, hogy a célelem a lista alsó felében található.
elif data[middle] > elem: high = middle - 1
- Egyébként az egyetlen lehetőség megmaradt, hogy a középső elem kisebb, mint a keresett elem, ezért az alsó határt újból kijelöljük, mert tudjuk, hogy a célelem a lista felső felében található.
else: low = middle + 1
Az elem nem található
Ha a ciklus az elem megkeresése nélkül fejeződik be, akkor a -1 értéket adja vissza.
return -1
és megvan a Bináris keresés algoritmus végleges megvalósítása:
def binary_search(data, elem): low = 0 high = len(data) - 1 while low elem: high = middle - 1 else: low = middle + 1 return -1
? Különleges esetek
Íme néhány olyan különleges eset, amelyet az algoritmus használatának megkezdése során találhat meg:
Ismételt elemek
Ha a keresett elem megismétlődik a szekvenciában, a visszaküldött index az elemek számától és az algoritmus által a szekvencián végrehajtott műveletsorozattól függ.
>>> >>> b = [2, 2, 3, 6, 7, 7] >>> binary_search(b, 7) 4
Az elem nem található
Ha az elem nem található, akkor -1 adódik vissza.
>>> b = [2, 2, 3, 6, 7, 7] >>> binary_search(b, 8) -1
Üres szekvencia
Ha a sorozat üres, -1-et adunk vissza.
>>> b = [] >>> binary_search(b, 8) -1
Válogatás nélküli sorrend
Ha a sorrend nincs rendezve, akkor a válasz nem lesz helyes. A helyes index megszerzése tiszta véletlen, és annak oka lehet az elemek sorrendje a sorrendben és az algoritmus által végrehajtott műveletek sorrendje.
Ez a példa a helyes eredményt adja vissza:
>>> b = [5, 7, 3, 0, -9, 2, 6] >>> binary_search(b, 6) 6
De ez nem:
>>> b = [5, 7, 3, 0, -9, 2, 10, 6] >>> binary_search(b, 6) -1
? Tipp: Gondolja át, miért adja vissza az első példa a helyes eredményt. Tipp: Pontos véletlen, hogy az elemek sorrendje miatt az algoritmus eléri a helyes indexet, de a lépésenkénti folyamat kiértékeli 0
, majd 2
végül 6
. Ebben a konkrét esetben az adott elem esetében a megfelelő index akkor is megtalálható, ha a sorrend nincs rendezve.
? Összetettebb példa
Most, hogy jobban ismeri az algoritmust és annak Python-implementációját, itt van egy összetettebb példa:
A bináris keresés segítségével meg akarjuk találni a 45 elem indexét ebben a listában:

Első iteráció
Az alsó és a felső határ kiválasztása:

A középső elem ( 26 ) van kiválasztva:

De a középső elem ( 26 ) nem az az elem, amelyet keresünk, kisebb, mint 45 :

Második iteráció
Így eldobhatunk minden elemet, amely kisebb, mint a középső elem, és új határokat választhatunk ki. Az új alsó határ ( 27 ) az előző középső elemtől jobbra található elem:

? Tipp: Ne feledje, hogy a lista már rendezve van.
Az új középső elem ( 30 ) van kiválasztva:

A középső ( 30 ) elem nem az az elem, amelyet keresünk, kisebb, mint 45 :

Harmadik iteráció
A 30- nál kisebb vagy azzal egyenlő elemeket eldobhatjuk, amelyeket még nem dobtak el. Az alsó határérték 32-re frissül :

Itt van egy érdekes esetünk: a középső elem az aktuális intervallum egyik határa, mert (7+8)//2
az 7
.

A középső ( 32 ) elem nem az az elem, amelyet keresünk ( 45 ), hanem kisebb.

Negyedik iteráció
A 32- nél kisebb vagy azzal egyenlő elemeket eldobhatjuk, amelyeket még nem dobtak el.
Itt van egy másik nagyon érdekes esetünk: az intervallumnak csak egy eleme van.

? Tipp: Ez az intervallum azért érvényes, mert ezt a feltételt írtuk while high <= low:
, amely olyan intervallumokat tartalmaz, amelyekben az alsó határ indexe megegyezik a felső határ indexével.
A középső elem az egyetlen elem az intervallumban, mert így (8+8)//2
van 8
, tehát a középső elem mutatója 8 , a középső pedig 45 .

Most a középső elem az az elem, amelyet keresünk, 45 :

Tehát a 8. érték (az index) visszatér:
>>> binary_search([1, 3, 7, 15, 26, 27, 30, 32, 45], 45) 8
? Extra gyakorlat
Ha szeretne még egy kis gyakorlatot ezzel az algoritmussal, próbálja meg elmagyarázni, hogyan működik az algoritmus a színfalak mögött, amikor ezt a listát alkalmazza a 90-es egész szám megkeresésére :
[5, 8, 15, 26, 38, 56]
- Mi történik lépésről lépésre?
- Milyen értéket adunk vissza?
- Megtalálták az elemet?
Nagyon remélem, hogy tetszett a cikkem, és hasznosnak találta. Most megvalósíthatja a bináris keresés algoritmust a Pythonban. Nézze meg a "Python keresési és rendezési algoritmusok: gyakorlati megközelítés" című online tanfolyamomat. Kövess a Twitteren. ⭐️