A TIETORAKENTEET JA ALGORITMIT

Samankaltaiset tiedostot
A TIETORAKENTEET JA ALGORITMIT

TIE Tietorakenteet ja algoritmit 25

A TIETORAKENTEET JA ALGORITMIT

811312A Tietorakenteet ja algoritmit III Lajittelualgoritmeista

Algoritmit 1. Luento 11 Ti Timo Männikkö

TAMPEREEN TEKNILLINEN YLIOPISTO

9 Erilaisia tapoja järjestää

4 Tehokkuus ja algoritmien suunnittelu

1 Erilaisia tapoja järjestää

TAMPEREEN TEKNILLINEN YLIOPISTO

Algoritmit 1. Luento 10 Ke Timo Männikkö

Tietorakenteet, laskuharjoitus 10, ratkaisuja. 1. (a) Seuraava algoritmi tutkii, onko jokin luku taulukossa monta kertaa:

Algoritmit 1. Luento 12 Ke Timo Männikkö

Algoritmit 1. Luento 12 Ti Timo Männikkö

Tietorakenteet ja algoritmit. Järjestäminen. Ari Korhonen

811312A Tietorakenteet ja algoritmit Kertausta kurssin alkuosasta

811312A Tietorakenteet ja algoritmit Kertausta kurssin alkuosasta

58131 Tietorakenteet ja algoritmit (kevät 2016) Ensimmäinen välikoe, malliratkaisut

Pikalajittelu: valitaan ns. pivot-alkio esim. pivot = oikeanpuoleisin

Kierros 2: Järjestämisalgoritmeja

Algoritmit 2. Luento 2 To Timo Männikkö

Algoritmit 2. Luento 3 Ti Timo Männikkö

Ohjelmoinnin perusteet Y Python

On annettu jono lukuja tai muita alkioita, joiden välille on määritelty suuruusjärjestys. Tehtävänä on saattaa alkiot suuruusjärjestykseen.

A TIETORAKENTEET JA ALGORITMIT

Tietorakenteet ja algoritmit - syksy

Algoritmit 2. Luento 3 Ti Timo Männikkö

811312A Tietorakenteet ja algoritmit , Harjoitus 2 ratkaisu

Algoritmit 2. Luento 7 Ti Timo Männikkö

Algoritmit 1. Luento 3 Ti Timo Männikkö

CS-A1140 Tietorakenteet ja algoritmit

Ohjelmoinnin peruskurssi Y1

Tietorakenteet ja algoritmit syksy Laskuharjoitus 1

58131 Tietorakenteet ja algoritmit (kevät 2013) Kurssikoe 2, , vastauksia

Mukautuvat järjestämisalgoritmit

Algoritmit 2. Luento 2 Ke Timo Männikkö

1. (a) Seuraava algoritmi tutkii, onko jokin luku taulukossa monta kertaa:

f(n) = Ω(g(n)) jos ja vain jos g(n) = O(f(n))

Algoritmit 1. Demot Timo Männikkö

Tietorakenteet ja algoritmit Johdanto Lauri Malmi / Ari Korhonen

Algoritmit 2. Luento 8 To Timo Männikkö

A TIETORAKENTEET JA ALGORITMIT KORVAAVAT HARJOITUSTEHTÄVÄT 3, DEADLINE KLO 12:00

58131 Tietorakenteet ja algoritmit (kevät 2014) Uusinta- ja erilliskoe, , vastauksia

8. Lajittelu, joukot ja valinta

Tämä on helpompi ymmärtää, kun tulkitaan keko täydellisesti tasapainotetuksi binääripuuksi, jonka juuri on talletettu taulukon paikkaan

A TIETORAKENTEET JA ALGORITMIT

5 Kertaluokkamerkinnät

ALGORITMIT 1 DEMOVASTAUKSET KEVÄT 2012

Olkoon S(n) kutsun merge-sort(a, p, q) tilavaativuus kun p q + 1 = n. Oletetaan merge toteutetuksi vakiotyötilassa (ei-triviaalia mutta mahdollista).

58131 Tietorakenteet (kevät 2009) Harjoitus 9, ratkaisuja (Antti Laaksonen)

Liitosesimerkki Tietokannan hallinta, kevät 2006, J.Li 1

Liitosesimerkki. Esim R1 R2 yhteinen attribuutti C. Vaihtoehdot

Ohjelmoinnin perusteet Y Python

811312A Tietorakenteet ja algoritmit, , Harjoitus 7, ratkaisu

Algoritmit 1. Luento 5 Ti Timo Männikkö

58131 Tietorakenteet ja algoritmit (syksy 2015)

Ohjelmoinnin perusteet Y Python

Nopea kertolasku, Karatsuban algoritmi

Algoritmit 1. Demot Timo Männikkö

11. Javan toistorakenteet 11.1

Perusteet. Pasi Sarolahti Aalto University School of Electrical Engineering. C-ohjelmointi Kevät Pasi Sarolahti

Algoritmit 2. Luento 14 Ke Timo Männikkö

Perusteet. Pasi Sarolahti Aalto University School of Electrical Engineering. C-ohjelmointi Kevät Pasi Sarolahti

ja λ 2 = 2x 1r 0 x 2 + 2x 1r 0 x 2

Algoritmit 1. Luento 10 Ke Timo Männikkö

2 Haku ja lajittelu. 2.1 Luvun hakeminen taulukosta X?? n-1. Haku ja lajittelu 35

Ohjelmointi 1 Taulukot ja merkkijonot

Luku 6. Dynaaminen ohjelmointi. 6.1 Funktion muisti

Algoritmi on periaatteellisella tasolla seuraava:

Algoritmit 2. Demot Timo Männikkö

811312A Tietorakenteet ja algoritmit, , Harjoitus 3, Ratkaisu

Algoritmit 2. Luento 13 Ti Timo Männikkö

3 Lajittelualgoritmeista

ITKP102 Ohjelmointi 1 (6 op)

Algoritmit 1. Luento 1 Ti Timo Männikkö

Kääreluokat (oppikirjan luku 9.4) (Wrapper-classes)

Hakupuut. tässä luvussa tarkastelemme puita tiedon tallennusrakenteina

Tehtävän V.1 ratkaisuehdotus Tietorakenteet, syksy 2003

Tiraka, yhteenveto tenttiinlukua varten

Harjoitus 4 (viikko 47)

10. Painotetut graafit

Algoritmit 1. Demot Timo Männikkö

(p j b (i, j) + p i b (j, i)) (p j b (i, j) + p i (1 b (i, j)) p i. tähän. Palaamme sanakirjaongelmaan vielä tasoitetun analyysin yhteydessä.

Algoritmit 1. Luento 14 Ke Timo Männikkö

12. Javan toistorakenteet 12.1

lähtokohta: kahden O(h) korkuisen keon yhdistäminen uudella juurella vie O(h) operaatiota vrt. RemoveMinElem() keossa

ITKP102 Ohjelmointi 1 (6 op)

13. Loogiset operaatiot 13.1

5. Keko. Tietorakenne keko eli kasa (heap) on tehokas toteutus abstraktille tietotyypille prioriteettijono, jonka operaatiot ovat seuraavat:

811312A Tietorakenteet ja algoritmit, VI Algoritmien suunnitteluparadigmoja

Tietorakenteet, laskuharjoitus 3, ratkaisuja

Tietorakenteet ja algoritmit. Kertaus. Ari Korhonen

1 Puu, Keko ja Prioriteettijono

Mediaanisuodattimet. Tähän asti käsitellyt suodattimet ovat olleet lineaarisia. Niille on tyypillistä, että. niiden ominaisuudet tunnetaan hyvin

useampi ns. avain (tai vertailuavain) esim. opiskelijaa kuvaavassa alkiossa vaikkapa opintopistemäärä tai opiskelijanumero

58131 Tietorakenteet ja algoritmit (syksy 2015) Toinen välikoe, malliratkaisut

Tietotyypit ja operaattorit

Algoritmien suunnittelu ja analyysi (kevät 2004) 1. välikoe, ratkaisuja

Tietorakenteet ja algoritmit

13. Loogiset operaatiot 13.1

Transkriptio:

A274101 TIETORAKENTEET JA ALGORITMIT LISÄÄ JÄRJESTÄMISESTÄ JÄRJESTÄMISEN TEORIAA Inversio taulukossa a[] on lukupari (a[i],a[j]) siten, että i < j mutta a[i] > a[j] Esimerkki Taulukko a[] = [2, 4, 1, 3] sisältää inversiot: (2, 1), (4, 1) ja (4, 3) Inversioille on voimassa Järjestetyssä taulukossa ei ole lainkaan inversioita Kahden peräkkäisen alkion vaihto muuttaa (vähentää) inversioiden lukumäärää yhdellä n-alkioisessa taulukossa on inversioita enintään n(n-1)/2 keskimäärin n(n-1)/4 molemmat 1.11.2005 KyAMK - TiRak, syksy 2005 2 JÄRJESTÄMISEN TEORIAA Siis taulukon järjestämisessä poistetaan siitä kaikki inversiot Edellä käsitellyt perusmenetelmät ovat hitaita, koska niissä inversiot poistettiin yksitellen Voidaan osoittaa, että minkä tahansa tämänkaltaisen menetelmän keskimääräinen aikavaatimus on aina Halutaan nopeampia algoritmeja poistetaan systemaattisesti useita inversioita kerralla Voidaan osoittaa, että paras mahdollinen tulos on Vertailuilla ja vaihdoilla ei ole voida toteuttaa nopeampaa menetelmää JÄRJESTÄMISEN TEORIAA Järjestämismenetelmä on stabiili eli vakaa, jos se jättää keskenään yhtä suuret avainarvot omaavat alkiot alkuperäiseen järjestykseen Tämä on usein olennainen vaatimus, jota kaikki järjestämismenetelmät eivät toteuta Esimerkki Henkilöistä tiedetään nimi sekä ikä, ja henkilöt ovat aakkosjärjestyksessä. Vaihto ikäjärjestykseen siten, että saman ikäiset ovat aakkosjärjestyksessä onnistuu helposti vain stabiililla järjestämismenetelmällä. 1.11.2005 KyAMK - TiRak, syksy 2005 3 1.11.2005 KyAMK - TiRak, syksy 2005 4

SHELL-SORT Donald Shell kehitti ensimmäisenä -rajan alittaneen menetelmän vuonna 1959 Shell on siis henkilön nimi, eikä kyseessä ole mikään "kuorilajittelu", joka esiintyy jopa joissakin oppikirjoissa Menetelmän perusidea on seuraava 1. vaiheessa verrataan ja vaihdetaan kaikki toisistaan etäisyydellä h m (suuri) olevat alkiot, jolloin useita inversioita poistuu kerralla Seuraavaksi verrataan ja vaihdetaan kaikki toisistaan etäisyydellä h m-1 < h m olevia alkioita Viimeisessä vaiheessa vertailu- ja vaihtoetäisyys on h 1 = 1 SHELL-SORT Kussakin vaiheessa järjestämismenetelmä on lisäysjärjestäminen Siis tarvitaan kasvava lisäysjono (increment sequence) h 1, h 2, h 3,...,h m, jossa h 1 = 1 Ensimmäisessä vaiheessa taulukko tulee h m - järjestetyksi, seuraavassa h m-1 -järjestetyksi ja lopuksi h 1 -järjestetyksi, jolloin se on järjestyksessä Jokaisessa vaiheessa h k-1 -järjestetty taulukko säilyy h k -järjestettynä Menetelmän tehokkuuden kannalta lisäysjonon valinta on kriittistä 1.11.2005 KyAMK - TiRak, syksy 2005 5 1.11.2005 KyAMK - TiRak, syksy 2005 6 SHELL-SORT SHELL-SORT Esimerkki: Järjestetään taulukko käyttäen lisäysjonona lukuja 1, 3, 7 Indeksi: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 Alkuperäinen: 17 11 6 14 22 8 1 16 10 19 12 3 5 15 13 7-järjestetty: 13 10 6 12 3 5 1 16 11 19 14 22 8 15 17 3-järjestetty: 1 3 5 8 10 6 12 14 11 13 15 17 19 16 22 1-järjestetty: 1 3 5 6 8 10 11 12 13 14 15 16 17 19 22 Kuten huomataan, 3-järjestetty taulukko on melkein järjestyksessä Siten 1-järjestäminen mukainen lisäysjärjestäminen ei joudu tekemään enää paljon työtä Shellin alkuperäinen lisäysjono oli 1, 2, 4, 8,... Tällä jonolla on tiedetty heikkous Taulukon parillisen ja parittoman indeksin alkiot sekoittuvat vasta viimeisessä vaiheessa 1-järjestykseen jää paljon vaihtoja Parempi jono on Hibbardin keksimä 1, 3, 7, 15,... Worst-case O(n 3/2 ), Average O(n 5/4 ) Parhaaksi tiedetty on Sedgewickin 1, 5, 19, 41, 109,... Monimutkainen lauseke tälle löytyy kirjallisuudesta Worst-case O(n 4/3 ) ja keskimääräiseksi on arveltu O(n 7/6 ) On todistettu, että ei ole inkrementtijonoa, jolla päästäisiin pahimmassa tapauksessa -aikaan 1.11.2005 KyAMK - TiRak, syksy 2005 7 1.11.2005 KyAMK - TiRak, syksy 2005 8

SHELLSORT MERGE-SORT C-koodi, joka toteuttaa Shell-lajittelun. Inkrementit riippuvat syötteestä, eivätkä ole välttämättä hyvät. void ShellSort( float *a, int n ){ int i, j, gap; float tmp; for ( gap = n/2; gap > 0; gap /= 2 ){ for ( i = gap; i < n; ++i ) { tmp = a[i]; for ( j = i; j >= gap && tmp < a[j-gap]; j -= gap ){ a[j] = a[j-gap]; a[j] = tmp; Merge-sortin (lomitusjärjestäminen) perusidea on, että kahdesta järjestyksessä olevasta taulukosta saadaan lomittamalla yksi järjestetty taulukko Esimerkki: 1 7 10 3 4 8 11 1 3 4 7 8 10 11 aptr bptr cptr Sijoitetaan *cptr = min( *aptr, *bptr ) ++cptr, ja ++aptr, jos oli *aptr < *bptr, muutoin ++bptr 1.11.2005 KyAMK - TiRak, syksy 2005 9 1.11.2005 KyAMK - TiRak, syksy 2005 10 MERGE-SORT Järjestäminen toteutetaan rekursiivisesti Jos n = 1, taulukko on valmiiksi järjestetty Muutoin järjestetään tällä menetelmällä alkupuolisko ja loppupuolisko erikseen sekä lomitetaan ne Rekursiivinen algoritmi vaatii aputaulukon, johon puolikkaat lomitetaan Huom. Aputaulukkoa ei saa luoda rekursiivisessa funktiossa. Muutoin taulukoita syntyy pahimmillaan log n kappaletta. Oheisessa koodissa aputaulukko välitetään parametrina. Algoritmi on tyyppiä "hajota ja hallitse" (divideand-conquer) Worst-case MERGE-SORT C-toteutus merge-sortista, merge()-funktion toteutus seuraavalla kalvolla. void mergesort( float *a, float *tmp, int left, int right ){ int m; if ( left < right ) { m = ( left + right ) / 2; mergesort( a, tmp, left, m ); mergesort( a, tmp, m+1, right ); merge( a, tmp, left, m, right ); 1.11.2005 KyAMK - TiRak, syksy 2005 11 1.11.2005 KyAMK - TiRak, syksy 2005 12

MERGE-SORT MERGE-SORT Merge-funktion toteutus. void merge( float *a, float *tmp, int left, int m, int right ) { int i, j, k; for ( i = m+1; i > left; --i ) tmp[i-1] = a[i-1]; for ( j = m; j < right; ++j ) tmp[right+m-j] = a[j+1]; for ( k = left; k <= right; ++k ) if( tmp[j] < tmp[i] ) a[k] = tmp[j--]; else a[k] = tmp[i++]; Esimerkki Tämän on periaatteellinen numeroesimerkki - edellä oleva koodi järjestää hitaammin eikä ihan samassa järjestyksessä. Alkuperäinen [7 3 2 8 5 9 6 4] 1. Jako [7 3 2 8] [5 9 6 4] 2. jako [7 3] [2 8] [5 9] [6 4] 3. jako [7] [3] [2] [8] [5] [9] [6] [4] 1. lomitus [3 7] [2 8] [5 9] [4 6] 2. lomitus [2 3 7 8] [4 5 6 9] 3. lomitus [2 3 4 5 6 7 8 9] 1.11.2005 KyAMK - TiRak, syksy 2005 13 1.11.2005 KyAMK - TiRak, syksy 2005 14 QUICKSORT QUICKSORT Quicksortin ideaa kuvataan kirjallisuudessa seuraavasti: Tehtävänä on järjestää penkkirivillä istuvat ihmiset järjestetään pituuden mukaan. 1. Rivin innokkain ilmoittautuu jakohenkilöksi ja ilmoittaa pituutensa 2. Etsitään rivin alusta lukien ensimmäinen, joka on jakohenkilöä pitempi ja rivin lopusta lukien ensimmäinen, joka on jakohenkilöä lyhyempi. He vaihtavat paikkaa keskenään. 3. Kohta 2 toistetaan, kunnes jakohenkilön edellä istuu vain häntä lyhyempiä ja jäljessä vain pitempiä henkilöitä 4. Kohdat 1-3 toistetaan sekä lyhyempien että pitempien henkilöiden joukolle 5. Kohta 4 toistetaan, kunnes jokainen joukko käsittää vain yhden henkilön, jolloin henkilöt ovatkin pituusjärjestyksessä Muodollisesti esitettynä algoritmi toimii seuraavasti: Olkoon S järjestettävien alkioiden jono Jos S:ssä on 0 tai 1 alkiota, S on järjestyksessä. Palauta S ja algoritmi päättyy. Ota mikä tahansa S:n alkio j. Kutsutaan sitä pivot-alkioksi (jakoalkio, napa). Jaa S kahdeksi erilliseksi jonoksi S1 ja S2 siten, että S1:n kaikki alkiot ovat <= j ja S2:n kaikki alkiot ovat >= j. Järjestä tällä algoritmilla jonot S1 ja S2 sekä palauta jono S1, j, S2 1.11.2005 KyAMK - TiRak, syksy 2005 15 1.11.2005 KyAMK - TiRak, syksy 2005 16

QUICKSORT QUICKSORTIN OMINAISUUKSIA void QuickSort( float *a, int lo, int hi ) { int i, j; float p; i = lo; j = hi; p = a[(lo + hi) / 2]; /* pivot */ do { while ( a[i] < p && i < hi ) ++i; while ( a[j] > p && j > lo ) --j; if ( i <= j ) { swap( &a[i], &a[j] ); ++i; --j; while ( i <= j ); /* Onko = tarpeen? */ if ( lo < j ) QuickSort( a, lo, j ); if ( hi > i ) QuickSort( a, i, hi ); Quicksortin suoritusaika Keskimääräinen Worst-case - tapahtuu, kun pivot-alkioksi toistuvasti sattuu järjestettävän osion pienin tai suurin alkio Siis pivotin valinta on keskeinen algoritmin suorituskyvyn kannalta Esimerkkikoodissa pivot on aina osion keskimmäinen alkio Ei hyvä valinta, kuten ei mikään yksittäisen alkion valinta Kirjallisuudessa pivot-alkiona käytetään ensimmäisen, keskimmäisen ja viimeisen alkion mediaania ehkäisee pahimman tapauksen syntymisen ja on ylipäätänsä osoittautunut hyväksi menetelmäksi (käytetään esim. C:n stdlib.h:n qsort()-funktiossa) Käytännössä quicksort on hyvin ohjelmoituna osoittautunut nopeimmaksi järjestämisalgoritmiksi "sisimmän toiston" yksinkertaisuuden vuoksi Quicksort on merge sortin tapaan "hajota ja hallitse"- algoritmi 1.11.2005 KyAMK - TiRak, syksy 2005 17 1.11.2005 KyAMK - TiRak, syksy 2005 18 HEAPSORT Heapsort (kekojärjestäminen) perustuu keon käyttöön Menetelmän idea on seuraava: Muokataan taulukko minimikeoksi, suoritusaika O(n) Poistetaan alkiot yksitellen del_min - operaatiolla toiseen taulukkoon worst-case aikavaatimus koko operaatiolle on HEAPSORT Käytännössä menetellään hieman edellistä ovelammin, jolloin vältytään toisen taulukon käytöltä Tehdäänkin taulukosta maksimikeko Aluksi vaihdetaan keon maksimialkio (on ensimmäisenä) ja taulukon viimeinen alkio keskenään. Ensimmäiseksi joutunutta alkiota valutetaan alaspäin taulukossa, kunnes kekoominaisuus on palautettu Menetellään samoin toiseksi viimeisen alkion ja uuden maksimialkion (ensimmäisenä) suhteen. Kun sama on toistettu n-1 kertaa, taulukko on järjestyksessä 1.11.2005 KyAMK - TiRak, syksy 2005 19 1.11.2005 KyAMK - TiRak, syksy 2005 20

HEAPSORT HEAPSORT Heapsortin C-toteutus, percdown()-funktio löytyy seuraavalta kalvolta. void HeapSort( float *a, int n ){ int i; for ( i = n/2; i >= 0; --i ) /* Tässä taulukosta */ percdown( a, i, n ); /* tulee maksimikeko */ for ( i = n-1; i > 0; --i ){ /* Tässä sitten */ swap( &a[0], &a[i] ); /* järjestetään */ percdown( a, 0, i ); void percdown( float *a, int i, int n ) /* Valuttaminen alas*/ { int child; float tmp; for ( tmp = a[i]; 2*i+1 < n; i = child ) { child = 2*i+1; if ( ( child!= n-1 ) && ( a[child+1] > a[child] ) ) ++child; if ( tmp < a[child] ) a[i] = a[child]; else break; a[i] = tmp; 1.11.2005 KyAMK - TiRak, syksy 2005 21 1.11.2005 KyAMK - TiRak, syksy 2005 22 JÄRJESTÄMISALGORITMIEN VALINNASTA JÄRJESTÄMISALGORITMIEN VERTAILUA Jos järjestettäviä on vähän ja järjestetään harvoin, menetelmän valinnalla ei ole väliä kannattaa valita yksinkertaisin tai se, jonka osaa parhaiten Jos järjestetään suurta datamäärää ja nopeus on tärkeää, kannattaa valita quicksort. Ei yleensä tarvitse itse implementoida, löytyy useimmiten valmiina ohjelmakirjastoista. Jos ehdottomasti pitää välttää -tapausta, paras menetelmä on heapsort tai Shell-sort On syytä muistaa, että paraskin vertailuihin perustuva järjestämismenetelmä on pahimmassa tapauksessa Menetelmä Exchange Bubble Selection Insertion Shell Shell/Hibbard Shell/Sedgewick Merge Quick Heap Worst-case O(n 3/2 ) O(n 4/3 ) Average O(n 5/4 ) O(n 7/6 ) Huom. Hidas, vaikka vain yksi alkio väärässä paikassa. Nopea, jos valmiiksi (melkein) järjestyksessä. Vaatii aputaulukon. Pahin tapaus voidaan useimmiten välttää. Elegantti 1.11.2005 KyAMK - TiRak, syksy 2005 23 1.11.2005 KyAMK - TiRak, syksy 2005 24

INDEKSIJÄRJESTÄMINEN INDEKSIJÄRJESTÄMINEN Jos järjestettävä alkiojoukko on sopivasti rajoitettu, voidaan erikoisalgoritmeilla päästä nopeampaan tulokseen kuin teoreettinen alaraja Eräs tällainen on indeksijärjestäminen Olkoon järjestettävänä taulukon a[] sisältämät n kokonaislukua, joiden lukualue p... q (p < q) tunnetaan Tällöin indeksijärjestäminen tapahtuu seuraavasti Varataan q-p+1 -alkioinen kokonaislukutaulukko c[] (nollia) Käydään taulukon a[] alkiot läpi yksitellen Jos alkion suuruus on k, (p <= k <= q), kasvatetaan alkiota c[k-p] yhdellä Käydään taulukko c[] läpi ja tulostetaan kaikki ne indeksit i, joita vastaava c[i] > 0, kukin luvun c[i] osoittama määrä kertoja, alkuperäinen taulukko on tulostettu järjestettynä Kuvatun menetelmän aikavaatimus on O(n) Esimerkki: Olkoon lukualue 0... 9 ja luvut: 2, 5, 7, 1, 4, 3, 2, 9, 2, 7 Tällöin taulukon c[] sisällöksi tulee: [ 0 1 3 1 1 1 0 2 0 1 ], jolloin luvut järjestettyinä ovat: 1, 2, 2, 2, 3, 4, 5, 7, 7, 9 Indeksijärjestämisessä taulukkoa a[] ei siis itse asiassa järjestetä Avaimet tulostetaan järjestettynä aputaulukon c[] perusteella 1.11.2005 KyAMK - TiRak, syksy 2005 25 1.11.2005 KyAMK - TiRak, syksy 2005 26 COUNTING SORT RADIX SORT Counting sort -menetelmässä alku tapahtuu kuten indeksijärjestämisessä, mutta pelkän tulostamisen sijaan a[] todella järjestetään saman kokoiseen toiseen taulukkoon b[]. Indeksitaulukkoa c tarvitaan edelleen apuna. Seuraavassa pseudokoodi (lähde: Cormen, Leiserson, Rivest: Introduction to Algorithms) hieman yksinkertaistetusta tapauksesta, missä lukualue on 0... q. CountingSort( a, b, q) for i = 0 to q do c[i] = 0 for j = 1 to length( a[] ) do c[a[j]] = c[a[j]] + 1 for i = 1 to q do c[i] = c[i] + c[i-1] for j = length( a[] ) downto 1 do b[c[a[j]]] = a[j] c[a[j]] = c[a[j]] 1 Counting sort -menetelmän aikavaatimus on O(n) ja menetelmän käyttökelpoisuutta lisää stabiilisuus Radix sort on nopea ja hyvä menetelmä järjestettäessä dataa, jossa avaimet ovat merkkijonoja tai kokonaislukuja Toisin kuin kaikissa edellä esitetyissä menetelmissä avaimia ei käsitellä kokonaisina vaan merkeittäin tai biteittäin Esimerkki: Järjestetään kolminumeroisia kokonaislukuja Alkuperäinen 1. kierros 2.kierros 3.kierros 329 720 720 329 457 355 329 355 657 436 436 436 839 457 839 457 436 657 355 657 720 329 457 720 355 839 657 839 1.11.2005 KyAMK - TiRak, syksy 2005 27 1.11.2005 KyAMK - TiRak, syksy 2005 28

RADIX SORT RADIX SORT Ensimmäisellä kierroksella luvut järjestetään viimeisen numeron perusteella, toisella kierroksella keskimmäisen numeron perusteella ja kolmannella kierroksella ensimmäisen numeron perusteella Koska yksittäisen numeron tai merkin lukualue on pieni ja rajoitettu, ja keskenään yhtä suurten numeroiden tai merkkien järjestys ei saa vaihtua, Counting sort on erinomainen menetelmä yksittäisen kierroksen suorittamiseen. Ohessa internetistä poimittu esimerkki, jossa järjestetään kokonaislukuja. Lähde on www.cubic.org/~submissive/sourcerer/radix.htm. #include <iostream.h> #include <stdlib.h> #include <string.h> void radix (int byte, long N, long *source, long *dest) { long count[256]; long index[256]; memset (count, 0, sizeof (count)); for ( int i=0; i<n; i++ ) count[((source[i])>>(byte*8))&0xff]++; index[0]=0; for ( i=1; i<256; i++ ) index[i]=index[i-1]+count[i-1]; for ( i=0; i<n; i++ ) dest[index[((source[i])>>(byte*8))&0xff]++] = source[i]; void radixsort (long *source, long *temp, long N) { radix (0, N, source, temp); radix (1, N, temp, source); radix (2, N, source, temp); radix (3, N, temp, source); void make_random (long *data, long N) { for ( int i=0; i<n; i++ ) data[i]=rand() (rand()<<16); long data[100]; long temp[100]; void main (void) { make_random(data, 100); radixsort (data, temp, 100); for ( int i=0; i<100; i++ ) cout << data[i] << '\n'; 1.11.2005 KyAMK - TiRak, syksy 2005 29 1.11.2005 KyAMK - TiRak, syksy 2005 30