Esittely latautuu. Ole hyvä ja odota

Esittely latautuu. Ole hyvä ja odota

Lajittelu: peruskäsitteet

Samankaltaiset esitykset


Esitys aiheesta: "Lajittelu: peruskäsitteet"— Esityksen transkriptio:

1 Lajittelu: peruskäsitteet
esim. struct {char *snimi, char *enimi, unsigned huone); Lajittele: Uudelleenjärjestä tietueet siten, että avaimet ovat järjestyksessä. tiedosto Kyrki Ville 6533 Kämäräinen Joni Ikonen Leena Alaoutinen Satu 6711 Bern Alexande 6725 Bochko Vladimir 6726 Alaoutinen Satu 6711 Bern Alexande 6725 Bochko Vladimir 6726 Ikonen Leena 6533 Kämäräinen Joni Kyrki Ville tietue avain

2 Lajittelu osoittimien avulla
Kyrki Ville 6533 Kämäräinen Joni Ikonen Leena Alaoutinen Satu 6711 Bern Alexande 6725 Bochko Vladimir 6726 Kyrki Ville 6533 Kämäräinen Joni Ikonen Leena Alaoutinen Satu 6711 Bern Alexande 6725 Bochko Vladimir 6726

3 Stabiilius Stabiili lajittelualgoritmi säilyttää saman avaimen omaavien tietueiden suhteellisen järjestyksen. Alaoutinen Satu 6711 Bern Alexande 6725 Bochko Vladimir 6726 Ikonen Leena 6533 Kämäräinen Joni Kyrki Ville Kyrki Ville 6533 Kämäräinen Joni Ikonen Leena Alaoutinen Satu 6711 Bern Alexande 6725 Bochko Vladimir 6726 tietueet joissa 3. avaimen arvo on 6533 eivät ole ensimmäisen avaimen mukaisessa järjestyksessä.

4 #define VAIHDA(A, B) { alkio t = A; A = B; B = t; }
void lisayslajittelu1(alkio a[], int n) { int i, j; for (i = 1; i < n; i++) for (j = i; j > 0 && a[j-1] > a[j]; j--) VAIHDA(a[j-1], a[j]); } Lisäyslajittelu

5 void valintalajittelu(alkio a[], int l, int r) { int i, j;
for(i = l; i < r; i++){ /* käydään kaikki paitsi viimeinen*/ int minimi = i; /* pienimmän indeksinumero */ for(j = i + 1; j <= r; j++) /* käydään läpi lajittelemattomat */ if(PIENEMPI(a[j], a[minimi])) /* jos pienempi kuin aikaisemmat */ minimi = j; /* pienimmän indeksinumero talteen */ /* Taulukon senhetkisen alkion ja lajittelemattomien pienimmän vaihto. */ VAIHDA(a[i], a[minimi]); } Valintalajittelu

6 VERTVAIHDA(a[j - 1], a[j]); }
void kuplalajittelu(alkio a[], int l, int r) { int i, j; for(i = l; i <= r; i++) /* käydään kaikki alkiot läpi */ for(j = r; j > i; j--) /* Vaihdetaan alkiopari tarvittaessa. */ VERTVAIHDA(a[j - 1], a[j]); } Kuplalajittelu

7 Kuorilajittelu (shell sort)
void kuorilajittelu(alkio a[], int l, int r) { int i, h; /* Lisäyssarjan laskenta. */ for(h = 1; h <= (r - l) / 9; h = 3 * h + 1) ; for(; h > 0; h /= 3) /* lajittelu lisäystä pienentäen */ for(i = l + h; i <= r; i++) { /* lisäyslajittelu lisäyksellä h */ int j = i; alkio v = a[i]; while(j >= l + h && PIENEMPI(v, a[j-h])) { a[j] = a[j - h]; j -= h; } a[j] = v; } Kuorilajittelu (shell sort)

8 Jakaumalajittelu (distribution counting)
void jakaumalajittelu(alkio a[], int l, int r) { int i, j, lkm[m]; int b[ARVO_MAX]; for(j = 0; j < m; j++) /* lukumäärien alustaminen */ lkm[j] = 0; for(i = l; i <= r; i++) /* lukumäärien laskenta */ lkm[a[i] + 1]++; for(j = 1; j < m; j++) /* kumulatiivinen summa */ lkm[j] += lkm[j - 1]; for(i = l; i <= r; i++) /* alkioiden lajittelu */ b[lkm[a[i]]++] = a[i]; for(i = l; i <= r; i++) /* lajitellun kopiointi */ a[i] = b[i]; } Jakaumalajittelu (distribution counting)

9 Hajoita ja hallitse (divide and conquer)
Pikalajittele n-alkioinen taulukko. Divide: Osoidaan taulukko kahdeksi alitaulukoksi tukialkion (pivot) x suhteen: Conquer: Lajitellaan alitaulukot rekursiivisesti Yhdistäminen: triviaali x x x

10 Pikalajittelu (quicksort)
void pikalajittelu(alkio a[], /* lajiteltavien taulukko */ int l, /* käsiteltävien alku */ int r) /* käsiteltävien loppu */ { int i; if(l < r) /* jos lajiteltavaa jäljellä */ i = osioi(a, l, r); /* taulukon jako kahteen osaan */ pikalajittelu(a, l, i - 1); /* ensimmäisen puoliskon lajittelu */ pikalajittelu(a, i + 1, r); /* toisen puoliskon lajittelu */ } Pikalajittelu (quicksort)

11 Valitaan k:nneksi pienin alkio rekursiivisesti
void valitse_rekursiivisesti(alkio a[], int l, int r, int k) { int i; if(r <= l) return; i = osioi(a, l, r); /* taulukon jako kahteen osioon */ /* Sen osion jatkokäsittely, johon k:s alkio kuuluu. */ if(i > k) valitse_rekursiivisesti(a, l, i - 1, k); if(i < k) valitse_rekursiivisesti(a, i + 1, r, k); } Valitaan k:nneksi pienin alkio rekursiivisesti

12 Valitaan k:nneksi pienin alkio iteratiivisesti
void valitse_iteratiivisesti(alkio a[], int l, int r, int k) { int i; while(r > l) { i = osioi(a, l, r); /* taulukon jako kahteen osioon */ /* Sen reunan siirto, johon k:s alkio ei kuulu. */ if(i >= k) r = i - 1; if(i <= k) l = i + 1; } Valitaan k:nneksi pienin alkio iteratiivisesti

13 Limityslajittelu (merge sort)
Limityslajittelu (hajoita ja hallitse) Jaa tiedosto kahteen osaan Rekursiivisesti lajittele molemmat osat Yhdistä lajitellut alitaulukot A L G O R I T M I T A L G O R I T M I T hajoita A G L O R I I M T T lajittele A G I I L M O R T T limittele

14 void limityslajittelu(alkio a[], int l, int r) { int m = (r + l) / 2;
if(r <= l) /* jos ei tehtävää jäljellä */ return; limityslajittelu(a, l, m); /* alkupuoliskon käsittely */ limityslajittelu(a, m+1, r); /* loppupuoliskon käsittely */ limitys(a, l, m, r); } Limityslajittelu

15 (Maksimi)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

16 kekoalas(alkio a[], int k, int n) { int j; while(2 * k <= n) {
j = 2 * k; /* j vasempaan lapseen */ /* Jos ollaan puun sisällä ja oikea lapsi on suurempi. */ if(j < n && PIENEMPI(a[j], a[j + 1])) j++; /* siirry oikeaan lapseen */ if(!PIENEMPI(a[k], a[j])) /* jos ylempänä suurempi */ break; VAIHDA(a[k], a[j]); k = j; /* puussa alemmaksi */ } Kekoalas

17 Kekolajittelu (heap sort)
#define pq(A) a[l A] void kekolajittelu(alkio a[], int l, int r) { int k; int n = r - l + 1; /* tehtävän koko */ /* keon muodostaminen taulukosta */ for(k = n / 2; k >= 1; k--) kekoalas(&pq(0), k, n); /* lajittelu */ while(n > 1) { VAIHDA(pq(1), pq(n)); /* suurin viimeiseksi */ kekoalas(&pq(0), 1, --n); /* keon päivittäminen */ } Kekolajittelu (heap sort)

18 Jakolajittelun lähestymistavat
Eniten merkitsevän numeron jakolajittelu Tutkivat minimimäärän informaatiota lajittelun suorittamiseksi Yleistävät pikalajittelun Vähiten merkitsevän numeron jakolajittelu Numeroita tutkitaan oikealta vasemmalle

19 int hae(alkio t, alkio x[], int n)
{ int l, u, m; l = 0; u = n-1; while (l <= u) { /* toistetaan kunnes ei voi enää löytyä */ m = (l + u) / 2; if (x[m] < t) l = m+1; else if (x[m] == t) /* jos löytyi */ return m; else /* x[m] > t */ u = m-1; } return -1; Binäärihaku

20 Binääriset hakupuut Lisäykset järjestettyyn taulukkoon olivat laskennallisesti raskaita Käytetään ekplisiittistä puurakennetta solmu x A B alipuut pienempiä suurempia

21 Binäärinen hakupuu C-kielellä
linkki on osoitin solmuun Solmu koostuu kolmesta kentästä Avaimellisesta solmusta Vasen linkki (binääripuu, jossa pienemmät avaimet) Oikea linkki (binääripuu, jossa suuremmat avaimet) 51 14 68 typedef struct STsolmu* linkki; struct STsolmu { alkio item; linkki l, r; }; static linkki paa, z; 12 54 79

22 Haku binäärisestä hakupuusta
alkio haeR(linkki h, Avain v) { avain t = AVAIN(h->item); if(h == z) /* lehtisolmussa ? */ { return NULLalkio; } /* ei löytynyt */ if(YHTASUURI(v, t)) return h->item; /* löytyi */ if(PIENEMPI(v, t)) return haeR(h->l, v); /* vasen alipuu */ else return haeR(h->r, v); /* oikea alipuu */ } alkio SThae(Avain v) { return haeR(paa, v); } Haku binäärisestä hakupuusta

23 Lisäys binääriseen hakupuuhun
linkki lisaaR(linkki h, alkio item) { Avain v = AVAIN(item), t = AVAIN(h->item); if(h == z) /* lehtisolmussa ? */ return uusi(item, z, z, 1); /* luodaan uusi solmu */ if(PIENEMPI(v, t)) h->l = lisaaR(h->l, item); /* vasen alipuu */ else h->r = lisaaR(h->r, item); /* oikea alipuu */ return h; } void STlisaa(alkio item) { paa = lisaaR(paa, item); } Lisäys binääriseen hakupuuhun

24 Hajakoodausfunktio Hajakoodausfunktio h kuvaa kaikkien avaimien joukon U joukoksi {0,1,…,m-1} k1 k5 k4 k2 k3 h(k1) h(k5) U h(k2)= h(k4) Kun kaksi avainta kuvautuu samaan indeksin arvoon tapahtuu törmäys. h(k3) m-1

25 Hajakoodausfunktio Tavoite: satunnainen kuvaus (kaikki indeksit yhtä todennäköisiä kaikille avaimille) Avaimia käsitellään pitkinä kokonaislukuina, taulukon koko M on alkuluku Hajakoodausfunktio: h(K) = K mod M Laske arvo Hornerin säännön avulla: Esim. abcd:n hajakoodausfunktion arvo on 11 97* * * = (256*(256*(256*97+98)+99)+100 % 101 = 11 Numerot liian isoja? Lasketaan jakojäännös jokaisen operaation jälkeen (256* ) % 101 = 84 (256* ) % 101 = 90 (256* ) % 101 = 11 Universaali hajakoodaus: hajakoodausfunktion kerroin vaihtuu jokaisen koodattavan yksikön kohdalla.

26 int haja(char *v, /* koodattava merkkijono */
int n) /* hajakoodaustaulun koko */ { int h = 0, a = 127; /* kokonaislukukerroin */ for(; *v != '\0'; v++) /* toisto, kunnes merkit loppu */ h = (a * h + *v) % n; /* hajakoodin laskenta */ return h; } Hajakoodausfunktio

27 Törmäyksen selvitysstrategiat
Erillinen ketjutus Taulukon koko (M) paljon alkioiden lukumäärää pienempi (N) n. N/M alkiota jokaisessa taulukon indeksissä Samaan indeksiin kuvautuvat avaimet laitetaan linkitettyyn listaan Avoin osoitteistus (lineaarinen koestus, kaksoishajakoodaus) Taulukon koko paljon alkioiden lukumäärää suurempi Paljon tyhjiä paikkoja taulukossa Törmäyksen sattuessa etsitään vapaa paikka

28 Avaimen hakufunktio patricia-puusta
alkio haeR(linkki h, /* rekursiivinen hakufunktio */ Avain v, /* haettava avain */ int w) /* käsiteltävä bitti */ { if(h->bit <= w) /* jos loppuja bittejä turha käsitellä */ return h->item; if(bitti(v, h->bit) == 0) /* jos h->bit:is bitti nolla */ return haeR(h->l, v, h->bit); /* vasemmalle */ else return haeR(h->r, v, h->bit); /* oikealle */ } alkio SThae(Avain v) /* haun liittymäfunktio */ alkio t = haeR(paa->l, v, -1); return YHTASUURI(v, AVAIN(t)) ? t : NULLalkio; Avaimen hakufunktio patricia-puusta

29 int raakahaku(char p[], char a[]) {
int i, j; int m = strlen(p); /* hahmon pituus */ int n = strlen(a); /* merkkijonon pituus */ for (i = 0; i < n-m+1; i++) { for (j = 0; j < m; j++) { if (a[i+j] != p[j]) break; } if (j == m) /* löytyi kohdasta i */ return i; return -1; /* ei löytynyt */ Raa’n voiman haku

30 int KMPhaku(char p[], char a[], int next[]) {
int i, j = 0; int m = strlen(p); /* hahmon pituus */ int n = strlen(a); /* merkkijonon pituus */ alusta_seur(p, next); /* uudelleenaloituspisteiden alustus*/ for (i = 0; i < n-m+1; i++) { if (a[i] == p[j]) /* merkit samat */ j++; else /* merkit erisuuret */ j = next[j]; if (j == m) /* löytyi */ return i – m + 1; } return -1; /* ei löytynyt */ Knuth-Morris-Pratt

31 void initskip(char *p){ /* uudelleenaloituspisteiden alustus*/
int j, m = strlen(p); for (j = 0; j < 256; j++) skip[j] = m; for (j = 0; j < m; j++) skip[p[j]] = m-j-1; } #define max(A, B) (A > B) ? A : B; int BMhaku(char *p, char *a){ int m = strlen(p), n = strlen(a); int i, j; initskip(p); for (i = m-1, j = m-1; j >= 0; i--, j--) while (a[i] != p[j]) { /* niin kauan, kun merkeissä eroa */ i += max(m-j, skip[a[i]]); if (i >= n) return -1; /* ei löytynyt */ j = m-1; /* hahmoindeksin alustus */ return i+1; /* palautetaan löytöpaikka */ Boyer-Moore

32 Karp-Rabin C-kielellä
#define Q /* taulukon koko */ #define D /* kantaluku */ int RKhaku(char p[], char a[]) { /* p on hahmo, a on merkkijono */ int i, j, dm = 1, h1 = 0, h2 = 0; int m = strlen(p), n = strlen(a); for (j = 1; j < m; j++) /* D^m % Q */ dm = (D * dm) % Q; for (j = 0; j < m; j++) { h1 = (h1*D + p[j]) % Q; /* hahmon tiiviste */ h2 = (h2*D + a[j]) % Q; /* merkkijonon tiiviste */ } for (i = m; i < n; i++) { if (h1 == h2) return i – m; /* löytyi */ h2 = (h2+D*Q–a[i-m]*dm)%Q; /*poistetaan eniten merkitsevä luku */ h2 = (h2*D + a[i]) % Q; /* lisätään vähiten merkisevä luku */ return -1; /* ei löytynyt */ Rabin-Karp Karp-Rabin C-kielellä D*Q pitää luvun positiivisena


Lataa ppt "Lajittelu: peruskäsitteet"

Samankaltaiset esitykset


Iklan oleh Google