Järjestämismenetelmät

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