|
Grafy a tabuľky |
Binárne vyhľadávanie
|
Priemerné počty porovnaní vybraných implementácií |
//binarne vyhladavanie zadaneho prvku "hladany" pomocou cyklu while
//pole musi byt usporiadane vzostupne (na zaciatku pola je prvok s najmensou hodnotou)
//funkcia vracia index zadaneho prvku v poli (v pripade neuspechu vyhladavania vracia -1)
template < class T, int velkost_ >
int CPole < T, velkost_ > ::najdi_bin_cykl_index(T hladany){
int lavy_o=0;
int pravy_o=velkost_-1;
while(++p_a_porovnani_ && lavy_o <= pravy_o){
++p_a_cyklov_;
int stred=(lavy_o + pravy_o)/2;
if (++p_b_porovnani_ && pole_[stred] < hladany) lavy_o=stred+1;
else if(++p_b_porovnani_ && pole_[stred] > hladany) pravy_o=stred-1;
else return stred;
}
return -1;
} |
Počet porovnaní, cyklov a času trvania algoritmu pre úspešné vyhľadávanie. |
počet prvkov v poli |
p_a_porovnani_ |
p_b_porovnani_ |
p_a_cyklov_ |
čas |
10 |
2,900 |
4,600 |
2,900 |
0,0739 |
100 |
5,800 |
8,990 |
5,800 |
0,1370 |
1.000 |
8,987 |
13,93 |
8,987 |
0,1742 |
10.000 |
12,36 |
18,82 |
12,36 |
0,2227 |
100.000 |
15,69 |
23,84 |
15,69 |
0,2742 |
|
Z predchádzajúcej tabuľky môžeme vidieť, že počet vykonaných cyklov už nerastie spolu s narastajúcim vstupným poľom lineárne. Ako bolo spomenuté, v priemernom úspešnom vyhľadávaní je prvok nájdený v predposlednom cykle delenia poľa na polovicu. Platí teda, že počet cyklov je približne (log(2) n)-1. Presný počet porovnaní závisí od toho v akom poradí sú zapísané v implementácii podmienky pre pokračovanie vyhľadávania v niektorej z polovíc poľa. |
|
Počet porovnaní, cyklov a času trvania algoritmu pre neúspešné vyhľadávanie s p=0,9. |
počet prvkov v poli |
p_a_porovnani_ |
p_b_porovnani_ |
p_a_cyklov_ |
čas |
10 |
4,200 |
5,100 |
3,400 |
0,0999 |
100 |
7,560 |
9,780 |
6,600 |
0,1557 |
1.000 |
10,81 |
14,81 |
9,902 |
0,2061 |
10.000 |
14,18 |
19,74 |
13,27 |
0,2577 |
100.000 |
17,58 |
24,75 |
16,61 |
0,3120 |
|
Keďže pri úspešnom vyhľadávaní závisel počet cyklov algoritmu od veľkosti vstupného poľa logaritmicky, nebude tomu inak ani pri neúspešnom vyhľadávaní. Príde však k drobnej odchýlke. Zatiaľ čo pri úspešnom vyhľadávaní sa algoritmus skončil väčšinou po (log(2) n)-1 cykloch, teraz bude väčšinou potrebovať približne (log(2) n) cyklov. Musí sa totiž dostať až do najväčšej hĺbky v pomyselnom strome a až potom, keď bude ľavý okraj väčší ako pravý, skonči neúspechom. |
|
|
//binarne vyhladavanie zadaneho prvku "hladany" pomocou rekurzie
//pole musi byt usporiadane vzostupne (na zaciatku pola je prvok s najmensou hodnotou)
//funkcia vracia index zadaneho prvku v poli (v pripade neuspechu vyhladavania vracia -1)
template < class T, int velkost_ >
int CPole < T, velkost_ > ::najdi_bin_rek_index(int lavy_o, int pravy_o, T hladany){
if (++p_a_porovnani_ && lavy_o <= pravy_o){
++p_a_cyklov_;
int stred=(lavy_o + pravy_o)/2;
if (++p_b_porovnani_ && pole_[stred] < hladany)
return najdi_bin_rek_index(stred+1, pravy_o, hladany);
else if (++p_b_porovnani_ && pole_[stred] > hladany)
return najdi_bin_rek_index(lavy_o, stred-1, hladany);
else return stred;
}
return -1;
} |
Počet porovnaní, cyklov a času trvania algoritmu pre úspešné vyhľadávanie. |
počet prvkov v poli |
p_a_porovnani_ |
p_b_porovnani_ |
p_a_cyklov_ |
čas |
10 |
2,900 |
4,600 |
2,900 |
0,1424 |
100 |
5,800 |
8,990 |
5,800 |
0,3117 |
1.000 |
8,987 |
13,93 |
8,987 |
0,4800 |
10.000 |
12,36 |
18,82 |
12,36 |
0,6663 |
100.000 |
15,69 |
23,84 |
15,69 |
0,8765 |
|
Z predchádzajúcej tabuľky môžeme vidieť, že počet vykonaných cyklov už nerastie spolu s narastajúcim vstupným poľom lineárne. Ako bolo spomenuté, v priemernom úspešnom vyhľadávaní je prvok nájdený v predposlednom cykle delenia poľa na polovicu. Platí teda, že počet cyklov je približne (log(2) n)-1. Presný počet porovnaní závisí od toho v akom poradí sú zapísané v implementácii podmienky pre pokračovanie vyhľadávania v niektorej z polovíc poľa. |
|
Počet porovnaní, cyklov a času trvania algoritmu pre neúspešné vyhľadávanie s p=0,9. |
počet prvkov v poli |
p_a_porovnani_ |
p_b_porovnani_ |
p_a_cyklov_ |
čas |
10 |
4,200 |
5,100 |
3,400 |
0,2165 |
100 |
7,560 |
9,780 |
6,600 |
0,3935 |
1.000 |
10,81 |
14,81 |
9,902 |
0,5730 |
10.000 |
14,18 |
19,74 |
13,27 |
0,7775 |
100.000 |
17,58 |
24,75 |
16,61 |
0,9949 |
|
Keďže pri úspešnom vyhľadávaní závisel počet cyklov algoritmu od veľkosti vstupného poľa logaritmicky, nebude tomu inak ani pri neúspešnom vyhľadávaní. Príde však k drobnej odchýlke. Zatiaľ čo pri úspešnom vyhľadávaní sa algoritmus skončil väčšinou po (log(2) n)-1 cykloch, teraz bude väčšinou potrebovať približne (log(2) n) cyklov. Musí sa totiž dostať až do najväčšej hĺbky v pomyselnom strome a až potom, keď bude ľavý okraj väčší ako pravý, skonči neúspechom. |
|
|
Závislost dĺžky času trvania algoritmu od veľkosti vstupného pola |
Dĺžka trvania vykonávania algoritmu závisí od vstupného poľa logaritmicky. Medzi priemerným úspešným a neúspešným vyhľadávaním nie sú veľké rozdiely. Vyhľadávanie v cykle je ako vidno z nameraných hodnôt vždy rýchlejšie ako vyhľadávanie pomocou rekurzie. Je to spôsobené opakovaným volaním tej istej funkcie a ukladaním parametrov funkcie na zásobník pri rekurzívnom volaní. Keďže vyhľadávanie v cykle takéto procedúry robiť nemusí, šetrí tak čas (a nielen ten). Ako je vidno, vyhľadávanie pomocou rekurzie trvá približne 2 až 3 krát dlhšie ako vyhľadávanie pomocou cyklu. |
|
|
10 |
100 |
1.000 |
10.000 |
100.000 |
úspešné vyhľadávanie cyklom |
0,0739 |
0,1370 |
0,1742 |
0,2227 |
0,2742 |
neúspešné vyhľadávanie s p=0,9 cyklom |
0,0999 |
0,1557 |
0,2061 |
0,2577 |
0,3120 |
úspešné vyhľadávanie rekurziou |
0,1424 |
0,3117 |
0,4800 |
0,6663 |
0,8765 |
neúspešné vyhľadávanie s p=0,9 rekurziou |
0,2165 |
0,3935 |
0,5730 |
0,7775 |
0,9949 |
|
|
|
Porovnanie algoritmu s predchádzajúcimi algoritmami |
Zatiaľ čo pri malých poliach sú sekvenčný algoritmus s podmienkou a binárne vyhľadávanie porovnateľné, nie je tomu tak pre väčšie polia. Sekvenčné vyhľadávanie s podmienkou má totiž lineárnu zložitosť a binárne vyhľadávanie logaritmickú. Preto s rastúcou veľkosťou vstupného usporiadaného poľa sa zväčšuje aj rozdiel v efektivite. Pre pole s veľkosťou 10.000 prvkov je binárny algoritmus približne 150 krát rýchlejší ako opísaný sekvenčný algoritmus s podmienkou. |
|
|
10 |
100 |
1.000 |
10.000 |
100.000 |
úspešné sekvenčné s podmienkou |
0,0864 |
0,4310 |
3,890 |
38,20 |
426,0 |
neúspešné sekvenčné s podmienkou s p=0,9 |
0,0929 |
0,4410 |
3,880 |
38,10 |
422,0 |
úspešné binárne |
0,0739 |
0,1370 |
0,1742 |
0,2227 |
0,2742 |
neúspešné binárne s p=0,9 |
0,0999 |
0,1557 |
0,2061 |
0,2577 |
0,3120 |
|
|
|
Pre malé polia (rádovo 10 prvkov) je z doteraz opísaných algoritmov najrýchlejší obyčajný sekvenčný algoritmus. Ponúka sa teda otázka, pre aké malé polia je stále binárny algoritmus tým najefektívnejším. Ako vidno z grafu, je to pre úspešné vyhľadávanie asi 8 prvkov a pre neúspešné vyhľadávanie asi 5 prvkov. Dá sa teda povedať, že pre polia obsahujúce viac ako 10 prvkov je výhodné použiť binárne vyhľadávanie. S rastúcou veľkosťou poľa rastie aj rozdiel v efektivite. |
|
|
5 |
10 |
15 |
úspešné sekvenčné |
0,056 |
0,07930 |
0,1045 |
neúspešné sekvenčné s p=0,9 |
0,0842 |
0,1139 |
0,1559 |
binárne úspešné |
0,0628 |
0,0746 |
0,0851 |
binárne neúspešné s p=0,9 |
0,0838 |
0,0999 |
0,1185 |
|
|
|
Poznámka: Algoritmy boli testované na počítači s procesorom AMD Athlon(tm) XP 1700+ a s 256 MB operačnou pamäťou pod operačným systémom Windows XP. Všetky časy uvedené v tabuľke sú v mikrosekundách. |