Professional Documents
Culture Documents
PID_00161972
Mòdul 6
© FUOC • PID_00161972 • Mòdul 6 El TAD Taula
Índex
Introducció .............................................................................................. 5
Objectius ................................................................................................... 8
Resum ........................................................................................................ 50
Activitats .................................................................................................. 51
Solucionari ............................................................................................... 53
Glossari ..................................................................................................... 58
Bibliografia .............................................................................................. 59
© FUOC • PID_00161972 • Mòdul 6 5 El TAD Taula
Introducció
Una vegada estudiats els tipus abstractes de dades (TAD) de les seqüències i els
arbres, podem considerar que disposem de diversos mètodes d’organització
d’una col·lecció de dades que hi permeten accedir en un ordre fixat pel TAD
mateix, sia seqüencial, sia jeràrquic. Això no obstant, molt freqüentment ne-
cessitem organitzar en els nostres programes col·leccions de dades, normal-
ment anomenades valors, a les quals s’ha d’accedir a partir d’una altra dada,
anomenada normalment clau o identificador. El resultat és un nou TAD ano-
menat Taula, pel fet que gràficament es pot representar com una taula, amb
una primera columna per a la clau, i una o més columnes per a representar les
parts d’un valor.
Un altre terme que s’usa sovint per a anomenar aquest TAD és el de diccionari,
pel fet que en un diccionari cerquem el significat (valor) d’una paraula (clau).
Una taula de símbols és una estructura que existeix en els traductors dels llen-
guatges de programació (compiladors i intèrprets) que associa a cada identifi-
cador d’un programa tota aquella informació d’interès per a la generació de
codi: categoria (si és un identificador d’objecte, de mètode, de classe, etc.), ti-
pus (si s’escau, que pot ser enter, real, string, etc.), direcció de memòria assig-
nada, nombre de bytes que ocupa, etc. El traductor crea una nova entrada a la
© FUOC • PID_00161972 • Mòdul 6 6 El TAD Taula
taula quan troba per primera vegada l’identificador; a partir d’aquest moment,
pot consultar la taula cada vegada que troba l’identificador en l’anàlisi del pro-
grama (per exemple, en fer l’anàlisi semàntica de la correcció d’una expressió);
quan acaba el tractament corresponent en l’àmbit de definició de l’identifica-
dor, l’esborra de la taula. Podem dir que la taula de símbols és un objecte que
pertany al TAD Taula tal que les claus són els identificadors i els valors associ-
ats, la resta d’informació.
1) En una aplicació informàtica per a una acadèmia, es volen guardar les dades personals
dels seus estudiants: DNI, nom, edat, domicili, etc. En aquest cas, es pot definir una taula
d’estudiants en què el valor de cada estudiant són les seves dades personals, mentre que
la clau és el DNI, atès que no pot haver-hi dos estudiants amb el mateix DNI.
2) En una aplicació web per a una agència de viatges, es volen enregistrar tots els aero-
ports internacionals del món amb les seves dades: situació, capacitat, etc. Els aeroports
s’identifiquen per un codi de tres lletres (per exemple, el de Barcelona a Catalunya és
BCN, el de Rio de Janeiro a Brasil és GIG, etc.). Podem tenir una taula d’aeroports en què
el valor de cada un siguin les dades abans esmentades (situació, etc.) i la clau sigui el codi
de tres lletres.
El mòdul està dividit en cinc apartats que presenten els conceptes següents:
4) En el quart apartat ens adrecem a una variant de les taules, que en realitat
és un cas particular, en què la clau coincideix amb la dada a emmagatzemar.
El resultat és el TAD Conjunt. Redefinirem les operacions per a aquest cas i veu-
rem com canvien els conceptes explicats per a les taules.
Objectius
En els materials didàctics d’aquest mòdul trobarem els continguts i les eines
indispensables per a assolir els objectius següents:
4. Identificar en quines situacions pot ser útil una taula o un conjunt imple-
mentats amb tècniques de dispersió.
© FUOC • PID_00161972 • Mòdul 6 9 El TAD Taula
Gràficament, dibuixem les taules com indica el seu nom, és a dir, en forma ta-
bular, tals que cada fila conté un parell clau-valor i només hi ha dues colum-
nes, una per a les claus i l’altra per als valors. Aquests parells s’anomenen
entrades de la taula. Si la clau forma part del valor, per convenció, no repetirem
la clau a la part del valor. En la introducció hem mostrat un exemple d’aquesta
representació gràfica.
El model subjacent de les taules són les funcions matemàtiques. Una funció f
és un cos matemàtic que associa valors que pertanyen a dos conjunts A i B, i
es denota per f: A → B. Aquestes associacions són úniques: per cada element
de A hi ha, com a molt, un element de B associat.
Les operacions que caracteritzen el TAD Taula són aquelles que possibiliten
l’accés als valors usant la clau. A continuació mostrem la seva signatura i definició
com a especificació informal de la pre- i post-condició. Denominem diccionari a la
interfície corresponent seguint la nomenclatura que utilitza el llenguatge Java en
la seva biblioteca JCF.
constructor()
Crea una taula.
@pre Cert.
@post Retorna una taula buida.
E esborrar(C clau)
Esborra una entrada de la taula.
@pre Cert.
@post No hi ha cap entrada amb la clau donada a la taula i retorna
com a resultat el valor associat a la clau esborrada (o ‘nul’, si la clau
no era a la taula).
E consultar(C clau)
Obté el valor associat a una clau.
@pre Cert.
@post Obté el valor associat a la clau; retorna ‘nul’ si la clau no és a la taula.
Notem que el resultat no és un objecte vàlid en cas que la clau no existeixi; pot
ser útil, doncs, comprovar-ne prèviament l’existència mitjançant hiEs. Fins i tot,
podríem requerir explícitament que la clau ha d’existir (vegeu l’exercici 1c).
A més d’aquestes operacions, el TAD Taula ofereix les operacions que hereta
dels contenidors: una operació per a saber el nombre d’entrades de la taula
(nombreElements), una per a saber si la taula és buida (estaBuit), una operació
de clonació (clone) i un iterador per a obtenir-ne els elements (elements).
Aquesta operació retorna un iterador sobre les entrades de la taula en un ordre
no determinat. A més, el TAD Taula ofereix un segon iterador, claus, que re-
torna les claus de la taula també en ordre aleatori. Sobre aquests iteradors po-
dem aplicar les operacions habituals per a obtenir-ne els elements.
En una aplicació informàtica per a una acadèmia, es volen guardar les dades personals
dels estudiants: DNI, nom, edat, sexe i domicili. L’acadèmia té prop de 2.000 estudiants.
Atès l’ús que se’n vol fer (per exemple, esborrar i consultar els estudiants a partir del seu
DNI), decidim definir una taula d’estudiants en què la clau és el seu DNI (som, doncs, en
el cas que la clau forma part del valor). Ara volem implementar la taula. Podem constatar
que:
• Si usem una estructura lineal encadenada, com ara una llista dinàmica, per a organit-
zar els estudiants, les operacions d’inserció, supressió i consulta tenen un cost lineal
sobre el nombre d’estudiants, independentment de si l’estructura està ordenada o no
(en el cas de la inserció, perquè cal comprovar si ja existeix alguna entrada amb la clau
donada).
• Si usem un vector gestionat seqüencialment, també tenim un cost lineal per a les ope-
racions d’inserció, supressió i consulta si els elements estan desordenats. En cas d’or-
denar el vector, les consultes passen a tenir un cost logarítmic prou bo, però les
operacions d’inserció i supressió segueixen tenint un cost lineal. En certes condicions,
aquesta ineficiència pot ser admissible, però en d’altres pot ser que no.
19 H 25 H 23 D
25 H 19 H 23 D
• Si usem un vector amb accés directe, aprofitant que els índexs són nombres naturals,
obtenim un cost constant en les operacions d’inserció, supressió i consulta, però mal-
baratem molt l’espai, ja que cal reservar tant espai com DNI hi pugui haver. Normal-
ment, aquesta situació serà inadmissible. A més, els recorreguts en resulten perjudicats:
per a obtenir l’element següent d’un altre, cal recórrer el vector fins a trobar la següent
© FUOC • PID_00161972 • Mòdul 6 13 El TAD Taula
posició lliure. Com a conseqüència, el cost del recorregut és lineal, però no sobre el
nombre d’elements de la taula (és a dir, la dimensió del domini real de la taula), sinó
sobre el nombre de claus possibles (és a dir, la dimensió del domini de la taula), que
normalment serà un factor molt més gran.
Aeroports internacionals
En una aplicació web per a una agència de viatges, es volen enregistrar tots els aeroports
internacionals del món amb les seves dades: situació, capacitat, etc. Els aeroports s’iden-
tifiquen per un codi de tres lletres (per exemple, el de Barcelona a Catalunya és BCN, el
de Rio de Janeiro a Brasil és GIG, etc.). Es requereix que hi hagi una funcionalitat per a
obtenir les dades d’un aeroport a partir del seu codi. La situació és similar a l’anterior, fins
i tot més restrictiva, ja que en aquest cas generalment no és possible accedir a un vector
usant el codi sense aplicar-hi alguna transformació.
1) Les implementacions per vector amb accés directe optimitzen el cost de les
operacions d’accés individual als elements (inserció, supressió i consulta) i
perjudiquen el cost dels recorreguts per iterador. L’eficiència espacial en resul-
ta molt perjudicada perquè l’espai que ocupa l’estructura és fix i molt gran, li-
neal sobre el nombre de claus que existeixen en el domini, ja que cada clau té
una posició reservada. Habitualment, el nombre de claus emmagatzemades en
la taula és molt més petit que aquesta dimensió. Per acabar, cal considerar que
hi ha casos en què la clau no és un índex vàlid de vector (per exemple, clau
string o claus multiatribut), de manera que cal fer una manipulació prèvia.
Inserció O(1) O(nombre real d’elements guardats) O(nombre real d’elements guardats)
Supressió O(1) O(nombre real d’elements guardats) O(nombre real d’elements guardats)
O(nombre real d’elements guardats)
Consulta O(1) O(nombre real d’elements guardats)
O(log nombre real d’elements guardats)
Iterador O(nombre màxim d’elements) O(nombre real d’elements guardats) O(nombre real d’elements guardats)
Espai O(nombre màxim d’elements) O(nombre real d’elements guardats) O(nombre real d’elements guardats)
Per totes aquestes particularitats, no és habitual que les implementacions es- Taules amb pocs elements
mentades siguin admissibles com a implementació del TAD Taula. Per això
Una excepció remarcable és
cerquem altres possibilitats. En concret, sembla interessant la implementació quan la taula té pocs elements,
unes poques desenes. En
per vector amb accés directe sempre que trobem solució als dos problemes aquest cas, es considera que
una representació encadenada
identificats: la possibilitat que la clau no permeti indexar el vector directa- o seqüencial és admissible.
ment i el malbaratament d’espai. Per al primer problema, necessitem ser capa-
ços de convertir qualsevol clau en un enter que sí que puguem utilitzar per a
indexar el vector. Per al segon problema, hem de dimensionar el vector amb
aproximadament tantes posicions com claus esperem a la taula.
Un examen més detallat del segon exemple ens pot ajudar a generar algunes
idees bàsiques per a gestionar aquesta situació. És obvi que el codi d’aeroport
es pot transformar de manera senzilla en un enter mitjançant la fórmula ade-
quada. Per exemple, un hipotètic aeroport amb codi AAA podria tenir assigna-
da la posició 0 del vector, el de codi AAB la posició 1, AAC la 2, [...], AAZ la 25,
ABA la 26, etc., fins a l’hipotètic ZZZ que tindria la posició 17.575 (hi ha
17.576 codis des del AAA fins al ZZZ usant les 26 lletres de l’alfabet anglès).
0000H 0 AAA 0
0001H 1 AAB 1
0002H 2 AAC 2
... ... ... ...
0009H 0 ABA 27
000AH 10 ... ...
Hexadecimal Decimal Codi aeroport Decimal
Segons aquesta regla, els codis “vertaders” (és a dir, que identifiquen aeroports
existents) tindrien assignats enters: per exemple, BCN tindria assignat l’enter 741
© FUOC • PID_00161972 • Mòdul 6 15 El TAD Taula
mentre que GIG tindria assignat l’enter 4.270. Aquesta fórmula es pot expressar
matemàticament si ens adonem que el codi d’aeroport és com un nombre en
base 26, usant les lletres de l’alfabet anglès com a dígits. Ho podem entendre mi-
llor si recordem com s’escriuen els nombres hexadecimals (en base 16): quan
s’acaben els dígits del 0 al 9, usem les lletres de la A a la F. Doncs bé, la idea que
proposem aquí és la mateixa.
Sigui COD el codi de l’aeroport format per tres lletres, COD = COD1COD2COD3
(per exemple, en el cas de BCN, tenim que COD1 = ‘B’, COD2 = ‘C’, COD3 = ‘N’).
Definim la transformació de COD en un enter, TRANSF(COD), com:
En què ord és una funció que transforma una lletra de l’alfabet anglès (que té 26
lletres diferents) en un nombre del 0 al 25: ord(A) = 0, ord(B) = 1, ..., ord(Z) = 25.
Aquesta fórmula no és més que la conversió d’un nombre en base 26 expressat
amb lletres en un nombre decimal.
T_aeroport[] A;
A = new T_aeroport[17576];
Fins ara hem solucionat el primer problema, però no el segon: ens trobem amb
el mateix malbaratament d’espai que hem esmentat en l’exemple dels estudi-
ants de l’acadèmia. Si considerem que hi ha uns 1.000 aeroports per emmagat-
zemar en l’aplicació, resulta que hi ha unes 16.576 posicions buides en el
vector. Aquest malbaratament es considerarà normalment intolerable. Com
podem evitar-lo?
A = new T_aeroport[1000];
Clarament des del codi AAA (que va a parar a la posició 0) fins al BML (que va
a parar a la posició 999) no hi ha cap problema; però, què passa a partir del
codi BMM, que hauria d’anar a la posició 1.000 que ja no existeix? Una mane-
© FUOC • PID_00161972 • Mòdul 6 16 El TAD Taula
Així, ens assegurem que TRANSF no pot retornar cap valor més gran que 999
(que és la posició més gran del vector), i a més ja tenim resposta a la pregunta:
el codi BMM té assignada la posició 0, el BMN la 1, etc.
Figura 10. Taula resum sobre l’organització de les taules per dispersió
En la resta de l’apartat estudiem
les funcions i les organitzacions
de dispersió.
Per a ser més precisos, donat el domini A de les claus i donat un enter r, ||A|| representa el nombre
d’elements de A; r << ||A|| significa
que complirà r < ||A|| (i, normalment, r << ||A||) una funció de dispersió que r és molt més petit que ||A||.
h és de la forma h: A → [0, r – 1]. Per a cada clau a ∈ A, h(a) representa
la posició del vector a partir de la qual se cercarà a aplicant la política
pròpia de l’organització de dispersió elegida.
A l’hora de dissenyar les funcions de dispersió, ens regirem per les propietats
següents:
3) La funció de dispersió haurà de ser ràpida de calcular per a evitar que s’alen-
teixi l’accés a la taula. Així, les funcions que per a assegurar que l’accés sigui
aleatori comencin a fer productes, divisions, arrels quadrades, etc., provocaran
problemes d’eficiència temporal, i no oblidem que un dels objectius de la dis-
persió és justament assegurar una bona eficiència temporal.
2) Després, se n’aplica una altra que restringeix un enter a un interval [0, r – 1].
Sigui C el domini dels caràcters de la màquina (UNICODE, ASCII, etc.). Ens in-
teressa trobar una bona funció de dispersió de la forma h: C* → Z, on C* repre-
© FUOC • PID_00161972 • Mòdul 6 19 El TAD Taula
Per a evitar una primera pèrdua d’uniformitat és convenient dur a terme una
traducció de codis mitjançant una funció conv: C → [1, b], essent b el nombre
diferent de caràcters que poden formar part de les claus, de manera que la funció
de conversió h es defineix finalment com a h(a) = h’(CONV(a)), (essent CONV
l’extensió de conv a tots els caràcters de la clau, i h’ una funció h’: [1, b]* → Z).
Aquesta conversió serà més o menys laboriosa segons la distribució dels caràc-
ters dins del codi usat per la màquina. Per exemple, si el codi ho permet (per
exemple, ASCII, però no UNICODE), aquesta conversió es pot implementar
amb un vector V indexat amb el tipus de dades dels caràcters, com V[c] = conv(c)
en aquells caràcters que formen part de la clau, i V[c] = 0 per a la resta.
Podríem dir que la funció SP interpreta les cadenes com nombres en base b
(amb alguns matisos irrellevants).
Exemple
Sigui a = “HOLA”, b = 26 i una funció conv que assigna valors enters a partir de l’1 a les
lletres majúscules. Llavors:
ter en el resultat seria independent del lloc en què aparegués, i això incrementaria amb
molta probabilitat el nombre de col·lisions.
2) Es pot produir un sobreeiximent en el càlcul que cal detectar abans que re-
alment tingui lloc. Per exemple, si b val 26, en una màquina que usi 32 bits
per a representar els enters, es pot produir sobreeiximent a partir del vuitè ca-
ràcter. Una solució consisteix a ignorar els bits que es van generant fora de la
dimensió de la paraula del computador, però aquesta estratègia ignora certa
quantitat d’informació, per la qual cosa redueix l’aleatorietat de la clau; a més,
no sempre és possible i/o eficient detectar i ignorar aquest sobreeiximent.
presentació de la taula. L’objectiu és ara trobar una bona funció de dispersió Podeu trobar una
panoràmica de les funcions
de la forma h: Z → [0, r – 1], de manera que es puguin transformar enters grans de restricció d’un enter en un
interval en l’obra següent:
(ja siguin obtinguts mitjançant la funció de la suma ponderada, ja siguin di-
X. Franch (2001). Estructuras
rectament les claus) en índexs vàlids. En els textos del món de les estructures de datos: especificación, diseño
e implementación (4a. ed.).
de dades, existeixen moltes propostes, i aquí veurem la més simple, que es Barcelona: Edicions UPC
(Politext, núm. 30).
comporta bé en la majoria dels casos, la funció del mòdul. Disponible en línia a:
http://www.edicionsupc.es
A partir d’un enter x, la funció del mòdul, denotada per MOD, es defi-
neix com MOD(x) = x mod r.
Com ja s’ha dit, les organitzacions de dispersió s’ocupen de resoldre les col·li-
sions que es produeixen durant la vida d’una taula de dispersió. Hi ha diverses
estratègies de dispersió que, com és habitual, podem classificar en encadena-
des i en seqüencials. Començarem estudiant una variant de les primeres, la
dispersió encadenada oberta –potser la implementació més intuïtiva del
concepte de dispersió–, i després passarem a l’organització seqüencial típica,
l’adreçament obert. Sigui quina sigui l’organització de dispersió adoptada, re-
© FUOC • PID_00161972 • Mòdul 6 22 El TAD Taula
En aquest gràfic, es mostra la llista corresponent als s sinònims que hi ha per a claus amb valor de dispersió igual a 0.
© FUOC • PID_00161972 • Mòdul 6 23 El TAD Taula
• constructor() O(MIDA_TAULA_PER_DEFECTE)
– Crida al constructor amb MIDA_TAULA_PER_DEFECTE com a nombre
d’elements màxim (O(MIDA_TAULA_PER_DEFECTE)).
© FUOC • PID_00161972 • Mòdul 6 24 El TAD Taula
• constructor(int r) O(r)
– Crea el vector d’elements (O(r)).
uoc.ei.tads.TaulaDispersio
package uoc.ei.tads;
...
...
1) Es troba una posició p tal que la seva clau és a. Se substitueix la seva infor-
mació associada per b.
2) Es troba una posició ps que és buida. S’hi col·loca el parell (a, b). Si s = 0,
vol dir que la clau ocupa la posició que li correspon. Si s > 0, de la clau a se’n
diu invasora (perquè ocupa un lloc que no és el seu).
ons. Suposem que la funció de dispersió h porta l’element a la posició del seu
subíndex. Suposem també que quan una posició es troba ocupada, s’explora
la següent, i així successivament.
Ara, l’únic que queda per determinar són les estratègies de redispersió que cal
utilitzar en l’organització vista. Podem trobar en la literatura diverses propos-
tes. Totes compleixen les propietats següents:
La darrera propietat vol dir que, si bé és inevitable que dues claus compartei-
xin part dels seus camins, cal evitar que l’encavalcament sigui total a partir
d’un punt determinat. En cas contrari, a la que es produís una primera col·li-
sió, se’n produirien moltes més; eventualment, cada assaig provocaria una
nova col·lisió. Aquest fenomen s’anomena apinyament i és present en diferents
graus en totes les estratègies; el que passa és que, en algunes, el grau d’apinya-
ment és prou petit per a negligir-lo.
plica col·lisions futures més que ocasionalment (amb les mateixes probabili-
tats que si no n’hi haguessin hagut anteriorment). De fet, el mètode de
redispersió doble s’apropa molt als resultats teòricament més bons, sempre
que h i g hagin estat correctament dissenyades.
Per acabar, notem que, a diferència del mètode lineal, no es poden moure ele-
ments perquè en esborrar-ne, no se sap trivialment de quines cadenes formen
part.
taula i que s’usa per dimensionar un vector. A més, des del punt de vista del
rendiment de la taula, el valor r té una importància cabdal:
• En el cas de l’organització per adreçament obert, els perills són els matei-
xos: una funció de dispersió que distribueixi malament i una taxa d’ocupa-
ció elevada de la taula. Cal veure, a més, que hi ha una restricció física
insalvable: no hi poden cabre més d’r claus, de manera que la taxa d’ocu-
pació mai no serà superior a 1. Però de fet, hi ha resultats que mostren que
el rendiment d’aquest tipus d’organització comença a ser dolent a partir
d’una taxa d’ocupació del 0,6; per això, normalment el valor r es calcula
per excés respecte del nombre de claus esperades.
La primera opció òbvia per a solucionar el problema és redimensionar el vec- Vegeu el concepte de cost
amortitzat en el mòdul
tor d’r posicions fins al nou valor màxim de dispersió. És una solució molt sim- “Contenidors seqüencials”
d’aquesta assignatura.
ple. A primera vista pot semblar molt ineficient, perquè cal reinserir totes les
entrades de la taula, i això té un cost lineal. Però aquí hem d’analitzar el cost
amortitzat (que s’ha introduït en el mòdul d’estructures seqüencials): si cal re-
inserir N entrades en el nou vector, el nombre mínim d’insercions que haurem
efectuat en la taula és N, cadascuna amb una eficiència O(1), de manera que el
cost que arrosseguem és O(N), i el cost O(N) de la reinserció queda compensat.
La figura següent mostra un exemple de redimensionament passant d’una tau-
la de 5 elements a una taula de 10 elements. La funció de dispersió es defineix * Aquesta és la solució
implementada a la JCF.
com el valor del subíndex de la clau mòdul la dimensió del vector.*
En aquesta estratègia, es disposa d’una taula índex que, com a informació, conté
apuntadors a zones de memòria que són les que realment contenen les entrades
de la taula organitzades mitjançant qualsevol de les organitzacions de dispersió
vistes. Aquest vector índex s’indexa usant els s bits de l’esquerra de la clau. La
posició indexada del vector es correspon a la interpretació decimal d’aquests s
bits. Com a resultat, la dimensió del vector és 2s, una magnitud considerable-
ment menor que r. La figura 17 mostra un exemple amb s = 2; mostrem el con-
tingut d’una de les taules suposant que les claus a tenen els seus tres bits de més
a l’esquerra igual a 010, i les b, igual a 011.
3. El TAD Conjunt
Una evolució del concepte taula és el de conjunt, en què la clau i el valor que
s’emmagatzemen en la taula coincideixen. Exemples clàssics són conjunts de
strings o d’enters. Si bé el model matemàtic subjacent i la interfície varien lleu-
gerament, les estratègies d’implementació són idèntiques al cas de les taules,
adaptades a la peculiaritat esmentada.
El model subjacent del TAD Conjunt són els conjunts de les matemàtiques. Un
conjunt C d’elements d’un domini A conté elements de A sense repeticions.
Denotem per P(A) tots els possibles conjunts que es poden formar amb ele-
ments d’A. Les operacions bàsiques són anàlogues al cas de les taules i, a més,
es presenten operacions d’unió, intersecció i diferència. A continuació mos-
trem la seva signatura i especificació pre-post.
constructor()
Crea un conjunt.
@pre Cert.
@post Retorna un conjunt buit.
Elements ja inserits
void afegir(E elem)
Per la definició de Conjunt, si
Afegeix un element al conjunt. l’element inserit ja era en el
conjunt, l’operació no té efec-
@pre Cert. te, ja que els conjunts no tenen
@post L’element pertany al conjunt. elements repetits.
A més d’aquestes operacions, el TAD Conjunt ofereix les operacions que hereta
dels contenidors: una operació per a saber el nombre d’entrades de la taula
(nombreElements), una per a saber si la taula és buida (estaBuit), una operació
de clonació (clone) i un iterador per a obtenir-ne els elements (elements).
Aquesta operació retorna un iterador sobre les dades de la taula en un ordre
aleatori. Sobre aquest iterador, podem aplicar les operacions habituals per a
obtenir els elements.
Figura 20
• constructor() O(MIDA_TAULA_PER_DEFECTE)
– Crida al constructor amb MIDA_TAULA_PER_DEFECTE com a nombre
d’elements màxim (O(MIDA_TAULA_PER_DEFECTE)).
© FUOC • PID_00161972 • Mòdul 6 36 El TAD Taula
• constructor(int r) O(r)
– Crea la taula de dispersió (O(r)).
uoc.ei.tads.ConjuntAbstracte
package uoc.ei.tads;
public abstract class ConjuntAbstracte<E> implements Conjunt<E> {
uoc.ei.tads.ConjuntTaulaImpl
package uoc.ei.tads;
public class ConjuntTaulaImpl<E> extends ConjuntAbstracte<E> {
protected TaulaDispersio<E,E> td;
...
public void afegir(E elem) { td.afegir(elem, elem); }
public boolean hiEs(E elem) {
return td.consultar(elem) != null; }
public E consultar(E elem) {
return td.consultar(elem); }
public E esborrar(E clau) {
return td.esborrar(clau); }
public Iterador<E> elements() {
return td.elements(); }
}
© FUOC • PID_00161972 • Mòdul 6 38 El TAD Taula
Figura 21
Clarament, una taula de símbols és una mena de taula de dispersió amb la petita
complicació del tractament dels blocs. Fixem-nos que la taula de la figura 13 no
es pot considerar com una taula de dispersió, perquè les claus (en aquest cas,
els identificadors del programa) hi poden aparèixer més d’una vegada. Una
solució simple seria considerar que cada entrada de la taula té, no pas unes
característiques úniques, sinó una seqüència de característiques en què cada ele-
ment identifica, a més, el bloc al qual està associat, tal com mostra la figura 22.
En realitat la seqüència és una pila, ja que se segueix l’estratègia “el darrer que
hi entra és el primer que en surt”.
uoc.ei.exemples.modul6.TaulaSimbols
...
public interface TaulaSimbols {
void entra();
void surt();
void declara(String id, Categoria categoria,
Tipus tipus, int dimensio);
PropietatsSimbol consulta(String id);
uoc.ei.exemples.modul6.ProvaTaulaSimbols
...
TaulaSimbols ts=creaTaulaSimbols();
ts.declara(“P”,Categoria.PROGRAM,
Tipus.NO_DEFINIT, 10230);
ts.declara(“a”,Categoria.VAR,Tipus.INT, 1024);
ts.declara(“b”,Categoria.VAR,Tipus.INT, 1026);
ts.declara(“Q”,Categoria.PROC,
Tipus.NO_DEFINIT, 10500);
ts.entra();
ts.declara(“c”,Categoria.PARAM,Tipus.INT, 1028);
ts.declara(“a”,Categoria.VAR,Tipus.REAL, 1030);
ts.declara(“d”,Categoria.VAR,Tipus.REAL, 1032);
ts.surt();
© FUOC • PID_00161972 • Mòdul 6 41 El TAD Taula
Operació Cost
creació O(N)
entra O(1)
surt O(N)
declara O(1)
consulta O(1)
Per a trobar la solució, caldria donar forma tant a la funció com a l’organitza-
ció de la taula de dispersió. Elegim la funció de suma ponderada per convertir
l’identificador en enter, i la funció de mòdul per restringir l’enter a un àmbit.
Pel que fa a la primera, cal determinar el nombre de caràcters diferents vàlids;
pel que fa a la segona, cal determinar l’estratègia i el nombre esperat d’identi-
ficadors que pot emmagatzemar la taula en un moment donat.
Per acabar, constatem que com que un identificador pot tenir un gran
nombre de caràcters (fins a 80 en moltes implementacions del traductor),
es pot produir sobreeiximent amb molta facilitat, i apliquem la tècnica ex- Vegeu la tècnica per a evitar el
sobreeiximent explicada al final del
subapartat 2.1.1 d’aquest mòdul.
plicada per evitar el sobreeiximent. En aquest cas, com b = 37 i suposem
que maxent = 231 – 1, el resultat és que la clau s’ha de partir en trossos de 5 bits.
Amb totes aquestes dades, ja podem completar la codificació en Java de la
taula de símbols.
© FUOC • PID_00161972 • Mòdul 6 42 El TAD Taula
uoc.ei.exemples.modul6.TaulaSimbolsImpl
...
public TaulaSimbolsImpl() {
nombreBlocsImbricats = 0;
taula = new TaulaDispersioSimbols();
}
uoc.ei.exemples.modul6.TaulaDispersioSimbols
...
class TaulaDispersioSimbols extends TaulaDispersio<String,Pila<PropietatsSimbol>> {
private static final int MIDA_TAULA = 1023;
public TaulaDispersioSimbols() {
super(MIDA_TAULA);
}
uoc.ei.exemples.modul6.PropietatsSimbol
Atès que les taules i els conjunts són dos TAD de gran tradició, les biblioteques
d’estructures de dades més difoses els inclouen. Aquest és el cas de la Java Co-
llections Framewok (JCF), que ofereix tant interfícies com implementacions.
La JCF ofereix interfícies tant per a les taules com per als conjunts. La interfície
dels conjunts, Set, és hereva de Collection, i remarcablement només presenta
aquestes operacions heretades. Les operacions es poden classificar en tres grans
tipus:
1) Operacions bàsiques, que són les pròpies del TAD: add, remove, contains,
size, isEmpty i iterator.
Pel que fa a la interfície de les taules, Map, no tenim aquesta relació d’herència
i presenta com a operacions:
La JCF ofereix dues implementacions tant per a les taules com per als conjunts. Vegeu les implementacions per a
taules i conjunts de la JCF per
L’una usa dispersió de forma similar a la presentada en aquest mòdul, i l’altra estructures arborescents en el mòdul
“Arbres de cerca” d’aquesta assignatura.
usa estructures arborescents. Les implementacions per dispersió s’anomenen
HashMap i HashSet, i implementen la interfície corresponent (Map o Set) i tam-
bé la Cloneable. Les jerarquies de les figures 23 i 24 mostren també l’existència
d’algunes classes abstractes, AbstractSet i AbstractMap, que s’usen per a imple-
mentar l’esquelet de les autèntiques implementacions, i de codificar tot allò
que no depèn de l’estratègia d’implementació.
Les operacions constructores tenen dos paràmetres, tal com queda palès a la
seva interfície:
uoc.ei.exemples.modul6.jcf.TaulaSimbolsImpl
...
public class TaulaSimbolsImpl implements TaulaSimbols {
private int nombreBlocsImbricats;
private Map<String,Stack<PropietatsSimbol>> taula;
public TaulaSimbolsImpl() {
nombreBlocsImbricats=0;
taula=new TaulaDispersioSimbols();
}
uoc.ei.exemples.modul6.TaulaDispersioSimbols
...
class TaulaDispersioSimbols extends HashMap<String,Stack<PropietatsSimbol>> {
private static final int MIDA_TAULA = 1023;
public TaulaDispersioSimbols() {
super(MIDA_TAULA);
}
}
© FUOC • PID_00161972 • Mòdul 6 50 El TAD Taula
Resum
3) Cal efectuar una anàlisi per a decidir quina funció de dispersió i quina or-
ganització de dispersió són les adients per al context d’ús.
Activitats
1. Doneu una especificació pre-post formal de les operacions sobre taules presentades en
l’apartat 1 d’aquest mòdul basada en el model matemàtic de funció. Com a exemple,
mostrem l’especificació de l’operació d’afegir:
t: Taula, a, b: Object
{ Pre: t = t0 ∧ a = a0 ∧ b = b0 }
t.afegir(a, b)
{ Post:
dom(t) = dom(t0) ∪ {a0} ∧ -- la clau a passa a formar part del domini real de t
t(a0) = b0 ∧ -- la clau a té b com a valor associat dins t
∀x: x∈dom(t) ∧ x ≠ a0: t(x) = t0(x)} -- la resta d’entrades de t segueixen com abans
4. Doneu una especificació pre-post formal de les operacions sobre conjunts presentades en
l’apartat 3 d’aquest mòdul.
Exercicis d’autoavaluació
2. Proposeu altres operacions per a les taules. Raoneu per què podrien ser interessants, pre-
feriblement donant-ne un context d’ús.
3. Apliqueu la funció de dispersió de la suma ponderada sobre les cadenes UOC, BOTIFLER i
CAPSIGRANY, suposant que els caràcters vàlids són les lletres majúscules de l’alfabet anglès.
4. Siguin unes claus que representen noms de ciutat (en majúscules i poden aparèixer gui-
ons, punts i espais en blanc) amb un màxim de 35 caràcters, i sigui un ordinador que re-
presenta els nombres enters amb 32 bits en la codificació de complement a 2. Volem
adaptar la funció de suma ponderada amb control de sobreeiximent a aquests supòsits.
Determineu el valor de maxent, b, k i m que defineixen aquesta funció.
5. Descriviu breument algunes funcions de dispersió adequades per als casos següents de
claus multiatribut:
a) nom i cognoms;
b) codi de caixa i número de compte;
c) districte postal, carrer i número.
6. La funció conv es defineix sobre l’abast [1, b]. Per què no es pot definir sobre l’abast [0, b − 1]?
8. Sigui un conjunt implementat amb una taula de dispersió d’adreçament obert de 7 posi-
cions en què les dades són nombres enters. Suposeu que la funció de dispersió és simple-
ment h(x) = x mod 7. Simuleu el comportament de la taula en efectuar la seqüència
d’operacions següent: inserció del 7, inserció del 17, inserció del 0, supressió del 7, inser-
ció del 22, inserció del 13, inserció del 20, supressió del 0. Considereu les tres alternatives
de redispersió següents:
a) lineal amb k = 1 i sense moviments a la supressió.
b) lineal amb k = 1 i moviments a la supressió.
c) doble amb g(x) = 1 + (x mod 5).
© FUOC • PID_00161972 • Mòdul 6 52 El TAD Taula
9. Sigui un conjunt implementat amb una taula de dispersió encadenada oberta de 7 posi-
cions, en què les dades són nombres enters. Suposeu que la funció de dispersió és simple-
ment h(x) = x mod 7. Suposeu que s’insereixen els enters següents en aquest ordre: 123,
49, 1, 22, 18, 23 i 100. Suposeu que el factor de càrrega permès a la taula és del 100%, de
manera que en inserir l’element 50 es produeix un sobreeiximent que es vol solucionar
doblant la dimensió de la taula. Mostreu la taula de dispersió resultant amb una nova tau-
la de 15 elements i funció de dispersió h(x) = x mod 15.
10. Volem implementar un diccionari amb operacions d’accés directe per paraula i recorre-
gut alfabètic. Suposeu que l’espai que ocupa cada entrada del diccionari (que conté la pa-
raula i la seva definició) és de X bits, un valor fix. Suposeu que el nombre esperat
d’entrades és N. Descriviu l’estructura de dades i les operacions necessàries per a oferir
una bona eficiència en els operacions d’accés directe per paraula. Determineu el cost tem-
poral asimptòtic de les diferents operacions del diccionari i l’espai usat (en bits i com a
funció de X i N), suposant que els enters i les adreces de memòria ocupen 32 bits.
11. Es vol implementar un dipòsit d’adreces web per a un navegador. El dipòsit consta
d’adreces URL exclusivament. Implementeu-lo mitjançant un conjunt. Feu-ne dues ver-
sions, amb la JCF i amb la biblioteca de classes de l’assignatura.
12. Es vol generar una aplicació de gestió dels alumnes i les assignatures d’una universitat. A
aquest efecte, els alumnes s’identifiquen pel seu DNI i se’n coneix el nom i cognoms,
l’adreça postal, l’adreça electrònica i l’edat. De les assignatures se’n sap el codi identifica-
dor, el nom i el nombre de crèdits. Es demana que implementeu aquestes dues estructu-
res com a taules de dispersió (les podeu encapsular mitjançant un nou TAD) i que feu un
programet de prova. A continuació, esteneu la implementació (i el TAD definit) per a in-
cloure-hi una operació per a matricular alumnes d’assignatures.
© FUOC • PID_00161972 • Mòdul 6 53 El TAD Taula
Solucionari
Activitats
1. En les precondicions, bàsicament es fixen els valors inicials dels objectes, és a dir, els va-
lors que tenen els objectes abans de l’execució de l’operació i totes aquelles condicions
que hagin de complir; mentre que les postcondicions mostren el canvi de valor d’aquests
objectes i referencien els valors inicials que apareixen en la precondició:
t: Taula, a, b: Object
{ Pre: t = t0 ∧ a = a0 }
b = t.esborrar(a)
{ Post:
dom(t) = dom(t0) – {a0} ∧ -- la clau a deixa de formar part del domini real de t
∀x: x∈dom(t): t(x) = t0(x) ∧ -- la resta d’entrades de t segueixen com abans
a0∈dom(t0) ⇒ b = t0(a0) ∧ -- si hi havia una entrada dins t amb clau a, es guarda a b el seu
valor associat
a0∉dom(t0) ⇒ b = null } -- altrament, b acaba valent null
t: Taula, a, b: Object
{ Pre: t = t0 ∧ a = a0 }
b = t.consultar(a)
{ Post: a0∈dom(t0) ⇒ b = t0(a0) ∧ -- si hi havia una entrada dins t amb clau a, es guarda a b el
seu valor associat
a0∉dom(t0) ⇒ b = null } -- altrament, b acaba valent null
4.
c: Conjunt, x: Object
{ Pre: c = c0 ∧ x = x0 }
c.afegir(x)
{ Post: c = c0 ∪ {x0} }
c: Conjunt, x: Object
{ Pre: c = c0 ∧ x = x0 }
c.esborrar(x)
{ Post: c = c0 - {x0} }
Exercicis d’autoavaluació
t: Taula, a, b: Object
{ Pre: no n’hi ha }
t.afegir(a, b)
{ Post: si la clau no era dins la taula t, el valor b passa a estar associat amb la clau a dins
de la taula t }
t: Taula, a, b: Object
{ Pre: t = t0 ∧ a = a0 ∧ b = b0 }
t.afegir(a, b)
{ Post: dom(t) = dom(t0) ∪ {a0} ∧ -- la clau a passa a formar part del domini real de t
a0∉dom(t0) ⇒ t(a0) = b0 ∧ -- la clau a té b com a valor associat dins t, si a no era dins t
∀x: x∈dom(t) ∧ x ≠ a0: t(x) = t0(x) } -- la resta d’entrades de t segueixen com abans
Segona variant:
t: Taula, a, b: Object
{ Pre: la clau a no és dins t }
t.afegir(a, b)
{ Post: el valor b passa a estar associat amb la clau a dins de la taula t }
© FUOC • PID_00161972 • Mòdul 6 54 El TAD Taula
t: Taula, a, b: Object
{ Pre: t = t0 ∧ a = a0 ∧ b = b0 ∧ a0∉dom(t0) }
t.afegir(a, b)
{ Post: dom(t) = dom(t0) ∪ {a0} ∧ -- la clau a passa a formar part del domini real de t
t(a0) = b0 ∧ -- la clau a té b com a valor associat dins t
∀x: x∈dom(t) ∧ x ≠ a0: t(x) = t0(x) } -- la resta d’entrades de t segueixen com abans
b)
t: Taula, a: Object
{ Pre: la clau a és dins t }
t.esborrar(a)
{ Post: elimina l’entrada amb clau a de la taula t }
t: Taula, a: Object
{ Pre: t = t0 ∧ a = a0 ∧ a0∈dom(t0) }
t.esborrar(a)
{ Post: dom(t) = dom(t0) – {a0} ∧ -- la clau a deixa de formar part del domini real de t
∀x: x ∈ dom(t): t(x) = t0(x) } -- la resta d’entrades de t segueixen com abans
c)
t: Taula, a, b: Object
{ Pre: la clau a és dins t }
b = t.consultar(a)
{ Post: retorna el valor associat a la clau a dins de la taula t }
t: Taula, a, b: Object
{ Pre: t = t0 ∧ a = a0 ∧ a0∈dom(t0) }
b = t.consultar(a)
{ Post: b = t0(a0) }
2. Podem trobar diverses propostes. Per exemple, si pensem en l’aplicació de les taules com a
taules de símbols, dues operacions pràctiques podrien ser obrirAmbit i tancarAmbit. La pri-
mera enregistraria que, durant el procés de traducció, s’entra en un nou àmbit dins del pro-
grama, és a dir, una nova classe, un nou mètode, etc. En obrir un nou àmbit, és lícit declarar
nous objectes que estiguin identificats per noms utilitzats en àmbits anteriors. En tancar
l’àmbit, haurien de desaparèixer de cop tots aquells identificadors de la taula introduïts en
l’àmbit.
Més genèricament, altres operacions que de vegades resulten útils són els recorreguts or-
denats. Ja hem dit que els recorreguts definits en el TAD de les taules obtenen els ele-
ments en un ordre no determinat, la qual cosa de vegades no és convenient. Hi ha força
contextos en què pot interessar trobar els elements ordenats alfabèticament (per nom,
per DNI, etc.) o numèricament.
També és necessari, ocasionalment, fusionar dues taules, és a dir, ajuntar les entrades de les
dues taules per a formar-ne una de nova. Òbviament, es requereix que els dominis i abastos
de les dues taules siguin els mateixos. L’especificació ha de determinar ben clarament què
passa quan una mateixa clau apareix en les dues taules i associada a un valor diferent en
cadascuna.
3. Mostrem els càlculs en la taula següent. Hi ha 10 columnes, una per cada caràcter del nom
(UOC en té 3; BOTIFLER, 8; i CAPSIGRANY, 10). Per cada cadena, mostrem: una fila per als
caràcters que la formen, la seva conversió amb la funció conv, la potència de 26 correspo-
nent, i el producte de cada sumand. El resultat SP es mostra en la darrera columna, SP(a).
k 1 2 3 4 5 6 7 8 9 10 SP(a)
a U O C
conv 21 15 3
bk-1 1 26 676
a B O T I F L E R
conv 2 15 20 9 6 12 5 18
a C A P S I G R A N Y
conv 3 1 16 19 9 7 18 1 14 25
4. Si considerem les 26 lletres majúscules i els tres caràcters addicionals, tenim b = 29.
El valor maxent és igual a 231 – 1 = 2147483647 (a partir de les característiques de la codificació
per complement a 2). Per als altres dos valors, hem de calcular-los a partir de la fórmula:
Anem donant valors amb una taula fins que ens passem:
És a dir, el k més gran és k = 5, la qual cosa significa que hem de partir la clau en, com a
mínim, 7 trossos (quan té la longitud màxima de 35 caràcters).
5.
a) En el primer cas, simplement concatenem el nom i els cognoms per obtenir una ca-
dena de caràcters sobre la qual apliquem la funció habitual (suma ponderada seguida
del’operació mòdul).
b) Si considerem que totes dues són nombres enters, tenim diverses opcions. Per exem-
ple, podem transformar els dos enters per separat i sumar-ne els resultats. També podem
formar un enter per la composició dels dos enters i aplicar el mòdul sobre el resultat.
També, podem considerar el número de compte com a cadena de caràcters, que aleshores
transformaríem en enter amb la suma ponderada i actuaríem com en el cas anterior. Fi-
nalment, tots dos camps es poden considerar caràcters i estaríem en la situació a.
c) Una vegada més, tenim diverses opcions. Podem considerar el districte postal com un
nombre o com una cadena de caràcters. En el segon cas, el podem combinar amb el carrer
per a tenir una única cadena a la qual aplicar la suma ponderada i combinar el resultat
amb el nombre seguint qualsevol de les opcions vistes en l’apartat b.
En els casos b i c, una alternativa diferent seria considerar dos nivells de tractament de les
dades. Per exemple, en el cas b podem tenir una primera estructura (que potser no caldria
que fos una taula de dispersió, perquè el nombre diferent de codis de bancs i caixes no és ex-
cessivament gran) que permeti a cada element (que representi un banc o caixa) tenir associ-
ada una taula de dispersió que emmagatzemi els comptes del banc o caixa, tal com mostra la
figura 25. En el cas c es pot fer un raonament similar aplicat als codis postals.
6. Perquè en aquest cas hi hauria claus que tindrien el mateix valor de suma ponderada SP.
En concret, si imaginem per un moment que, efectivament, conv es defineix sobre l’abast
[0, b – 1] i que les claus estan formades per lletres minúscules, és a dir b = 26, veurem que
SP(‘a’) = SP(‘aa’):
SP(‘a’) = conv(‘a’) = 0
SP(‘aa’) = conv(‘a’) + conv(‘a’) × 26 = 0
© FUOC • PID_00161972 • Mòdul 6 56 El TAD Taula
7. L’operació d’esborrar ha de recórrer tota la llista de sinònims, ja que la clau que identifica
l’entrada a esborrar pot estar repetida i limitar-nos a esborrar la primera entrada que tro-
bem no és suficient. Les operacions de consulta i comprovació d’existència funcionen
igual. Remarquem que l’operació de consulta ha d’esbrinar el valor de la primera entrada
que trobem, que és l’última inserció feta per la clau. Les operacions d’iteració són més
complicades, perquè cal evitar visitar les entrades corresponents a claus que han canviat
de valor associat per insercions posteriors. L’eficiència de totes les operacions –tret de la
inserció– empitjora perquè ara les llistes no tenen un nombre d’elements proporcional a
les claus existents, sinó a les insercions efectuades. Per la mateixa raó, l’eficiència espacial
és pitjor, lineal sobre el nombre d’insercions efectuades a la taula. Per això, aquesta estra-
tègia és especialment dolenta quan les taules s’actualitzen amb molta freqüència i, en
particular, quan una clau es modifica moltes vegades mentre està inserida dins de la tau-
la. En canvi, és bona quan una clau no es modifica mai, atès el context d’ús de la taula.
Per exemple, imagineu-vos una taula que guardés tots els alumnes graduats de la UOC.
Com normalment aquests alumnes, un cop inserits a la taula, no es modificarien mai,
aquesta estratègia seria millor que l’habitual.
8.
a)
9.
© FUOC • PID_00161972 • Mòdul 6 57 El TAD Taula
10. El diccionari es pot considerar un conjunt de paraules. L’estructura de dades és una taula
de dispersió que podem implementar de manera encadenada oberta. Les operacions són
les habituals: inserir una paraula al diccionari, esborrar-l’en quan ha quedat obsoleta, mi-
rar si existeix i obtenir-ne la definició. Totes aquestes operacions són O(1) suposant el
bon comportament de la funció de dispersió. L’espai usat d’una taula de dispersió enca-
denada oberta es calcula de la manera següent:
11.
uoc.ei.exercicis.modul6.exercici11.DipositURLImpl
...
public class DipositURLImpl implements DipositURL {
private Conjunt<String> diposit;
public DipositURLImpl() {
diposit = new ConjuntAVLImpl<String>();
}
uoc.ei.exercicis.modul6.exercici11.DipositURLJCLImpl
...
public class DipositURLJCFImpl implements DipositURL {
private Set<String> diposit;
public DipositURLJCFImpl() {
diposit = new HashSet<String>();
}
12.
uoc.ei.exercicis.modul6.exercici12.TaulaAlumnes
...
public class TaulaAlumnes extends TaulaDispersio<String,Alumne> {
public TaulaAlumnes() { super(1023); }
}
uoc.ei.exercicis.modul6.exercici12.TaulaAssignatures
...
public class TaulaAssignatures extends TaulaDispersio<String,Assignatura> {
public TaulaAssignatures() { super(257); }
}
© FUOC • PID_00161972 • Mòdul 6 58 El TAD Taula
uoc.ei.exercicis.modul6.exercici12.CursAcademicImpl
...
public class CursAcademicImpl implements CursAcademic {
TaulaAlumnes alumnes;
TaulaAssignatures assignatures;
public CursAcademicImpl() {
alumnes = new TaulaAlumnes();
assignatures = new TaulaAssignatures();
}
Glossari
camí d’una clau m Seqüència de valors de dispersió generada per una funció de redispersió
aplicada reiteradament sobre una clau.
clau invasora f En una taula de dispersió d’adreçament obert, clau que ocupa una posició
del vector diferent del seu valor de dispersió.
clau sinònima f Clau que té el mateix valor de dispersió que una altra.
col·lisió f Inserció d’una clau a en una taula en què ja existeix una altra clau amb el mateix
valor de dispersió que a.
dispersió f Noció general d’implementació de les taules que utilitza una funció de dispersió que
transforma les claus en valors de dispersió, i resol les col·lisions mitjançant una taula de dispersió.
domini real d’una funció m Conjunt de claus del domini d’una funció per a les quals
existeix un valor associat.
funció f Relació establerta entre dos dominis de dades A i B tal que a cada element de A li
correspon com a molt un element de B. Les funcions de A a B es denoten per A → B. De A,
se’n diu domini de la funció, i de B se’n diu abast de la funció. Dels elements de A se’n diu
claus, i dels de B, valors.
© FUOC • PID_00161972 • Mòdul 6 59 El TAD Taula
funció del mòdul f Funció de restricció d’un enter a un interval basat en l’aplicació de la
divisió entera.
funció de redispersió f Família de funcions de dispersió definides a partir del valor de dis-
persió retornat per una funció de dispersió primària.
redispersió f Noció general d’implementació de les taules d’adreçament obert usant una
funció de redispersió que transforma les claus en valors de dispersió.
taula de dispersió f Mètode de resolució de les col·lisions que es produeixen en una taula
de dispersió.
taula oberta f Mètode d’organització encadenada d’una taula de dispersió, caracteritzat per
l’ús d’un vector indexat pels valors de dispersió, de les posicions del qual pengen llistes de
claus sinònimes del valor de dispersió corresponent.
valor de dispersió m Enter generat per les funcions de dispersió que serveix de mitjà d’ac-
cés a les taules de dispersió.
Bibliografia
Aho, A.; Hopcroft, J.; Ullman, J. (1998). Estructuras de datos y algoritmos. Wilmington:
Addison-Wesley Iberoamericana.
Cormen, T. H.; Leiserson, C. E.; Rivest, R. L.; Stein, C. (2001). Introduction to algorithms
(2a. ed.). MIT Press.