Hajautus. operaatiot insert ja search pyritään tekemään erittäin nopeiksi

Samankaltaiset tiedostot
5. Hajautus. Tarkastellaan edelleen sivulla 161 esitellyn joukkotietotyypin toteuttamista

Algoritmit 2. Luento 3 Ti Timo Männikkö

Algoritmit 2. Luento 3 Ti Timo Männikkö

Algoritmit 2. Luento 4 To Timo Männikkö

4. Hajautus. Hajautus (hashing) on vaihtoehto tasapainoisille puille dynaamisen joukon toteuttamisessa:

Algoritmit 2. Luento 4 Ke Timo Männikkö

(a) L on listan tunnussolmu, joten se ei voi olla null. Algoritmi lisäämiselle loppuun:

CS-A1140 Tietorakenteet ja algoritmit

Kierros 5: Hajautus. Tommi Junttila. Aalto University School of Science Department of Computer Science

7.4 Sormenjälkitekniikka

Tietorakenteet ja algoritmit Johdanto Lauri Malmi / Ari Korhonen

Tietorakenteet, laskuharjoitus 8,

Tietorakenteet ja algoritmit - syksy

TKHJ:ssä on yleensä komento create index, jolla taululle voidaan luoda hakemisto

AVL-puut. eräs tapa tasapainottaa binäärihakupuu siten, että korkeus on O(log n) kun puussa on n avainta

Algoritmit 1. Luento 12 Ke Timo Männikkö

Hajautusrakenteet. R&G Chapter Tietokannan hallinta, kevät 2006, Jan 1

Algoritmit 1. Luento 12 Ti Timo Männikkö

A TIETORAKENTEET JA ALGORITMIT

Tietorakenteet, laskuharjoitus 8, malliratkaisut

Hajautusrakenteet. Hajautukseen perustuvat tiedostorakenteet. Hajautukseen perustuvat tiedostorakenteet. Hajautukseen perustuvat tiedostorakenteet

Ohjelmoinnin perusteet Y Python

8. Yhteenvetoa. abstrakti tietotyyppi: mitä datalle halutaan tehdä tietorakenne: miten se tehdään (talletusrakenne, operaatioden toteutus)

Tietorakenteet, laskuharjoitus 7, ratkaisuja

Algoritmit 2. Luento 2 To Timo Männikkö

Ohjelmoinnin perusteet Y Python

Algoritmit 2. Luento 2 Ke Timo Männikkö

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

Algoritmit 2. Luento 5 Ti Timo Männikkö

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

Luento 2: Tiedostot ja tiedon varastointi

Kirjoita oma versio funktioista strcpy ja strcat, jotka saavat parametrinaan kaksi merkkiosoitinta.

2.1. Tehtävänä on osoittaa induktiolla, että kaikille n N pätee n = 1 n(n + 1). (1)

Hakupuut. tässä luvussa tarkastelemme puita tiedon tallennusrakenteina

Tieto- ja tallennusrakenteet

Algoritmit 2. Luento 6 Ke Timo Männikkö

Algoritmit 2. Luento 7 Ti Timo Männikkö

Satunnaisalgoritmit. Topi Paavilainen. Laskennan teorian opintopiiri HELSINGIN YLIOPISTO Tietojenkäsittelytieteen laitos

Tietorakenteet ja algoritmit. Hajautus. Ari Korhonen Tietorakenteet ja algoritmit - syksy

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

Ohjelmoinnin jatkokurssi, kurssikoe

Algoritmit 1. Luento 11 Ti Timo Männikkö

Algoritmi on periaatteellisella tasolla seuraava:

A TIETORAKENTEET JA ALGORITMIT

Algoritmit 1. Luento 8 Ke Timo Männikkö

58131 Tietorakenteet ja algoritmit (syksy 2015)

Ohjelmoinnin perusteet Y Python

Tarkennamme geneeristä painamiskorotusalgoritmia

Algoritmit 2. Luento 6 To Timo Männikkö

811120P Diskreetit rakenteet

4. Joukkojen käsittely

Algoritmit 2. Luento 13 Ti Timo Männikkö

Algoritmit 1. Luento 9 Ti Timo Männikkö

Algoritmit 1. Luento 3 Ti Timo Männikkö

A TIETORAKENTEET JA ALGORITMIT

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

Ongelma 1: Onko datassa tai informaatiossa päällekkäisyyttä?

Tietorakenteet, laskuharjoitus 3, ratkaisuja

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

811312A Tietorakenteet ja algoritmit II Perustietorakenteet

TKT20001 Tietorakenteet ja algoritmit Erilliskoe , malliratkaisut (Jyrki Kivinen)

Luku 8. Aluekyselyt. 8.1 Summataulukko

Algoritmit 1. Luento 5 Ti Timo Männikkö

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

Ohjelmoinnin perusteet Y Python

4 Tehokkuus ja algoritmien suunnittelu

Ohjelmoinnin peruskurssi Y1

Esimerkkejä polynomisista ja ei-polynomisista ongelmista

Tietorakenteet ja algoritmit syksy Laskuharjoitus 1

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

Algoritmit 1. Luento 10 Ke Timo Männikkö

3. Kongruenssit. 3.1 Jakojäännös ja kongruenssi

18. Abstraktit tietotyypit 18.1

Ohjelmoinnin peruskurssien laaja oppimäärä

815338A Ohjelmointikielten periaatteet Harjoitus 3 vastaukset

Algoritmit 1. Luento 1 Ti Timo Männikkö

Ohjelmoinnin peruskurssien laaja oppimäärä

Sisällys. 18. Abstraktit tietotyypit. Johdanto. Johdanto

Sekvenssi: kokoelma peräkkäisiä alkioita (lineaarinen

Ohjelmistojen mallintaminen viikon 4 laskareiden mallivastauksia

} {{ } kertaa jotain

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

Algebra I Matematiikan ja tilastotieteen laitos Ratkaisuehdotuksia harjoituksiin 6 (8 sivua) OT. 1. a) Määritä seuraavat summat:

Tuloperiaate. Oletetaan, että eräs valintaprosessi voidaan jakaa peräkkäisiin vaiheisiin, joita on k kappaletta

Kohdissa 2 ja 3 jos lukujen valintaan on useita vaihtoehtoja, valitaan sellaiset luvut, jotka ovat mahdollisimman lähellä listan alkua.

Lukuteoria. Eukleides Aleksandrialainen (n. 300 eaa)

Opintojakso TT00AA11 Ohjelmoinnin jatko (Java): 3 op. Tietorakenneluokkia 2: HashMap, TreeMap

Tekijä Pitkä Matematiikka 11 ratkaisut luku 2

Ohjelmassa muuttujalla on nimi ja arvo. Kääntäjä ja linkkeri varaavat muistilohkon, jonne muuttujan arvo talletetaan.

Dierentiaaliyhtälöistä

Tehtävä 2: Loppuosataulukko

Algoritmit 1. Luento 10 Ke Timo Männikkö

6. Sanakirjat. 6. luku 298

2. Seuraavassa kuvassa on verkon solmujen topologinen järjestys: x t v q z u s y w r. Kuva 1: Tehtävän 2 solmut järjestettynä topologisesti.

Tehtävät. 1. Ratkaistava epäyhtälöt. a) 2(4 x) < 12, b) 5(x 2 4x + 3) < 0, c) 3 2x 4 > 6. 1/10. Sukunimi (painokirjaimin)

Nimittäin, koska s k x a r mod (p 1), saadaan Fermat n pienen lauseen avulla

Ohjelmoinnin perusteet Y Python

4.3. Matemaattinen induktio

Johdatus matematiikkaan

811312A Tietorakenteet ja algoritmit V Hash-taulukot ja binääriset etsintäpuut

Transkriptio:

Hajautus eräs (osittainen) toteutus joukko-tietotyypille operaatiot insert ja search pyritään tekemään erittäin nopeiksi tärkeä tekniikka käytännön ohjelmoinnissa valmiita toteutuksia on, mutta väärät valinnat voivat johtaa huonoon lopputulokseen emme tällä kurssilla mene kovin syvälle taustalla olevaan teoriaan, mutta on tärkeä ymmärtää keskeiset asiat, jotka voivat mennä pieleen 1

Esimerkki: shakkiasemien arvioiminen shakkiohjelmat kokeilevat runsaasti erilaisia siirtovaihtoehtoja ja arvioivat syntyviä asemia (eli tilanteita) arvio voi olla esim. +0.5 jolloin koneen mielestä valkealla on noin puolen sotilaan arvoinen etu asemien arvioimiseen kuluvan ajan minimoiminen on olennaista suorituskyvylle sama asema voi syntyä useilla eri tavoilla (pelaamalla samat siirrot eri järjestyksessä), mutta sitä ei haluta arvioida kuin kerran siis tarvitaan tietorakenne, joka tukee seuraavia: Onko asema X jo arvioitu? Jos on, niin mikä oli arvion lopputulos? Merkitse muistiin asemalle X arvio v. 2

Havainto: ainakin periaatteessa tähän kelpaa abstrakti tietotyyppi joukko: avaimena asema shakkipelissä datana arvio asemasta Verrattuna aiempiin esimerkkeihin potentiaalisten avainten joukko todella suuri, avaimet monimutkaisia search-operaation tehokkuusvaatimus ankara myös insert ja ehkä delete tarvitaan, muista ei niin väliä 3

Hajautuksen perusajatus mahdollisten avainten joukko U hyvin suuri mikä tahansa yksittäinen sovellus käyttää vain häviävän pientä osaa joukon U alkioista talletetaan pareja avain, data, missä avain U ja data voi olla mitä tahansa avaimet ja data talletetaan hajautustauluun, jonka indeksit ovat väliltä 0... m 1 hajautustaulun koko m on paljon pienempi kuin avainten lukumäärä U hajautusfunktio h: U { 0,..., m 1 } kertoo, mihin kohtaan hajautustaulua kukin avain pitäisi sijoittaa 4

hajautusfunktio siis h liittää jokaiseen avaimeen x U indeksin h(x) { 0,..., m 1 } voidaan ajatella, että hajautustaulussa on m lokeroa joihin varsinainen tieto talletetaan jos h(x) = j, se tarkoittaa, että avain x kuuluu lokeroon j koska lokeroita on m, mahdollisia avaimia on U, ja m U, tulee pakostakin yhteentörmäyksiä eli tilanteita, joissa kaksi eri avainta kuuluu samaan lokeroon muodollisemmin yhteentörmäys on tilanne, jossa x y mutta h(x) = h(y) Kysymys 1: miten valitaan h niin, että yhteentörmäyksiä ei tule liikaa Kysymys 2: kun yhteentörmäyksiä kuitenkin tulee, miten ne käsitellään 5

Ennen kysymysten 1 ja 2 tarkempaa pohtimista katsotaan konkreettisuuden vuoksi esimerkkinä yksi usein toimiva perusratkaisu: oletetaan, että avaimet ovat luonnollisia lukuja: U = { 0,..., U 1 } hajautusfunktiona jakojäännösmenetelmä (eli jakolaskumenetelmä): h(x) = x mod m missä x mod m tarkoittaa jakojäännöstä, kun kokonaisluku x jaetaan kokonaisluvulla m siis erityisesti x mod m on joukossa { 0,..., m 1 } kaikilla x lokeroon j tulee näin ollen avaimet j, j + m, j + 2m,... yhteentörmäykset käsitellään ketjuttamalla: lokeroon k tulevat avaimet (ja niihin liittyvä data) talletetaan linkitettyyn listaan varsinainen hajautustaulu T [0... m 1] sisältää m osoitinta T [j] osoittaa lokeroa j vastaavan linkitetyn listan alkuun 6

Ketjuttamalla toteutetun hajautustaulun kaikki operaatiot (insert, search, delete) noudattavat seuraavaa kaavaa: 1. Etsi annettua avainta k vastaava lista (siis käytännössä osoitin listan alkuun) L = T [h(k)]. 2. Suorita haluttu operaatio listalle L. Aikavaativuus on siis O(1 + L ), missä L on listan pituus ja lisävakio tulee hajautusfunktion laskemisesta. 7

Miten hajautustaulu eroaa siitä, että pareja avain, data talletettaisiin tavalliseen taulukkoon: tavallisen taulukon etuja: tavallinen taulukko käyttää muistia mahdollisimman tehokkaasti (jos koko on suunnilleen tiedossa etukäteen) tavallinen taulukko voidaan järjestää jne. hajautustaulun keskeinen etu: avaimesta nähdään vakioajassa sen oikea paikka taulukossa tosin avainta voidaan vielä joutua etsimään listasta 8

Hajautustaulun tehokkuuden kannalta keskeinen suure on täyttösuhde (load factor) oletetaan lokeroiden lukumääräksi m oletetaan taulukkoon talletetuksi n avainta täyttösuhde on nyt α = n/m Tästä seuraa α on myös ylivuotoketjujen pituuksien keskiarvo jos h(x) saa kunkin arvoista 0,..., m 1 samalla todennäköisyydellä, niin operaatioiden aikavaativuudet ovat odotusarvoisesti O(1 + α) Huom. edellä x on satunnainen, h ei 9

yleensä pyritään pitämään täyttösuhde melko pienenä vakiona esim. Javan HashMap pitää oletusarvoisesti α 0,75 täyttösuhteen pienentäminen nopeuttaa hakuja mutta lisää muistinkulutusta sopivan täyttösuhteen löytäminen voi vaatia kokeilua Ei ole realistista yrittää valita niin pieni täyttösuhde, että yhteentörmäyksiltä kokonaan vältyttäisiin syntymäpäiväparadoksi: jos n 2m ja avaimet sijoitetaan tauluun tasaisen satunnaisjakauman mukaan, niin ainakin todennäköisyydellä 1/2 tulee ainakin yksi yhteentörmäys tässä siis α = 2/m 1 10

jos alkioiden lukumäärä ei ollut etukäteen tiedossa ja täyttösuhde näyttää kasvavan liian suureksi, voidaan tehdä uudelleenhajauttaminen (rehash) varataan uusi kaksi kertaa suurempi taulu siirretään alkiot vanhasta taulusta uuteen yksi kerrallaan tämä ei ole niin tehotonta kuin ensi silmäyksellä voisi luulla voidaan osoittaa, että operaatiot vievät edelleen keskimäärin O(1 + α) (samoin oletuksin kuin edellä) kuitenkin jotkin yksittäiset operaatiot (ne jotka laukaisevat uudelleenhajauttamisen) voivat olla hyvin hitaita 11

jos hajautettavat avaimet eivät ole kokonaislukuja, ne pitää jotenkin muuntaa sellaisiksi esim. jakojäännösmenetelmän soveltamiseksi periaatteessa kaikki avaimet ovat tietokoneen muistissa bitteinä, ja bittiesitys voidaan tulkita kokonaisluvuksi tämä kuitenkin tuottaa helposti lukuja, jotka ovat liian suuria käsiteltäväksi tavat, jotka tarkastelevat vain osaa biteistä tai esim. ASCII-koodien summaa ovat usein huonoja hyväksi havaittu tapa merkkijonoille on ascii(a 1 ) + c ascii(a 2 ) + c 2 ascii(a 3 ) + c on sopivasti valittu parametri joka ei ole kakkosen potenssi ascii(a i ) on i:nnen merkin ASCII-koodi laskutoimituksissa huomioidaan vain p vähiten merkitsevää bittiä sopivalla p 12

Hajautusfunktion valinta Yleisiä huomioita: 1. oletetaan nyt avaimet luonnollisiksi luvuiksi: U = { 0,..., U 1 } 2. talletusalueena on taas taulu T [0... m] 3. jos avaimet jakautuvat tasaisesti joukkoon U, meille kelpaa mikä tahansa hajautusfunktio, joka sijoittaa suunnilleen U /m avainta kuhunkin lokeroon 4. hyvän hajautusfunktion pitäisi kuitenkin sietää myös tyypillisiä tapoja, joilla avaimet voivat jakautua joukkoon U epätasaisesti: esiintyy vain pieniä avaimia kaikki avaimet ovat parillisia... 13

Hajautusfunktion valinta (2) Jakojäännösmenetelmässä suositellaan, että hajautustaulun koko m on alkuluku ei lähellä mitään kakkosen potenssia Miksi alkuluku: oletetaan että m = pq, missä p, q ykköstä suurempia kokonaislukuja jos hajautetaan avaimet q, 2q, 3q,..., ne sijoittuvat vain lokeroihin p, 2p, 3p,... (ei tässä järjestyksessä) avainten jaollisuus yhteisellä tekijällä q on tilanne johon halutaan varautua Miksi ei lähellä kakkosen potenssia: oletetaan esim. m = 2 8 1 hajautetaan 32-bittinen luonnollinen luku x, jonka binääriesitys on x 1 x 2... x 32 on melko helppo nähdä, että h(x) = x mod m määräytyy summasta x 1... x 8 + x 9... x 16 + x 17... x 24 + x 25... x 32 (missä siis 32-bittisestä luvusta on lohkottu neljä 8-bittistä ja laskettu ne yhteen) 14

Hajautusfunktion valinta (3) Vaihtoehto jakojäännösmenetelmälle on kertolaskumenetelmä m on hajautustaulun koko h(k) = m fr(ak) 0 < A < 1 on sopivasti valittu parametri eräs suositeltu arvo on A = ( 5 1)/2 0,618 (Knuth) idea on, että fr(ak) jakautuisi suunnilleen tasaisesti välille [0, 1) tällöin m fr(ak) jakautuu suunnilleen tasaisesti joukkoon { 0,..., m 1 } oli m mikä hyvänsä voidaan valita m = 2 p sopivalla p laskujen helpottamiseksi 15

Universaalihajautus mille tahansa kiinteälle hajautusfunktiolle on olemassa avainjoukkoja, joilla se toimii erittäin huonosti tarkemmin: jos U (n 1)m + 1, niin millä tahansa hajautusfunktiolla on olemassa n avainta, jotka kaikki menevät samaan lokeroon Todistus: Kiinnitä hajautusfunktio h ja hajauta kaikki joukon U avaimet. Ainakin yhteen lokeroon tulee ainakin U /m n avainta. universaalihajautuksen idea on valita satunnainen hajautusfunktio niin, että millä tahansa avainjoukolla se toimii todennäköisesti melko hyvin tarkemmin: joukko H hajautusfunktioita on universaali, jos mille tahansa avaimille x ja y pätee, että yhteentörmäyksen h(x) = h(y) todennäköisyys on korkeintaan 1/m, kun h valitaan satunnaisesti joukosta H eräs tapa on valita alkuluku p > n ja satunnaiset kokonaisluvut 1 a < p ja 0 b < p, minkä jälkeen h(k) = ((ak + b) mod p) mod m 16

Avoin hajautus ketjutuksessa alkiot talletetaan varsinaisen taulun T ulkopuolelle emmekä etukäteen tarkalleen tiedä, kuinka paljon muistia kuluu myös muistiviittausten paikallisuus on huono avoimessa hajautuksessa tauluun T talletetaan itse alkiot, ei viitteitä yhteentörmäyksen sattuessa etsitään toiselle alkiolle vapaa paikka jostain toisesta kohdasta taulua yksinkertaisin menetelmä on lineaarinen kokeilu: avaimen k tallettamiseksi Jos paikka h(k) on tyhjä, talleta sinne. Muuten jos paikka (h(k) + 1) mod m on tyhjä, talleta sinne. Muuten jos paikka (h(k) + 2) mod m on tyhjä, talleta sinne.... 17

Lineaarisen kokeilun ongelma on ensisijainen kasautuminen (primary clustering) yhteentörmäykset täyttävät taulusta yhtenäisiä alueita mitä suurempi yhtenäinen alue on täytetty, sitä todennäköisemmin sinne tulee lisää yhteentörmäyksiä Tämä ongelma voidaan välttää neliöisellä kokeilemisella: avaimen k tallettamiseksi Jos paikka h(k) on tyhjä, talleta sinne. Muuten jos paikka (h(k) + a + b) mod m on tyhjä, talleta sinne. Muuten jos paikka (h(k) + 2a + 4b) mod m on tyhjä, talleta sinne. Muuten jos paikka (h(k) + 3a + 9b) mod m on tyhjä, talleta sinne.... Muuten jos paikka (h(k) + i a + i 2 b) mod m on tyhjä, talleta sinne. tässä a ja b ovat sopivasti valittuja parametreja 18

Neliöinen kokeileminen välttää ensisijaisen kasautumisen, mutta kärsii silti toissijaisesta kasautumisesta: jos h(x) = h(y), niin kaikki muutkin paikat, joihin avaimia x ja y yritetään laittaa, ovat samat Toissijainenkin kasautuminen voidaan välttää kaksoishajautuksella: avaimen k tallettamiseksi Jos paikka h(k) on tyhjä, talleta sinne. Muuten laske arvo h (k) missä h on jokin toinen hajautusfunktio Jos nyt paikka (h(k) + h (k)) mod m on tyhjä, talleta sinne. Muuten jos paikka (h(k) + 2h (k)) mod m on tyhjä, talleta sinne.... Muuten jos paikka (h(k) + i h (k)) mod m on tyhjä, talleta sinne.... 19

Avoimessa hajautuksessa myös search-operaatiossa pitää seurata samaa kokeilujonoa esim. lineaarisessa kokeilussa jos etsitään alkiota x ja T [h(x)] sisältää jonkin toisen avaimen, x voikin olla paikassa T [h(x) + 1] etsiminen voidaan lopettaa, kun löytyy joko etsitty avain tai vapaa kohta taulussa Jotta etsimisen tosiaan voi turvallisesti lopettaa ensimmäiseen vapaaseen kohtaan, delete pitää toteuttaa laiskasti: käytetään jotain erityistä arvoa merkitsemään, että taulukon tässä kohdassa on ollut avain, joka on poistettu hakua ei voi lopettaa tällaiseen merkittyyn kohtaan, mutta lisäyksen siihen voi tehdä 20

Loppuhuomioita hajautuksesta riippuu aineistosta, mikä on hyvä hajautusmenetelmä jos tämä on tärkeää, kannattaa kokeilla eri menetelmiä kirjallisuudesta löytyy jonkin verran teoriaa ja paljon kokeilemalla hyväksi havaittuja menetelmiä hajautusfunktioilla ja niiden sukuisilla tekniikoilla on paljon muitakin sovelluksia kuin joukko-tietotyypin toteuttaminen: tietoturva, tarkistussummat, sormenjälkitekniikat,... 21