**Hakurakenne** eli **assosiaatiotaulu** (engl. *associative array*) eli **hakemisto** on abstrakti tietotyyppi, joka kuvaa avaimia arvoiksi. Kun hakurakenteelle antaa *avaimen* (esimerkiksi henkilön nimi), se kertoo *arvon* (puhelinnumero). Sen rajapinta on tyypillisesti:

* Set(*k*, *v*): merkitse avaimen *k* arvoksi *v*
* Lookup(*k*): hae avaimeen *k* liitetty arvo
* Remove(*k*): poista avain *k* ja siihen liittyvä arvo

Puhelinluetteloa mallintavassa assosiaatiotaulussa avaimilla (nimet) pääsee käsiksi arvoihin (puhelinnumerot).
Taulukkoa voidaan pitää hakurakenteena, joka sallii avaimiksi vain luonnollisia lukuja.

Hakurakenteen matemaattinen malli on funktio, jonka määrittely- ja maalijoukko ovat numeroituvia. Määrittely- ja maalijoukot vastaavat hakurakenteen avain- ja arvojoukkoja. Assosiaatiotauluja käytetäänkin säilyttämään vaikeasti laskettavan funktion arvoja tietokoneen muistissa.

Toteutus
--------

Linkitetyn listan alkioina on kolmikoita (*linkki*, *avain*, *arvo*), joten se toimii hakurakenteena.
Yksinkertaisinta on käyttää toteutukseen linkitettyä listaa säilömään (*avain*, *arvo*)-pareja, jolloin kyselyn asymptoottinen suoritusaika on *O*(*n*). Tasapainotetulla hakupuulla päästään aikaan *O*(log *n*) ja hajautustaululla keskimääräiseen suoritusaikaan *O*(1). Ennaltalaskettuja tulosarvoja sisältävää hakutaulua voidaan käyttää ohjelman optimointiin kun laskenta vaatisi enemmän aikaa kuin muistihaku.

Oikeastaan avaimien ja arvojen käsitteleminen erillisenä ei ole välttämätöntä, sillä mihin tahansa haku-, lisäys- ja poisto-operaatiot toteuttavaan tietorakenteeseen voidaan tallentaa (*avain*, *arvo*)-pareja. Tällöin parien vertailun on toimittava yksinomaan avaimen perusteella.

Usein sallitaan useiden arvojen tallentaminen samaan avaimeen. Etenkin C++-ohjelmointikielen yhteydessä tätä kutsutaan *assosiaatiomonitauluksi* (*multimap*). Joissakin yhteyksissä hakurakenteen rajapintaa on laajennettu tukemaan muitakin operaatioita, kuten seuraajaa (hae löydetystä avaimesta järjestyksessä seuraava) tai aluehakua (*range query*, hae kaikki avaimet annetulta väliltä).

Tuki ohjelmointikielissä
------------------------

Ohjelmoinnissa hakurakenteen toteuttavaa tietotyyppiä kutsutaan assosiaatiotauluksi. Koska assosiaatiotaulut ovat hyvin yleiskäyttöisiä, useat ohjelmointikielet tukevat niitä suoraan. Lua-kieli jopa perustuu täysin niiden varaan. Yleisimpiä nimiä assosiaatiotaululle ovat *dictionary* (sanakirja), *map* (kuvaus) tai tyypillisen toteutustavan mukaan *hash table*, hajautustaulu.

### C++

C++:n standardimallikirjastossa on säiliöluokkia kuten `std::map`, joka on tyypillisesti toteutettu tasapainotettuna binäärihakupuuna. Standardi velvoittaa, että indeksointi voidaan tehdä ajassa *O*(log *n*).

```
 #include <string>
 #include <map>

 std::map<std::string, int> taulu;
 taulu["Jussi Virtanen"] = 991234567;
 int nro = taulu["Jussi Virtanen"];

```

C++11-standardia edeltävässä Technical Report 1 -muistiossa standardikirjastoon on lisätty `std::unordered_map`, joka toteuttaa assosiaatiotaulun hajautustauluna.

### Lua

Luan ainoa sisäänrakennettu tietorakenne on assosiaatiotaulu, jonka avulla tietueet, taulukot ja oliot rakennetaan. Koska assosiaatiotaulut ovat kaikkialla, niistä käytetään vain sanaa *table*, taulu.

```
 taulu = {}
 taulu = {x = 10}
 print(taulu["x"])  -- tulostaa 10
 print(taulu.x)     -- tulostaa 10
 taulukko = { "a", "b", "c", "d" }  -- alkiot saavat automaattisesti avaimet 1, 2, 3 ja 4
 print(taulukko[2]) -- tulostaa "b"

```

### Python

Pythonissa on sisäänrakennettu assosiaatiotaulu, josta käytetään sanaa *dictionary*, sanakirja.

```
 >>> sanakirja = {'map': 'kuvaus', 'lookup': 'haku'}
 >>> print(sanakirja['map'])
 kuvaus

```

Katso myös
----------

* Punamusta puu

### Muita abstrakteja tietotyyppejä

* Jono
* Säiliö
* Pino
* Prioriteettijono

Lähteet
-------

* L. Malmi, A. Korhonen, V. Karavirta: TRAKLA2: Elektroninen oppikirja / Opetusmoniste: Hakurakenteet  27. joulukuuta 2006. Teknillinen korkeakoulu.  Arkistoitu 12.6.2007. Viitattu 1. huhtikuuta 2007.

* Thomas Cormen, Charles Leiserson, Ronald Rivest ja Clifford Stein: *Introduction to Algorithms – 2nd ed.*. MIT Press ja McGraw-Hill, 2001. ISBN 0-262-03293-7.

### Viitteet

1. ↑  Laaksonen, Antti: Kisakoodarin käsikirja (Sivut 48–49) *cs.helsinki.fi*.  2018. Viitattu 15.12.2020.
2. ↑  Chris Wilcox & Michelle Mills Strout & James M. Bieman: Mesa: Automatic Generation of Lookup Table Optimizations (PDF) *cs.colostate.edu*.  Arkistoitu 11.8.2017. Viitattu 29.8.2019. (englanniksi)
3. ↑  Thomas Cormen, Charles Leiserson, Ronald Rivest ja Clifford Stein: *Introduction to Algorithms – 2nd ed.*, s. 197–198. MIT Press ja McGraw-Hill, 2001. ISBN 0-262-03293-7.
4. ↑
5. ↑
6. ↑  Bjarne Stroustrup: "17.1.2: Säiliöiden yhteenveto", *C++-ohjelmointi*. 2. painos. Alkup. *The C++ Programming Language – 3rd. ed*. Teknolit/Addison-Wesley, 1997. ISBN 0-201-88954-4.

Aiheesta muualla
----------------

* TRAKLA2: Hakurakenteet (Arkistoitu – Internet Archive)