Prioriteettijonot ja kekolajittelu (heapsort) Käytetään kekoa kahden ongelman ratkaisemiseen: Prioriteettijono: keko ylläpitää keko-ominaisuutta lisäys –ja poisto-operaatioiden kanssa, kukin operaatio vie O(log n) ajan Lajittelu: O(n log n) huonoimmassa tapauksessa, tarvitsee vain vähän ylimääräistä muistia
Keon toteutus Juuri = 1 i:n vasen lapsi = 2*i i:n oikea lapsi = 2*i+1 i:n vanhempi = i/2 x[1] x[2] X[3] x[4] x[5] X[6] Täydellinen binääripuu jonka jokaisen solmun avain on suurempi tai yhtäsuuri kun lasten avain Suurimman alkion etsiminen on nopeaa
Keko – siftup Uudet alkiot lisätään aina taulukon viimeiseen paikkaan, minkä jälkeen puu päivitetään keoksi seuraavalla funktiolla: kekoylos(alkio a[], int k) { while(k > 1 && PIENEMPI(a[k / 2], a[k])) { VAIHDA(a[k], a[k / 2]); k = k / 2; } a[1] a[2] a[3] a[4] a[5] a[6]
Keko – siftdown a[1] a[2] a[3] a[4] a[5] a[6] Poisto maksimikeon juurisolmusta suoritetaan siten, että viimeinen taulukon alkio vaihdetaan juurisolmuun ja päivitetään tietorakenne keoksi seuraavalla funktiolla: kekoalas(alkio a[], int k, int n) { int j; while(2 * k <= n) { j = 2 * k; if(j < n && PIENEMPI(a[j], a[j + 1])) j++; if(!PIENEMPI(a[k], a[j])) break; VAIHDA(a[k], a[j]); k = j; } a[1] a[2] a[3] a[4] a[5] a[6]
Prioriteettijonot esim. käyttöjärjestelmä voisi käyttää prioriteettijonoa esittämään joukkoa prosesseja, joista valitaan seuraavaksi suoritukseen otettava Diskreetissä simuloinnissa jonosta otetaan seuraava tapahtuma suoritettavaksi sekä mahdollisesti lisätään uusia tapahtumia jonoon Tietorakenne lisäys suurimman poisto Lajiteltu taulukko O(n) O(1) Keko O(log n) Lajittelematon taulukko
Kekoon perustuva prioriteettijono static alkio *pq; /* taulukon osoite */ static int n; /* alkioiden lukumäärä */ void PQalusta(int maxn) { if((pq = (alkio *)malloc((maxn + 1) * sizeof(alkio))) == (alkio *)NULL) { perror("Taulukon muistinvaraus"); exit(1); } n = 0; } int PQtyhja() { return n == 0; } void PQlisaa(alkio v) { pq[++n] = v; kekoylos(pq, n); } alkio PQpoistamax() { VAIHDA(pq[1], pq[n]); kekoalas(pq, 1, n - 1); return pq[n--];
Kekolajittelu (heapsort) Yhdistää pikalajittelun ja limityslajittelun edut O(n log n) huonoimmassa tapauksessa aivan kuten limityslajittelu Ei tarvitse lisätilaa aivan kuten pikalajittelu Parannettu versio valintalajittelusta: Taulukko muutetaan keoksi, jonka jälkeen isoin alkio poistetaan keosta ja laitetaan lajiteltuun järjestykseen Ei ole stabiili
Kekolajittelu (heapsort) #define pq(A) a[l - 1 + A] void kekolajittelu(alkio a[], int l, int r) { int k, n = r - l + 1; for(k = n / 2; k >= 1; k--) kekoalas(&pq(0), k, n); while(n > 1) { VAIHDA(pq(1), pq(n)); kekoalas(&pq(0), 1, --n); } 1 3 5 7 2 4 8 11 1 3 5 7 2 4 8 11
Kekolajittelu (heapsort) #define pq(A) a[l - 1 + A] void kekolajittelu(alkio a[], int l, int r) { int k, n = r - l + 1; for(k = n / 2; k >= 1; k--) kekoalas(&pq(0), k, n); while(n > 1) { VAIHDA(pq(1), pq(n)); kekoalas(&pq(0), 1, --n); } 1 3 5 11 2 4 8 7 1 3 5 11 2 4 8 7
Kekolajittelu (heapsort) #define pq(A) a[l - 1 + A] void kekolajittelu(alkio a[], int l, int r) { int k, n = r - l + 1; for(k = n / 2; k >= 1; k--) kekoalas(&pq(0), k, n); while(n > 1) { VAIHDA(pq(1), pq(n)); kekoalas(&pq(0), 1, --n); } 1 3 8 11 2 4 5 7 1 3 8 11 2 4 5 7
Kekolajittelu (heapsort) #define pq(A) a[l - 1 + A] void kekolajittelu(alkio a[], int l, int r) { int k, n = r - l + 1; for(k = n / 2; k >= 1; k--) kekoalas(&pq(0), k, n); while(n > 1) { VAIHDA(pq(1), pq(n)); kekoalas(&pq(0), 1, --n); } 1 11 8 7 2 4 5 3 1 11 8 7 2 4 5 3
Kekolajittelu (heapsort) #define pq(A) a[l - 1 + A] void kekolajittelu(alkio a[], int l, int r) { int k, n = r - l + 1; for(k = n / 2; k >= 1; k--) kekoalas(&pq(0), k, n); while(n > 1) { VAIHDA(pq(1), pq(n)); kekoalas(&pq(0), 1, --n); } 11 7 8 3 2 4 5 1 11 7 8 3 2 4 5 1
Kekolajittelu (heapsort) #define pq(A) a[l - 1 + A] void kekolajittelu(alkio a[], int l, int r) { int k, n = r - l + 1; for(k = n / 2; k >= 1; k--) kekoalas(&pq(0), k, n); while(n > 1) { VAIHDA(pq(1), pq(n)); kekoalas(&pq(0), 1, --n); } 1 7 8 3 2 4 5 1 7 8 3 2 4 5 11 11
Kekolajittelu (heapsort) #define pq(A) a[l - 1 + A] void kekolajittelu(alkio a[], int l, int r) { int k, n = r - l + 1; for(k = n / 2; k >= 1; k--) kekoalas(&pq(0), k, n); while(n > 1) { VAIHDA(pq(1), pq(n)); kekoalas(&pq(0), 1, --n); } 8 7 5 3 2 4 1 8 7 5 3 2 4 1 11 11
Kekolajittelu (heapsort) #define pq(A) a[l - 1 + A] void kekolajittelu(alkio a[], int l, int r) { int k, n = r - l + 1; for(k = n / 2; k >= 1; k--) kekoalas(&pq(0), k, n); while(n > 1) { VAIHDA(pq(1), pq(n)); kekoalas(&pq(0), 1, --n); } 1 7 5 3 2 4 1 7 5 3 2 4 8 11 8 11
Kekolajittelu (heapsort) #define pq(A) a[l - 1 + A] void kekolajittelu(alkio a[], int l, int r) { int k, n = r - l + 1; for(k = n / 2; k >= 1; k--) kekoalas(&pq(0), k, n); while(n > 1) { VAIHDA(pq(1), pq(n)); kekoalas(&pq(0), 1, --n); } 7 3 5 1 2 4 7 3 5 1 2 4 8 11 8 11
Kekolajittelu (heapsort) #define pq(A) a[l - 1 + A] void kekolajittelu(alkio a[], int l, int r) { int k, n = r - l + 1; for(k = n / 2; k >= 1; k--) kekoalas(&pq(0), k, n); while(n > 1) { VAIHDA(pq(1), pq(n)); kekoalas(&pq(0), 1, --n); } 4 3 5 1 2 4 3 5 1 2 7 8 11 7 8 11
Kekolajittelu (heapsort) #define pq(A) a[l - 1 + A] void kekolajittelu(alkio a[], int l, int r) { int k, n = r - l + 1; for(k = n / 2; k >= 1; k--) kekoalas(&pq(0), k, n); while(n > 1) { VAIHDA(pq(1), pq(n)); kekoalas(&pq(0), 1, --n); } 5 3 4 1 2 5 3 4 1 2 7 8 11 7 8 11
Kekolajittelu (heapsort) #define pq(A) a[l - 1 + A] void kekolajittelu(alkio a[], int l, int r) { int k, n = r - l + 1; for(k = n / 2; k >= 1; k--) kekoalas(&pq(0), k, n); while(n > 1) { VAIHDA(pq(1), pq(n)); kekoalas(&pq(0), 1, --n); } 2 3 4 1 2 3 4 1 5 7 8 11 5 7 8 11
Kekolajittelu (heapsort) #define pq(A) a[l - 1 + A] void kekolajittelu(alkio a[], int l, int r) { int k, n = r - l + 1; for(k = n / 2; k >= 1; k--) kekoalas(&pq(0), k, n); while(n > 1) { VAIHDA(pq(1), pq(n)); kekoalas(&pq(0), 1, --n); } 4 3 2 1 4 3 2 1 5 7 8 11 5 7 8 11
Kekolajittelu (heapsort) #define pq(A) a[l - 1 + A] void kekolajittelu(alkio a[], int l, int r) { int k, n = r - l + 1; for(k = n / 2; k >= 1; k--) kekoalas(&pq(0), k, n); while(n > 1) { VAIHDA(pq(1), pq(n)); kekoalas(&pq(0), 1, --n); } 1 3 2 1 3 2 4 5 7 8 11 4 5 7 8 11
Kekolajittelu (heapsort) #define pq(A) a[l - 1 + A] void kekolajittelu(alkio a[], int l, int r) { int k, n = r - l + 1; for(k = n / 2; k >= 1; k--) kekoalas(&pq(0), k, n); while(n > 1) { VAIHDA(pq(1), pq(n)); kekoalas(&pq(0), 1, --n); } 3 1 2 3 1 2 4 5 7 8 11 4 5 7 8 11
Kekolajittelu (heapsort) #define pq(A) a[l - 1 + A] void kekolajittelu(alkio a[], int l, int r) { int k, n = r - l + 1; for(k = n / 2; k >= 1; k--) kekoalas(&pq(0), k, n); while(n > 1) { VAIHDA(pq(1), pq(n)); kekoalas(&pq(0), 1, --n); } 2 1 2 1 3 4 5 7 8 11 3 4 5 7 8 11
Kekolajittelu (heapsort) #define pq(A) a[l - 1 + A] void kekolajittelu(alkio a[], int l, int r) { int k, n = r - l + 1; for(k = n / 2; k >= 1; k--) kekoalas(&pq(0), k, n); while(n > 1) { VAIHDA(pq(1), pq(n)); kekoalas(&pq(0), 1, --n); } 2 1 2 1 3 4 5 7 8 11 3 4 5 7 8 11
Kekolajittelu (heapsort) #define pq(A) a[l - 1 + A] void kekolajittelu(alkio a[], int l, int r) { int k, n = r - l + 1; for(k = n / 2; k >= 1; k--) kekoalas(&pq(0), k, n); while(n > 1) { VAIHDA(pq(1), pq(n)); kekoalas(&pq(0), 1, --n); } 1 2 3 4 5 7 8 11 1 2 3 4 5 7 8 11