130 likes | 272 Views
Hajoita ja hallitse (divide and conquer). Pikalajittele n-alkioinen taulukko Divide : Jaetaan taulukko kahdeksi alitaulukoksi tukialkion (pivot) x suhteen: Conqueror : Lajitellaan alitaulukot rekursiivisesti Yhdistäminen: triviaali. x. x. x. Animaatio.
E N D
Hajoita ja hallitse (divide and conquer) • Pikalajittele n-alkioinen taulukko • Divide: Jaetaan taulukko kahdeksi alitaulukoksi tukialkion (pivot) x suhteen: • Conqueror: Lajitellaan alitaulukot rekursiivisesti • Yhdistäminen: triviaali x x x
Animaatio • http://www.cs.brockport.edu/cs/java/apps/sorters/quicksort.html
Osiointi 55 41 59 26 53 58 97 93 41 26 53 55 59 58 97 93 55 55
x x x l m r x x x l m r Yksinkertaisin versio x x x ? voidpikalajittelu1(alkio a[], intl, intr){ inti, m, x=a[l]; if (l >= r) return; m = l; for (i = l+1; i <= r; i++) if (a[i] < x) vaihda(a, ++m, i); vaihda(a, l, m); pikalajittelu1(a, l, m-1); pikalajittelu1(a, m+1, r);} l m i r ensimmäinen alkio on tukialkio enintään yksi alkio => palaa
Kaikki alkiot samoja 55 55 55 55 55 55 55 55 l,m r Taulukon jako on hyvin epätasainen: toiseen alitaulukkoon kuuluu kaikki muut alkiot paitsi tukialkio.
Kaksisuuntainen osiointi x x x ? voidpikalajittelu3(alkio a[], intl, intr){ inti, j; alkiox; if (l >= r) return; x = a[l];i = l;j = r+1; for (;;) { doi++; while (i <= r && a[i] < x); doj--; while (a[j] > x); if (i > j)break; vaihda(a, i, j);} vaihda(a, l, j); pikalajittelu3(a, l, j-1); pikalajittelu3(a,j+1, r);} l i r j enintään yksi alkio => palaa Pysähdytään yhtäsuuriin elementteihin
Alkiot nousevassa järjestyksessä 55 56 57 58 58 59 60 61 l,m r Taulukon jako on hyvin epätasainen: toiseen alitaulukkoon kuuluu kaikki muut alkiot paitsi tukialkio.
Satunnaistaminen+ pienten alitaulukoiden lisäyslajittelu intcutoff = 50; voidpikalajittelu4(alkio a[], intl, intr){ inti, j; alkiot, temp; if (r - l < cutoff) return; vaihda(a, l, randint(l, r)); x = a[l];i = l;j = r+1; for (;;) { doi++; while (i <= r && a[i] < x); doj--; while (a[j] > x); if (i > j) break; vaihda(a, l, j); } vaihda(a, l, j); pikalajittelu4(a, l, j-1); pikalajittelu4(a, j+1, r); } pieni taulukko => palaa vaihdetaan satunnainen alkio tukialkioksi Ohjelman päättyessä taulukko a:n sisältö ei ole lajiteltuna, vaan se on ryhmitelty pieniin satunnaisesti järjestettyihin arvoihin. Kukin ryhmä sisältää pienempiä arvoja kuin sen oikealla puolella olevat. Lajittelu: pikalajittelu4(a, l, r); lisayslajittelu3(a, l, r);
Kolmivaiheinen osiointi • Tehokas runsaasti samoja avaimia sisältävässä tapauksessa
Algoritmin kompleksisuus • Huonoin tapaus: toiselle puolelle jää N-1 alkiota ja toiselle 0 => O(N2) • Paras tapaus: molemmille puolille jää yhtä monta alkiota=> O(N log N) • Myös keskimääräinen kompleksisuus on O(N log N)
Tukialkion valinta • Valitaan vakiopaikasta, esim. taulukon ensimmäinen. Toimii hyvin satunnaiselle syötteelle. Melkein järjestetylle syötteelle jako on erittäin epätasainen. • Valitaan tukialkioksi ensimmäisen, keskimmäisen ja viimeisen alkion mediaani. • Valitaan tukialkio satunnaisesti. Erittäin todennäköisesti osittelu on tasainen.
Valitaan k:ksi pienin alkio rekursiivisesti void valitse_rekursiivisesti(alkio a[], intl, intr, intk) { inti; if(r <= l) return; i = osioi(a, l, r); if(i > k) valitse_rekursiivisesti(a, l, i - 1, k); if(i < k) { valitse_rekursiivisesti(a, i + 1, r, k); } • k:s alkio löytyy taulukosta kohdasta a[k-1] vaikkei taulukkoa ole kokonaan lajiteltukaan
Valitaan k:ksi pienin alkio iteratiivisesti void valitse_iteratiivisesti(alkio a[], intl, intr, intk) { inti; while(r > l) { i = osioi(a, l, r); if(i >= k) r = i - 1; if(i <= k) l = i + 1; } } • k:s alkio löytyy taulukosta kohdasta a[k-1] vaikkei taulukkoa ole kokonaan lajiteltukaan