|
Grafy a tabuľky |
Vyhľadávanie k-tej hodnoty
|
Priemerné počty porovnaní vybraných implementácií |
//najdenie zadanej (k-tej najmensej) hodnoty v poli
//funkcia vracia zadanu hodnotu v poli
//(ak je v poli menej prvkov ako k, funkcia vracia maximum,
//ak je k <= 0, funkcia vracia minimum)
template < class T, int velkost_ >
T CPole < T, velkost_ > ::najdi_k_tu_hodnotu2(int k){
int lavy_o=0;
int pravy_o=velkost_-1;
int Q;
while(++p_a_porovnani_ && lavy_o!=pravy_o) {
++p_a_cyklov_;
triedenie(lavy_o, pravy_o, Q);
int M=Q-lavy_o+1;
if (++ p_a_porovnani_ && k <=M) pravy_o=Q;
else {
lavy_o=Q+1;
k=k-M;
}
}
return pole_[lavy_o];
}
//pomocna funkcia na ciastocne triedenie pola "pole"
//medzi zadanym lavym "lavy_o" a pravym "pravy_o" okrajom
//prvky s mensim indexom ako Q su po ukonceni funkcie mensie alebo rovne ako pivot
//prvky s vacsim indexom ako Q su po ukonceni funkcie vacsie alebo rovne ako pivot
//pocet prvkov mensich alebo rovnych ako pivot je ulozeny na adresu &Q
template < class T, int velkost_ >
void CPole < T, velkost_ > ::triedenie(int lavy_o, int pravy_o, int& Q){
int i=lavy_o;
int j=pravy_o;
T pivot=pole_[(lavy_o+pravy_o)/2];
do {
++p_b_cyklov_;
while (++p_b_porovnani_ && pole_[i] < pivot) i++;
while (++p_b_porovnani_ && pole_[j] > pivot) j--;
if (++p_a_porovnani_ && i <= j) {
T pomocna;
pomocna=pole_[i]; pole_[i]=pole_[j]; pole_[j]=pomocna;
i++; j--;
}
} while (++p_c_porovnani_ && i <= j);
Q=i-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_c_porovnani_ |
p_a_cyklov_ |
p_b_cyklov_ |
čas |
10 |
8,000 |
20,70 |
10,00 |
3,500 |
5,000 |
0,4236 |
100 |
17,18 |
284,7 |
110,0 |
8,090 |
54,98 |
2,880 |
1.000 |
28,78 |
4321,4 |
1017,3 |
13,89 |
508,7 |
32,46 |
10.000 |
34,88 |
27541,0 |
10031,4 |
16,94 |
5015,7 |
276,4 |
100.000 |
43,73 |
245474,4 |
100106 |
21,37 |
50052,7 |
3325,8 |
|
Pri tomto algoritme už nie nie je taký dôležitý počet porovnaní ako to bolo pri predchádzajúcich algoritmoch, môžeme si však všimnúť, že sa súčet všetkých porovnaní pohybuje približne okolo hodnoty 4*n. |
|
|
//najdenie zadanej (k-tej najmensej) hodnoty v poli medzi lavym "lavy_o" a
//pravym "pravy_o" okrajom
//pre vyhladavanie v celom poli treba zadat lavy_o=0 a pravy_o=velkost-1
//funkcia vracia zadanu hodnotu v poli
//(ak je v poli menej prvkov ako k, funkcia vracia maximum,
//ak je k <= 0, funkcia vracia minimum)
template < class T, int velkost_ >
T CPole < T, velkost_ > ::najdi_k_tu_hodnotu(int lavy_o, int pravy_o, int k){
int M, Q;
if (++p_a_porovnani_ && lavy_o==pravy_o) return pole_[lavy_o];
else {
++p_a_cyklov_;
triedenie(lavy_o, pravy_o, Q);
M=Q-lavy_o+1;
if (++ p_a_porovnani_ && k <= M) najdi_k_tu_hodnotu(lavy_o, Q, k);
else najdi_k_tu_hodnotu(Q+1, pravy_o, k-M);
}
}
//pomocna funkcia na ciastocne triedenie pola "pole"
//medzi zadanym lavym "lavy_o" a pravym "pravy_o" okrajom
//prvky s mensim indexom ako Q su po ukonceni funkcie mensie alebo rovne ako pivot
//prvky s vacsim indexom ako Q su po ukonceni funkcie vacsie alebo rovne ako pivot
//pocet prvkov mensich alebo rovnych ako pivot je ulozeny na adresu &Q
template < class T, int velkost_ >
void CPole < T, velkost_ > ::triedenie(int lavy_o, int pravy_o, int& Q){
int i=lavy_o;
int j=pravy_o;
T pivot=pole_[(lavy_o+pravy_o)/2];
do {
++p_b_cyklov_;
while (++p_b_porovnani_ && pole_[i] < pivot) i++;
while (++p_b_porovnani_ && pole_[j] > pivot) j--;
if (++p_a_porovnani_ && i <= j) {
T pomocna;
pomocna=pole_[i]; pole_[i]=pole_[j]; pole_[j]=pomocna;
i++; j--;
}
} while (++p_c_porovnani_ && i <= j);
Q=i-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_c_porovnani_ |
p_a_cyklov_ |
p_b_cyklov_ |
čas |
10 |
8,000 |
20,70 |
10,00 |
3,500 |
5,000 |
0,5477 |
100 |
17,18 |
284,7 |
110,0 |
8,090 |
54,98 |
3,590 |
1.000 |
28,78 |
4321,4 |
1017,3 |
13,89 |
508,7 |
42,26 |
10.000 |
34,88 |
27541,0 |
10031,4 |
16,94 |
5015,7 |
293,5 |
100.000 |
43,73 |
245474,4 |
100106 |
21,37 |
50052,7 |
3344,1 |
|
Počet porovnaní a cyklov sa pri zmene použitého postupu z vyhľadávania pomocou cyklu na vyhľadávanie pomocou rekurziu nemení. Súčet porovnaní je stále približne rovný 4*n. |
|
|
Závislost dĺžky času trvania algoritmu od veľkosti vstupného pola |
Vyhľadávanie cyklom je časovo menej náročné ako vyhľadávanie pomocou rekurzie. Pri opakovanom volaní funkcie sa totiž musia ukladať parametre volanej funkcie na zásobník. Keďže pri vyhľadávaní v cykle nepotrebujeme žiadnu réžiu navyše, je takéto vyhľadávanie rýchlejšie. Pri zväčšovaní poľa sa však spomínaný náskok postupne zmenšuje. |
|
|
10 |
100 |
1.000 |
10.000 |
100.000 |
vyhľadávanie cyklom |
0,4236 |
2,880 |
32,50 |
276,0 |
3326,0 |
vyhľadávanie rekurziou |
0,5477 |
3,590 |
42,26 |
293,5 |
3344,0 |
|
|
|
Porovnanie algoritmu s predchádzajúcimi algoritmami |
Ako bolo možné predpokladať, najnáročnejším na čas z predchádzajúcich troch algoritmov bol práve posledne opisovaný. Čas potrebný na ukončenie tohto algoritmu je približne 3 až 4 krát väčší ako čas potrebný na ostatné dva algoritmy. Bez tohto posledného by sme však nevedeli efektívne riešiť hľadanie inej ako najmenšej alebo najväčšej hodnoty v poli prvkov. |
|
|
10 |
100 |
1.000 |
10.000 |
100.000 |
vyhľadávanie jedného extrému |
0,1314 |
0,8590 |
7,770 |
76,60 |
918,0 |
vyhľadávanie oboch extrémov súčasne |
0,1054 |
0,9190 |
8,930 |
90,40 |
1174,0 |
vyhľadávanie k-tej hodnoty |
0,4236 |
2,880 |
32,46 |
276,4 |
3326 |
|
|
|
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. |