Serwis Edukacyjny w I-LO w Tarnowie Materiały dla uczniów liceum |
Wyjście Spis treści Wstecz Dalej Autor artykułu: mgr Jerzy Wałaszek |
©2024 mgr Jerzy Wałaszek |
ProblemW uporządkowanym rosnąco zbiorze Z należy wyszukać element o wartości (o kluczu) k. |
Postąpimy w sposób następujący.
Wyznaczymy element środkowy zbioru. Sprawdzimy, czy jest on poszukiwanym elementem. Jeśli tak, to element został znaleziony i możemy zakończyć poszukiwania. Jeśli nie, to poszukiwany element jest albo mniejszy od elementu środkowego, albo większy. Ponieważ zbiór jest uporządkowany, to elementy mniejsze od środkowego będą leżały w pierwszej połówce zbioru, a elementy większe w drugiej połówce. Zatem w następnym obiegu zbiór możemy zredukować do pierwszej lub drugiej połówki – jest w nich o połowę mniej elementów. Mając nowy zbiór postępujemy w sposób identyczny – znów wyznaczamy element środkowy, sprawdzamy, czy jest poszukiwanym elementem. Jeśli nie, to zbiór dzielimy znów na dwie połowy – elementy mniejsze od środkowego i elementy większe od środkowego. Poszukiwania kontynuujemy w odpowiedniej połówce zbioru aż znajdziemy poszukiwany element lub do chwili, gdy po podziale połówka zbioru nie zawiera dalszych elementów.
Ponieważ w każdym obiegu pętli algorytm redukuje liczbę elementów o połowę,
to jego klasa złożoności obliczeniowej jest równa
Oczywiście algorytm wyszukiwania liniowego może być zastosowany dla dowolnego zbioru. Nasz algorytm można stosować tylko i wyłącznie w zbiorze uporządkowanym. Ze względu na podział zbioru na kolejne połówki, ćwierci itd. algorytm nosi nazwę wyszukiwania binarnego (ang. binary search).
Musimy uściślić sposób podziału zbioru na coraz mniejsze fragmenty. Zbiór
Z odwzorowujemy w tablicy
Z składającej się z n elementów ponumerowanych kolejno
ip – indeks pierwszego elementu zbioru ik – indeks końcowego elementu zbioru
indeksy elementów tablicy Z
|
0 |
1 |
2 |
… |
n-2
|
n-1
|
|
indeksy początku i końca |
ip |
|
|
|
|
ik |
|
Indeksy ip i ik określają
obszar zbioru w tablicy Z. Początkowo będą oczywiście równe:
Na podstawie tych dwóch indeksów obliczamy indeks elementu środkowego isr:
isr = [(ip + ik) / 2]
Jeśli zbiór Z jest uporządkowany rosnąco, to:
Z[0]
|
Z[1]
|
… |
Z[isr-1] |
Z[isr] |
Z[isr+1] |
… |
Z[n-2] |
Z[n-1] |
ip |
← |
isr |
→ |
ik |
||||
elementy ≤ Z[isr] | elementy ≥ Z [isr] |
Zatem w przypadku, gdy
Jeśli k > Z[isr], to
przechodzimy do drugiej połówki o indeksach
K01: p ← -1 ; zakładamy, iż k nie występuje w zbiorze K02: Dopóki ip ≤ ik, ; w pętli poszukujemy wykonuj kroki K02…K10 ; elementu o wartości k K03: isr = [(ip + ik) / 2] ; wyznaczamy element środkowy K04: Jeśli k ≠ Z[isr], to idź do kroku K07 K05: p ← isr ; element znaleziony, kończymy K06: Idź do kroku K11 K07: Jeśli k < Z[isr], ; wybieramy odpowiednią połówkę to idź do kroku K10 ; zbioru na dalsze poszukiwania K08: ip ← isr + 1 ; k > Z[isr] → druga połówka K09: Następny obieg pętli K02 K10: ik ← isr - 1 ; k < Z [isr] → pierwsza połówka K11: Zakończ z wynikiem p
Uwaga: Zanim uruchomisz program, przeczytaj wstęp do tego artykułu, w którym wyjaśniamy funkcje tych programów oraz sposób korzystania z nich. |
Program wypełnia tablicę 100
elementową Z liczbami naturalnymi w taki sposób, aby powstał z nich ciąg rosnący. Następnie generuje liczbę pseudolosową
k z zakresu |
Pascal// Wyszukiwanie binarne // Data: 7.05.2008 // (C)2020 mgr Jerzy Wałaszek //--------------------------- program prg; const N = 100; var Z : array [0..N - 1] of integer; i, ip, ik, isr, k, L, p : integer; begin randomize; // wypełniamy tablicę Z[] Z[0] := random(5); for i := 1 to N - 1 do Z[i] := Z[i - 1] + random(5); // generujemy klucz k k := Z[0] + random(Z[N - 1] - Z[0] + 1); // poszukujemy binarnie elementu k L := 0; p := -1; ip := 0; ik := N - 1; while ip <= ik do begin inc(L); isr := (ip + ik) shr 1; if Z[isr] = k then begin p := isr; break; end else if k < Z[isr] then ik := isr - 1 else ip := isr + 1; end; // wyświetlamy wyniki write(k, ' : '); if p >= 0 then write(p) else write('BRAK'); writeln(' : obiegi = ', L); writeln; for i := 0 to N - 1 do begin write (Z[i]:3); if p = i then write ('<') else write (' '); end; writeln; writeln; end. |
// Wyszukiwanie binarne // Data: 7.05.2008 // (C)2020 mgr Jerzy Wałaszek //--------------------------- #include <iostream> #include <iomanip> #include <cstdlib> #include <ctime> using namespace std; const int N = 100; int main() { int Z[N], i, ip, ik, isr, k, L, p; srand(time(NULL)); // wypełniamy tablicę Z[] Z[0] = rand() % 5; for(i = 1; i < N; i++) Z[i] = Z[i - 1] + (rand() % 5); // generujemy klucz k k = Z[0] + (rand() % (Z[N - 1] - Z[0] + 1)); // poszukujemy binarnie elementu k p = -1; L = ip = 0; ik = N - 1; while(ip <= ik) { L++; isr = (ip + ik) >> 1; if(Z[isr] == k) { p = isr; break; } else if(k < Z[isr]) ik = isr - 1; else ip = isr + 1; } // wyświetlamy wyniki cout << k << " : "; if(p >= 0) cout << p; else cout << "BRAK"; cout << " : obiegi = " << L << endl << endl; for(i = 0; i < N; i++) { cout << setw(3) << Z[i]; if(p == i) cout << "<"; else cout << " "; } cout << endl << endl; return 0; } |
Basic' Wyszukiwanie binarne ' Data: 7.05.2008 ' (C)2020 mgr Jerzy Wałaszek '--------------------------- Const N = 100 Dim As Integer Z(N-1), i, ip, ik, isr, k, L, p Randomize ' wypełniamy tablicę Z[] Z(0) = Cint(Rnd * 4) For i = 1 To N - 1 Z(i) = Z(i - 1) + Cint(Rnd * 4) Next ' generujemy klucz k k = Z(0) + Cint(Rnd * (Z(N - 1) - Z(0))) ' poszukujemy binarnie elementu k L = 0: p = -1: ip = 0: ik = N - 1 While ip <= ik L += 1 isr = (ip + ik) Shr 1 If Z(isr) = k Then p = isr: Exit While Elseif k < Z(isr) Then ik = isr - 1 Else ip = isr + 1 End If Wend ' wyświetlamy wyniki Print k;" : "; If p >= 0 Then Print p;: Else Print "BRAK"; Print " : obiegi = ";L Print For i = 0 To N - 1 Print Using "###";Z(i); If p = i Then Print "<";: Else Print " "; Next Print Print End |
Python
(dodatek)# Wyszukiwanie binarne # Data: 27.02.2024 # (C)2024 mgr Jerzy Wałaszek #--------------------------- import random N = 100 # Liczba elementów Z = [] # Tablica # wypełniamy tablicę Z[] Z.append(random.randrange(5)) for i in range(1,N): Z.append(Z[i-1] + random.randrange(5)) # generujemy klucz k k = random.randrange(Z[0],Z[N-1] + 1) # poszukujemy binarnie elementu k L,p,ip,ik = 0,-1,0,N - 1 while ip <= ik: L += 1 isr = (ip + ik) >> 1 if Z[isr] == k: p = isr break elif k < Z[isr]: ik = isr - 1 else: ip = isr + 1 # wyświetlamy wyniki print(k,": ", end="") if p >= 0: print(p, end="") else: print("BRAK", end="") print(" : obiegi =",L) print() for i in range(N): print("%3d" % Z[i], end="") if p == i: print("<", end="") else: print(" ", end="") print() print() |
Wynik: |
6 : BRAK : obiegi = 6 0 0 0 3 5 5 9 13 15 16 18 22 24 26 30 33 37 41 43 47 47 47 49 52 55 56 56 58 58 58 62 66 66 70 74 74 75 75 75 77 80 84 86 86 88 90 93 94 94 98 100 102 106 108 110 111 115 117 118 119 120 120 121 124 125 127 131 131 135 139 142 145 146 146 146 146 146 148 152 155 158 158 159 159 161 165 168 169 169 172 174 177 179 182 186 186 187 187 188 190 192 : 88 : obiegi = 6 1 3 7 8 11 14 14 14 16 19 19 22 25 28 28 28 31 32 34 36 39 39 43 46 47 47 51 51 52 56 60 64 67 70 72 74 76 78 79 83 86 89 89 91 92 92 92 95 95 96 97 98 101 104 105 108 109 112 115 117 121 125 125 126 128 131 135 137 139 141 144 147 151 151 154 158 159 163 167 169 173 177 181 183 185 185 186 188 192<194 198 200 204 208 208 209 209 209 209 210 |
Zespół Przedmiotowy Chemii-Fizyki-Informatyki w I Liceum Ogólnokształcącym im. Kazimierza Brodzińskiego w Tarnowie ul. Piłsudskiego 4 ©2024 mgr Jerzy Wałaszek |
Materiały tylko do użytku dydaktycznego. Ich kopiowanie i powielanie jest dozwolone
pod warunkiem podania źródła oraz niepobierania za to pieniędzy.
Pytania proszę przesyłać na adres email:
Serwis wykorzystuje pliki cookies. Jeśli nie chcesz ich otrzymywać, zablokuj je w swojej przeglądarce.
Informacje dodatkowe.