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. <a1, a2, ..., an> Tuloste: sellainen lukusarjan permutaatio <a1´, a2´, ..., an´>, jolle a1´ ≤ a2´ ≤ ... ≤ an´ Sovelluksia on lukemattomia: henkilörekisterit puhelinluettelo tilitapahtumat sähköpostiohjelma graafiset koordinaatit … 6.10.2015 Tietorakenteet ja algoritmit - syksy 2015 3 Perusajatukset: String key1 Int key2 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 key1 Int key2 String key1 Int key2 3 a3 Hakemisto: 6.10.2015 String key1 2 a4 a1 a4 a2 String key1 4 a2 a3 Int key2 … Int key2 1 a1 n e d i e tu e i t n aa d i o h ra t s b is o A p t e e t t i o os 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 key1 Int key2 String key1 3 3 Hakemisto: 6.10.2015 Int key2 String key1 2 4 1 4 2 String key1 4 2 3 Int key2 Int key2 1 1 … 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 key1 Int key2 String key1 3 3 Hakemisto: 6.10.2015 Int key2 String key1 2 4 2 3 4 String key1 4 2 1 Int key2 … Int key2 1 1 ton s i m e k ha n a a t s a siin i Aino e u t e i t et s k u a t t i vi vat. u t t u u m 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( N2 ) 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(N2), O(NlogN), O(N)) avaimen laatu, esim. integer / string 6.10.2015 ulkoisen tilan tarve (O(N), O(1)) onko menetelmä stabiili vai ei alkioiden vaihtojen kustannukset (~ tietoalkion ”koko”) järjestysaste menetelmän monimutkaisuus 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(N2). 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). 6.10.2015 for (i = 0; i < N-1; i++) { min = i; for (j = i+1; j < N; j++) if (a[j] < a[min]) min = j; temp = a[min]; a[min] = a[i]; a[i] = temp; } 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 6.10.2015 for (i = 0; i < N-1; i++) { min = i; for (j = i+1; j < N; j++) if (a[j] < a[min]) min = j; temp = a[min]; a[min] = a[i]; a[i] = temp; } 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 N2/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 Ω(N2)” 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 LR – Oletetaan pari (x, y), x > y listassa L. Tällöin pari (y, x), x > y esiintyy käänteislistassa LR – Yo. pari on inversio täsmälleen yhdessä listoista L ja LR – 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 Ω (N2) Todistus: Teoreema 6.1: Inversioiden lukumäärä on N(N-1)/4 = Ω (N2) Jokainen vierekkäisten alkioiden vaihto poistaa vain yhden inversion => Tarvitaan Ω(N2) 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 kerralla 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; a[M] = INT_MAX; /* i,j: askeltajat */ 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 • • • • 6.10.2015 Tunnetuin ja yleisin tehokas järjestämismenetelmä Keskimääräinen tehokkuus N log N Pahin tapaus N2, mutta se voidaan välttää pienillä virityksillä Kohtuullisen helppo toteuttaa perusmuodossaan 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] • 6.10.2015 Tämän jälkeen partitiointi suoritetaan molemmille puoliskoille rekursiivisesti 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]; return i; a[right] = apu; } 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 = Θ(N2) 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 N2 – 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 ⇒ Vaihdetaan lisäysjärjestämiseen, kun right - left < M (kutsutaan lisäysjärjestämistä O(N) kertaa) tai ⇒ 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=2k, ja jakamalla molemmat puolet 2k: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; } • 6.10.2015 Keskimääräinen kompleksisuus O(N) 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. Esim. a = <x,y,x,y,z,y,z>, N = |S| = 7, M = 3 • "Etsitään samojen avainarvojen alueet taulukossa" N >> M; 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 010011001 101100101 010010000 010010000 101100101 101110001 101110001 111000101 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 2b alkiota (esim. 28 = 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) Selection sort N2 /2 Insertion sort N2 /2 Distribution counting c0N Quicksort N2 /2 Radix exchange sort c0NlogN Straight radix sort c0N Heapsort 2.0NlogN Mergesort 1.0NlogN 6.10.2015 Tietorakenteet ja algoritmit - syksy 2015 A(N) N2 /2 N2 /4 c0N 1.38NlogN c0NlogN c0N ei tietoa 1.0NlogN 59 Huom! • Kaikki laskettavat operaatiot eivät ole keskenään suoraan verrannollisia • Kaikille algoritmeille ei löytynyt vakiokertoimen c0 arvoa 6.10.2015 Tietorakenteet ja algoritmit - syksy 2015 60 Muita ominaisuuksia Selection sort Insertion sort Distribution count Quicksort Radix exchange sort Straight radix sort Heapsort (ei käsitelty tässä) Mergesort Lisämuistin tarve Ei Ei N + count Ei Ei N + 2m Ei N tai osoitt. stabiilius On On On Ei Ei On Ei On Huom! • • • 6.10.2015 Myös rekursio aiheuttaa yleiskustannuksia tilankäyttöön Mergesort voidaan toteuttaa ilman lisätilaa (monimutkaista) Quicksort ja Radix exhange sort voidaan toteuttaa stabiileina (monimutkaista) 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
© Copyright 2024