Tietorakenteet ja algoritmit Järjestäminen Ari Korhonen 6.10.2015 1
6. Järjestäminen (sor0ng) 6.1 Johdanto 6.2 Yksinkertaiset menetelmät 6.2.1 Valintajärjestäminen 6.2.2 Lisäysjärjestäminen 6.3 Lomitusjärjestäminen (merge sort) 6.3.1 Lomitus (merging) 6.4 Pikajärjestämismenetelmä (quicksort) 6.4.1 Valikointi (selection) 6.5 Jakauman laskeminen (Distribution counting) 6.6 Kantalukujärjestäminen (radix sorting) 6.6.1 Digitaalinen vaihtojärjestäminen 6.6.2 Suora digitaalinen järjestäminen 6.7 Järjestämismenetelmän valinnasta 6.10.2015 Tietorakenteet ja algoritmit - syksy 2015 2
6.1 Johdanto Järjestäminen eli lajittelu on tietojenkäsittelyn perusasioita. Syöte: sarja tietueita, avaimia, lukuja, tms. <a 1, a 2,..., a n > Tuloste: sellainen lukusarjan permutaatio <a 1, a 2,..., a n >, jolle a 1 a 2... a n Sovelluksia on lukemattomia: henkilörekisterit puhelinluettelo tilitapahtumat sähköpostiohjelma graafiset koordinaatit 6.10.2015 Tietorakenteet ja algoritmit - syksy 2015 3
Perusajatukset: String key 1 Int key 2 Järjestetään tiedostoja tai lineaarisia tietorakenteita, jotka koostuvat tietueista Jokaisessa tietueessa on yksi tai useampi avain, jonka perusteella järjestetään. Sen lisäksi on dataa Kouluesimerkit yksinkertaisuuden vuoksi dataosuutta ei jatkossa näytetä avaimet lukuja tai yksittäisiä kirjaimia, vaikka todellisuudessa ne voivat olla mielivaltaisen pitkiä merkkijonoja tms. epäsuora järjestäminen, avaimet esim. taulukossa 6.10.2015 Tietorakenteet ja algoritmit - syksy 2015 4
Epäsuora järjestäminen: ei vaihdeta tietueiden paikkaa muistissa vaan luodaan hakemisto (viittauksia), joita järjestetään String key 1 Int key 2 String key 1 3 Int key 2 String key 1 2 Int key 2 String key 1 4 a3 a2 a4 a1 Int key 2 1 Hakemisto: a3 a1 a4 a2 Abstrahoidaan tietueiden osoitteet pois 6.10.2015 Tietorakenteet ja algoritmit - syksy 2015 5
Epäsuora järjestäminen: ei vaihdeta tietueiden paikkaa muistissa vaan luodaan hakemisto (viittauksia), joita järjestetään String key 1 Int key 2 String key 1 3 Int key 2 String key 1 2 Int key 2 String key 1 4 3 2 4 1 Int key 2 1 Hakemisto: 3 1 4 2 6.10.2015 Tietorakenteet ja algoritmit - syksy 2015 6
Epäsuora järjestäminen: ei vaihdeta tietueiden paikkaa muistissa vaan luodaan hakemisto (viittauksia), joita järjestetään String key 1 Int key 2 String key 1 3 Int key 2 String key 1 2 Int key 2 String key 1 4 3 2 4 1 Int key 2 1 Hakemisto: 1 2 3 4 Ainoastaan hakemiston viittaukset tietueisiin muuttuvat. 6.10.2015 Tietorakenteet ja algoritmit - syksy 2015 7
Jos järjestetään keskusmuistissa, on kyse sisäisestä järjestämisestä (internal sorting) Jos järjestetään levyllä, koska tiedostot eivät mahdu keskusmuistiin, on kyse ulkoisesta järjestämisestä (external sorting) tätä ei juurikaan käsitellä kurssilla. Tällä kurssilla keskitytään enemmän sisäiseen järjestämiseen 6.10.2015 Tietorakenteet ja algoritmit - syksy 2015 8
Järjestämismenetelmän vaatima tietokoneaika on verrannollinen järjestettävien elementtien määrään seuraavasti: O( N 2 ) perusmenetelmät O(N log N) kehittyneet menetelmät Ω(N log N) alaraja järjestämisalgoritmeille, jotka perustuvat kokonaisten avainten vertailuihin O(N) jos avaimella on erikoisominaisuuksia, joita voidaan käyttää hyväksi bittitasolla 6.10.2015 Tietorakenteet ja algoritmit - syksy 2015 9
Järjestämismenetelmä on stabiili (vakaa), jos se säilyttää samojen avainten keskinäisen järjestyksen. Perusmenetelmät ovat yleensä stabiileja, kehittyneet menetelmät eivät. Tähän vaikuttaa se, miten algoritmi käsittelee tilanteita, joissa verrataan yhtä suuria avaimia. Esimerkiksi, jos järjestän sähköpostiviestini ensin ajan suhteen ja sitten lähettäjän suhteen, stabiilissa menetelmässä saman lähettäjän viestit pysyvät aikajärjestyksessä. Kokeile tätä omalla sähköpostiohjelmallasi. Jos lajiteltavat avaimet ovat kaikki erilaisia, ei stabiiliudella ole merkitystä Tätä seikkaa hyödyntämällä kaikista järjestämismenetelmistä voidaan tehdä stabiileja (miten?) 6.10.2015 Tietorakenteet ja algoritmit - syksy 2015 10
Järjestämismenetelmän valintaan vaikuttavia tekijöitä ovat: tiedon määrä (järjestettävän aineiston koko) järjestämismenetelmän tehokkuus (O(N 2 ), O(NlogN), O(N)) avaimen laatu, esim. integer / string ulkoisen tilan tarve (O(N), O(1)) onko menetelmä stabiili vai ei alkioiden vaihtojen kustannukset (~ tietoalkion koko ) järjestysaste menetelmän monimutkaisuus 6.10.2015 Tietorakenteet ja algoritmit - syksy 2015 11
6.2 Yksinkertaiset menetelmät Järjestämisen perusmenetelmät perustuvat vierekkäisten alkioiden vertailuun ja niiden vaihtamiseen keskenään tai siirtämiseen. 6.2.1 Valintajärjestäminen 6.2.2 Lisäysjärjestäminen (Kuplajärjestäminen) EI KANNATA KÄYTTÄÄ 6.10.2015 Tietorakenteet ja algoritmit - syksy 2015 12
6.2.1 Valintajärjestäminen (selec0on sort) Etsitään taulukon pienin alkio ja sijoitetaan se taulukon alkuun vaihtamalla sen paikka 1. alkion kanssa. Seuraavaksi etsitään jäljellä olevasta osuudesta taulukon toisiksi pienin alkio ja vaihdetaan se 2. alkion kanssa, jne. 6.10.2015 Tietorakenteet ja algoritmit - syksy 2015 13
6.2.1 Valintajärjestäminen (selec0on sort) Vertailuja O(N 2 ). Vaihtoja tarvitaan vain N-1 kappaletta. Tällä on merkitystä, jos vaihto aiheuttaa jonkin työlään operaation tai keskenään vaihdettavat tietueet ovat suuria. Viimeksi mainittu asia voidaan kiertää epäsuoralla järjestämisellä, jossa järjestetäänkin hakemisto eikä itse tietueita (vaihdetaankin osoittimia eikä tietueita). for (i = 0; i < N-1; i++) { } min = i; for (j = i+1; j < N; j++) if (a[j] < a[min]) temp = a[min]; a[min] = a[i]; a[i] = temp; min = j; 6.10.2015 Tietorakenteet ja algoritmit - syksy 2015 14
6.2.1 Valintajärjestäminen (selec0on sort) Minua hämää hieman tämä tehtävä: "Kuinka monta kertaa valintajärjestämisessä alkioita vaihdetaan keskenään (swap) kun järjestetään n alkiota?" Jos n alkiota on jo järjestyksessä, niin vaihtaako se siinä tapauksessa "itsensä" vai miksi parhainkin tapaus on O(n)? CSE-A1140 for (i = 0; i < N-1; i++) { } min = i; for (j = i+1; j < N; j++) if (a[j] < a[min]) temp = a[min]; a[min] = a[i]; a[i] = temp; min = j; 6.10.2015 Tietorakenteet ja algoritmit - syksy 2015 15
6.2.2 Lisäysjärjestäminen (inser0on sort) Järjestettävä aineisto jakautuu kahteen osaan, jo järjestettyyn osaan ja sen jälkeiseen järjestämättömään osaan Joka askelella otetaan järjestämättömän osan ensimmäinen alkio, verrataan sitä askel askeleelta järjestettyyn osaan, kunnes oikea kohta löytyy. Alkio sijoitetaan tähän väliin, jolloin järjestynyt osa on kasvanut yhdellä 6.10.2015 Tietorakenteet ja algoritmit - syksy 2015 16
Animaa0o http://www.ee.ryerson.ca/~courses/ coe428/sorting/insertionsort.html 6.10.2015 Tietorakenteet ja algoritmit - syksy 2015 17
for (i = 1; i < N; i++) /* i: askeltaja */ { temp = a[i]; /* temp: tilapäissäilö */ j = i; /* j: askeltaja */ while (j > 0 && a[j-1] > temp) { a[j] = a[j-1]; j--; } a[j] = temp; } Testi j > 0 on välttämätön, jotta indeksi ei juokse taulukon ulkopuolelle 6.10.2015 Tietorakenteet ja algoritmit - syksy 2015 18
Testi j > 0 voidaan välttää sijoittamalla paikkaan a[0] vartiosotilas (sentinel), joka on arvoltaan pienempi kuin taulukon muut alkiot. Nyt while-silmukka ei juokse taulukon alarajasta läpi. Samalla koodi yksinkertaistuu ja tehostuu hieman. a[0] = INT_MIN; for (i = 2; i <= N; i++) /* askeltaja */ { temp = a[i]; /* tilapäissäilö */ j = i; /* askeltaja */ while (a[j-1] > temp) { a[j] = a[j-1]; j--; } a[j] = temp; } 6.10.2015 Tietorakenteet ja algoritmit - syksy 2015 19
Järjestettävä data on alkioissa a[1] - a[n] Sisäsilmukka suoritetaan keskimäärin N 2 /2 kertaa Jos data on melkein järjestyksessä, algoritmi toimii lineaarisessa ajassa. Lisäysjärjestämistä käytetään usein manuaalisessa järjestämisessä, esim. postinjakajilla. Tällöin lisäyskohta haetaan älykkäämmin ja lisäys voidaan toteuttaa yhdellä operaatiolla => algoritmin tehokkuus on noin N log N manuaalisessa toteutuksessa 6.10.2015 Tietorakenteet ja algoritmit - syksy 2015 20
Perusalgoritmien yleinen tehokkuus Analyysiä: algoritmi, joka järjestää alkioita vaihtamalla vierekkäisiä alkioita keskenään, vaatii pahimmassa tapauksessa aikaa Ω(N 2 ) Oletetaan järjestämätön lista arvoja, joiden joukossa ei ole duplikaatteja Inversio on tapaus, jossa kaksi listan alkiota on väärässä järjestyksessä. Esim. i < j, mutta a[i] > a[j]. Teoreema 6.1. Inversioiden lukumäärä satunnaisessa listassa on keskimäärin N (N-1) / 4. 6.10.2015 Tietorakenteet ja algoritmit - syksy 2015 21
Todistus: Jokaista listaa L kohti on olemassa yksikäsitteinen käänteislista L R Oletetaan pari (x, y), x > y listassa L. Tällöin pari (y, x), x > y esiintyy käänteislistassa L R Yo. pari on inversio täsmälleen yhdessä listoista L ja L R Mahdollisten parien lukumäärä listassa yhteensä on (N- 1) + (N- 2) +... + 1 = N (N- 1) / 2 Keskimääräinen määrä inversioita listaa kohti on siis edellisen puolikas => Inversioita on siis keskimäärin N (N- 1) / 4 kappaletta 6.10.2015 Tietorakenteet ja algoritmit - syksy 2015 22
Teoreema 6.2. Mikä tahansa algoritmi, joka järjestää alkioita vaihtamalla vierekkäisiä alkioita keskenään, vaatii pahimmassa tapauksessa aikaa Ω (N 2 ) Todistus: Teoreema 6.1: Inversioiden lukumäärä on N(N-1)/4 = Ω (N 2 ) Jokainen vierekkäisten alkioiden vaihto poistaa vain yhden inversion => Tarvitaan Ω(N 2 ) vaihtoa 6.10.2015 Tietorakenteet ja algoritmit - syksy 2015 23
Tämä on ns. alarajatodistus (lower bound proof), joka pätee kaikille em. ehdon täyttäville algoritmeille, riippumatta siitä, onko näitä edes keksitty. Tehokkaammat järjestämisalgoritmit perustuvat siihen, että ne siirtävät alkioita kerralla kauemmas ja siten poistavat ker- ralla useampia kuin yhden inversion. 6.10.2015 Tietorakenteet ja algoritmit - syksy 2015 24
6.3 Lomitusjärjestäminen (merge sort) Yhdistetään järjestäminen ja lomitus: 1. Jaa tiedosto kahtia 2. Järjestä puoliskot rekursiivisesti 3. Yhdistele puoliskot yhdeksi (lineaarinen merging) Hajoita ja hallitse (Divide & Conquer) -algoritmi (kuten myös quicksort) T(N) = 2T(N/2) + N, T(1) = 1 Tehokkuus aina N log N 6.10.2015 Tietorakenteet ja algoritmit - syksy 2015 25
Mergesort visualisa0on http://www.ee.ryerson.ca/~courses/coe428/sorting/ mergesort.html Jos joku kaipaa suhteellisen perusteellista selitystä joidenkin järjestämismenetelmien toiminnasta, niin suosittelen katsomaan Harvardin videopätkiä. esimerkiksi quick sort ja merge sort. Useimmista menetelmistä taitaa löytyä video. 6.10.2015 Tietorakenteet ja algoritmit - syksy 2015 26
6.3.1 Lomitus (merging) Kaksi järjestyksessä olevaa tiedostoa yhdistetään uudeksi tiedostoksi, joka on myös järjestyksessä Tyyppitilanne: Rekisteriin, joka on järjestetty, lisätään uusia elementtejä Ne kootaan ensin tapahtumatiedostoon (myös järjestyksessä) Nämä yhdistetään määräajoin Yhdistely lineaarisessa ajassa, two-way merging: a[0..m-1], b[0..n-1] => c[0..m+n-1] 6.10.2015 Tietorakenteet ja algoritmit - syksy 2015 27
Valitaan aina pienin alkio a:sta ja b:stä ja kirjoitetaan se c:hen. Taulukkojen lopussa vahtisotilaat. i = 0; j = 0; /* i,j: askeltajat */ a[m] = INT_MAX; b[n] = INT_MAX; for (k = 0; k < M + N; k++) /* k: askeltaja */ if ( a[i] < b[j] ) { c[k] = a[i]; /* c: järjestelijä */ i = i + 1; } else { c[k] = b[j]; j = j + 1; } Vaatii aikaa O(M + N) 6.10.2015 Tietorakenteet ja algoritmit - syksy 2015 28
Mergesort taulukoille http://en.wikipedia.org/wiki/merge_sort 6.10.2015 Tietorakenteet ja algoritmit - syksy 2015 29
Mergesort linkitetyille listoille: link mergesort(link alkuosa; int N) /* alkuosa: kulkija */ { /* N: askeltaja */ link c, loppuosa; /* c: askeltaja, loppuosa: tilapäissäilö */ int i; /* i: askeltaja */ } if (alkuosa->next == z) return alkuosa; else { c = alkuosa; for (i = 2; i <= (N / 2); i++) // etsitään loppuosan edeltäjä c = c->next; loppuosa = c->next; c->next = z; return merge( mergesort(alkuosa, N / 2), mergesort(loppuosa, N-(N/2))); } 6.10.2015 Tietorakenteet ja algoritmit - syksy 2015 30
Mergesort linkitetyille listoille: link mergesort(link alkuosa; int N) /* alkuosa: kulkija */ { /* N: askeltaja */ link c, loppuosa; /* c: askeltaja, loppuosa: tilapäissäilö */ int i; /* i: askeltaja */ } if (alkuosa->next == z) return alkuosa; else { c = alkuosa; for (i = 2; i <= (N / 2); i++) // etsitään loppuosan edeltäjä c = c->next; loppuosa = c->next; c->next = z; return merge( mergesort(alkuosa, N / 2), mergesort(loppuosa, N-(N/2))); } 6.10.2015 Tietorakenteet ja algoritmit - syksy 2015 31
link merge(link a; link b){...} two-way merge linkitetyille listoille 6.10.2015 Tietorakenteet ja algoritmit - syksy 2015 32
Yhteenveto: lomitusjärjestäminen N log N -algoritmi Lyhyt sisin silmukka Yleensä stabiili Mergesort soveltuu hyvin tilanteisiin, joissa tietoon päästään käsiksi vain peräkkäisjärjestyksessä (esim. linkitetyt listat, ulkoiset tiedostot). Toteutus taulukolla vaatii ylimääräisen muistitilan Voidaan toteuttaa myös ei-rekursiivisena 6.10.2015 Tietorakenteet ja algoritmit - syksy 2015 33
6.4 Pikajärjestäminen (Quicksort) Kehittäjä C.A.R. Hoare 1960 Tunnetuin ja yleisin tehokas järjestämismenetelmä Keskimääräinen tehokkuus N log N Pahin tapaus N 2, mutta se voidaan välttää pienillä virityksillä Kohtuullisen helppo toteuttaa perusmuodossaan 6.10.2015 Tietorakenteet ja algoritmit - syksy 2015 34
PERUSIDEA: Partitionti muokkaa taulukkoa a[left..right] ja hakee siitä kohdan i siten, että 1) alkio a[i] on kohdallaan 2) alkiot a[left].. a[i-1] a[i] 3) alkiot a[i+1]..a[right] a[i] Tämän jälkeen partitiointi suoritetaan molemmille puoliskoille rekursiivisesti 6.10.2015 Tietorakenteet ja algoritmit - syksy 2015 35
Quicksort on divide & conquer -algoritmi void quicksort(int left; int right) { /* left, right: kulkijat */ int i; /* i: kiintoarvo */ if (right > left) { i = partition(left, right); quicksort(left, i-1); quicksort(i+1, right); } } 6.10.2015 Tietorakenteet ja algoritmit - syksy 2015 36
(Erään) partitiofunktion toiminta: 1. Valitaan alueen oikeasta reunasta partitioalkio (pivot-alkio) 2. Verrataan siihen alkioita yhtäaikaa taulukon vasemmasta ja oikeasta reunasta alkaen 1. Vasemmasta reunasta osoitin kasvaa oikealle ja oikeasta reunasta vasemmalle. 2. Osoitin pysähtyy, kun vasemmalta löytyy pivotia suurempi ja oikealta vastaavasti pivotia pienempi alkio. 3. Nämä alkiot vaihdetaan keskenään. => Vaihdetaan vasemmalla olevat sitä suuremmat alkiot oikealla oleviin sitä pienempiin alkioihin 3. Kun osoittimet menevät ristiin, vaihdetaan pivot siihen, mihin vasenosoitin pysähtyi. 4. Pivot-alkion kanssa yhtäsuuret alkiot osallistuvat vaihtoon (ei välttämätöntä, mutta tasapainottaa algoritmin toimintaa) 6.10.2015 Tietorakenteet ja algoritmit - syksy 2015 37
... b a Q... B y z y P swap... b a B... Q y z y P swap 6.10.2015 Tietorakenteet ja algoritmit - syksy 2015 38
int partition(int left; int right) { int i, j, pivot, apu; pivot = a[right]; /* pivot: kiintoarvo */ i = left - 1; /* i: askeltaja */ j = right; /* j: askeltaja */ do { do i++; while (a[i] < pivot); do j--; while (a[j] > pivot); apu = a[i]; a[i] = a[j]; a[j] = apu; /* apu: tilapäissäilö */ } while (j > i); apu = a[i]; a[i] = a[right]; a[right] = apu; return i; } Huom! Vertailu a[j] > pivot riittää, jos taulukon alkuun sijoitetaan vartiosotilas (eli pienin mahdollinen alkio) 6.10.2015 Tietorakenteet ja algoritmit - syksy 2015 39
Pahin tapaus Kun partitionti epäonnistuu Toiseen puoleen jää N-k alkiota ja toiseen vain k (vakio) << N Jos tämä tapahtuu (lähes) jokaisella partitiointikierroksella (Θ(N) operaatio) saadaan rekursioyhtälö (kun k=1) T(N) = T(N-1) + N, T(1) = 1 T(N) = N + (N-1) + (N-2) + + 1 = Θ(N 2 ) Epätasapainoinen partitiointi johtaa neliölliseen käyttäytymiseen! Tehtävä: Anna esimerkki syötteestä, jolla tämä tapahtuu. 6.10.2015 Tietorakenteet ja algoritmit - syksy 2015 40
Ongelmia ja virityksiä 1) Jos taulukko on valmiiksi järjestyksessä, partitiot degeneroituvat ja kyseessä on N 2 algoritmi Valitaan partitioelementti mediaani-kolmesta menetelmällä tai satunnaisesti 2) Sama tilanne johtaa siihen, että suoritetaan N rekursiokutsua, jolloin ajonaikaisessa pinossa on N pinokehystä Poistetaan rekursio ja työnnetään suuremman alueen rajat itse pinoon (pienempi käsitellään suoraan). Pinon kooksi tulee korkeintaan log N. 6.10.2015 Tietorakenteet ja algoritmit - syksy 2015 41
3) Rekursio suoritetaan pienillekin partitioille tai Vaihdetaan lisäysjärjestämiseen, kun right - left < M (kutsutaan lisäysjärjestämistä O(N) kertaa) Lopetetaan vastaavassa tilanteessa quicksort ja järjestetään lopuksi koko taulukko lisäysjärjestämisellä (kutsutaan lisäysjärjestämistä yhden kerran) 6.10.2015 Tietorakenteet ja algoritmit - syksy 2015 42
Paras tapaus Partitiointi jakaa aineiston tasan kahteen osaan T(N) = 2T(N/2) + N, T(2) = 1 ratkaistaan esim. sijoituksella N=2 k, ja jakamalla molemmat puolet 2 k :lla, kuten aiemmin on osoitettu. T(N) = O(NlogN) 6.10.2015 Tietorakenteet ja algoritmit - syksy 2015 43
6.4.1 Valikoin0 (selec0on) "Hae mielivaltaisessa järjestyksessä olevasta tietoaineistosta k:nneksi suurin alkio. Esim. "Hae aineiston mediaani Täsmällinen järjestäminen vie turhaa aikaa Prioriteettijonon avulla O(N + k log N) esim. mediaanin haku O(N log N) Jos k on pieni, valintajärjestäminen on hyvä menetelmä Mielivaltaiselle aineistolla voidaan soveltaa quicksortin idea: Partitioidaan aineisto ja otetaan jatkoon se osuus, johon k sisältyy. 6.10.2015 Tietorakenteet ja algoritmit - syksy 2015 44
int quickselect(int left; int k; int right) { /* left, right: kulkijat; k: kiintoarvo */ int i = -1; /* i: kiintoarvo */ if (left < right) { i = partition(left, right); if (k < i) return quickselect(left, k, i-1); if (k > i) return quickselect(i+1, k, right); } return i; } Keskimääräinen kompleksisuus O(N) 6.10.2015 Tietorakenteet ja algoritmit - syksy 2015 45
Erilaisia 0lanteita Osalla algoritmeista toiminta vaihtelee sen mukaan, missä järjestyksessä alkuperäinen taulukko on. http://www.sorting-algorithms.com/ 6.10.2015 Tietorakenteet ja algoritmit - syksy 2015 46
6.10.2015 Tietorakenteet ja algoritmit - syksy 2015 47
6.5 Jakauman laskeminen (Distribu0on coun0ng) N tietuetta, joissa kokonaislukuavaimia välillä 0..M-1. N >> M; Esim. a = <x,y,x,y,z,y,z>, N = S = 7, M = 3 "Etsitään samojen avainarvojen alueet taulukossa" 1) Aluelaskurien alustus; count = <0,0,0> for (i=0; i<m; i++) count[i] = 0; 2) Lasketaan avainten jakauma; count = <2,3,2> for (i=0; i<n; i++) count[a[i]]++; 6.10.2015 Tietorakenteet ja algoritmit - syksy 2015 48
3) Lasketaan kumulatiivinen jakauma; count = < 2,5,7> for (j=1; j<m; j++) count[j] += count[j-1]; 4) Sijoitetaan avaimet alueisiinsa; t = < x,x,y,y,y,z,z > (a=<x,y,x,y,z,y,z>) for (i=n-1; i>=0; i--) { t[ count[a[i]]-1 ] = a[i]; // t[6]=z,t[4]=y,t[5]=z count[a[i]]--; } 5) Lajiteltu aineisto on nyt aputaulukossa t = a 6.10.2015 Tietorakenteet ja algoritmit - syksy 2015 49
6.6 Kantalukujärjestäminen (radix sor0ng) Järjestäminen perustuu siihen, että käsitellään ja vertaillaan avaimen osia Esimerkki: Avaimet ovat kokonaislukuja välillä 0-999. Järjestetään dekadeittain. Tietokoneessa avaimia käsitellään binäärilukuina eli järjestetään bittipositio/bittiryhmä kerrallaan Ominaisuuden hyväksikäyttö vaatii tehokasta pääsyä bittitason toimintoihin. Jos avaimet ovat lyhyitä, kannattaa käyttää jakauman laskemismenetelmää. Tarvittavan aputaulukon count koko on 2 b. 6.10.2015 Tietorakenteet ja algoritmit - syksy 2015 50
Tärkeimmät menetelmät ovat: digitaalinen vaihtojärjestäminen (O(N log N)) suora digitaalinen järjestäminen (O(N)) 6.10.2015 Tietorakenteet ja algoritmit - syksy 2015 51
6.6.1 Digitaalinen vaihtojärjestäminen (radix exchange sort) Tiedot järjestetään bittipositio kerrallaan vasemmalta oikealle Kukin positio jaetaan kahteen osaan keräämällä nollat ja ykköset omiin ryhmiin Osat järjestetään edelleen rekursiivisesti seuraavasta bitistä lähtien Jos osan kooksi tulee 1, sitä ei järjestetä eteenpäin 6.10.2015 Tietorakenteet ja algoritmit - syksy 2015 52
Esimerkki 1 010011001 101100101 010010000 101110001 111000101 010011001 010010000 101100101 101110001 111000101 6.10.2015 Tietorakenteet ja algoritmit - syksy 2015 53
Tehokkuus N log N tai N*b (b = bittimäärä) Jos avaimet ovat satunnaisesti jakautuneita, ei kaikkia bittejä tarvitse tutkia log N bittiä riittää, jolloin menetelmä on jopa nopeampi kuin Quicksort Samoilla avaimilla käydään läpi kaikki bitit, jolloin tehokkuus laskee 6.10.2015 Tietorakenteet ja algoritmit - syksy 2015 54
6.6.2 Suora digitaalinen järjestäminen (straight radix sort) Järjestetään bittipositio kerrallaan oikealta vasemmalle Käyttää jakauman laskemista M:n bitin osuuksille (M 1) Perustuu osaltaan siihen, että jakauman laskeminen on stabiili menetelmä Jos M on yksi, järjestetään bitti kerrallaan. Tehokkuus paranee, jos M kasvaa Hyvä suositus on M = b / 4, jossa b on avainten bittien lukumäärä 6.10.2015 Tietorakenteet ja algoritmit - syksy 2015 55
Esimerkki 2 010011001 010010000 111000101 010010000 101100101 010011001 010010000 010011001 010010000 101110001 010011001 101100101 101110001 101100101 101100101 101110001 111000101 111000101 101110001 111000101 6.10.2015 Tietorakenteet ja algoritmit - syksy 2015 56
Esim. 32-bittisiä kokonaislukuja järjestetään tavu kerrallaan Tehokkuusluku on N, eli kyseessä on lineaarinen menetelmä Mutta: vaatii lisätilaa 2 b alkiota (esim. 2 8 = 256) hidas sisin luuppi 6.10.2015 Tietorakenteet ja algoritmit - syksy 2015 57
Seuraavalla kerralla 13.10.2014 Puurakenteet ja puiden läpikäyntialgoritmit Aihe prioriteettijonot jää itseopiskelun varaan! 6.10.2015 Tietorakenteet ja algoritmit - syksy 2015 58
6.7 Järjestämismenetelmän valinnasta Yhteenveto tehokkuusluvuista W(N) A(N) Selection sort N 2 /2 N 2 /2 Insertion sort N 2 /2 N 2 /4 Distribution counting c 0 N c 0 N Quicksort N 2 /2 1.38NlogN Radix exchange sort c 0 NlogN c 0 NlogN Straight radix sort c 0 N c 0 N Heapsort 2.0NlogN ei tietoa Mergesort 1.0NlogN 1.0NlogN 6.10.2015 Tietorakenteet ja algoritmit - syksy 2015 59
Huom! Kaikki laskettavat operaatiot eivät ole keskenään suoraan verrannollisia Kaikille algoritmeille ei löytynyt vakiokertoimen c 0 arvoa 6.10.2015 Tietorakenteet ja algoritmit - syksy 2015 60
Muita ominaisuuksia Lisämuistin tarve stabiilius Selection sort Ei On Insertion sort Ei On Distribution count N + count On Quicksort Ei Ei Radix exchange sort Ei Ei Straight radix sort N + 2 m On Heapsort (ei käsitelty tässä) Ei Ei Mergesort N tai osoitt. On Huom! Myös rekursio aiheuttaa yleiskustannuksia tilankäyttöön Mergesort voidaan toteuttaa ilman lisätilaa (monimutkaista) Quicksort ja Radix exhange sort voidaan toteuttaa stabiileina (monimutkaista) 6.10.2015 Tietorakenteet ja algoritmit - syksy 2015 61
Tehokkuusluku ei kerro kaikkea! On muitakin näkökulmia: Selection sort Yksinkertainen Pienelle tiedostolle, jossa suuret tietueet Voidaan soveltaa valikointiongelmaan, kun k on pieni Insertion sort Yksinkertainen Hyvä menetelmä pienille tiedostoille (N<50) Tehokas (lineaarinen) menetelmä, jos tiedosto 'melkein järjestyksessä 6.10.2015 Tietorakenteet ja algoritmit - syksy 2015 62
Heapsort Taattu N log N Sopii hyvin ongelmaan, jossa halutaan löytää aineistosta k pienintä alkiota (k << N) Mergesort Taattu N log N Vaatii lisätilan Sopii tilanteisiin, joissa dataa käsitellään peräkkäisesti Lomitus on ulkoisten järjestämismenetelmien perusalgoritmeja Quicksort Käytännön valinta useimpiin suuriin sovelluksiin Partitioelementtiä ei tule valita triviaalisti laidoista Viritykset ohjelmoitava huolellisesti Ei käy, jos tarvitaan stabiiliutta Huolelliset viritykset, jos ehdoton vaatimus NlogN-käyttäytymisestä Voidaan soveltaa valikointiongelmaan lineaarisessa ajassa 6.10.2015 Tietorakenteet ja algoritmit - syksy 2015 63
Distribution counting Yksinkertainen Tilanteisiin, joissa avainavaruus pienempi kuin avainten määrä Vaatii lisätilaa Radix exchange sort Implementaatio edellyttää pääsyä bitti-informaatioon kiinni Voidaan toteuttaa myös muissa kantaluvuissa (bucket sort) Tehokas, jos aineisto satunnainen Tehokkuus kärsii, jos aineistossa runsaasti samoja avainarvoja Ei kannata käyttää merkkijonoavaimille Straight radix sort Implementaatio edellyttää pääsyä bitti/tavuinformaatioon kiinni Tehokas Vaatii lisätilan, joka voi olla rasite suurilla tiedostoilla Ei kannata käyttää merkkijonoavaimille 6.10.2015 Tietorakenteet ja algoritmit - syksy 2015 64