You are on page 1of 52

Recursivitat.

Arbres
Isidre Guix Miranda

Estructures de dades dinmiques

Estructures de dades dinmiques

Recursivitat. Arbres

ndex

Introducci ............................................................................................... Objectius ................................................................................................... 1. Recursivitat ......................................................................................... 1.1. Definici i exemples de recursivitat .......................................... 1.1.1. Clcul del factorial dun nombre natural ....................... 1.1.2. Clcul dun nombre de la srie de Fibonacci ................. 1.1.3. Clcul del capital amb inters compost ......................... 1.2. Recursivitat i piles ...................................................................... 1.2.1. Funcionament intern de la recursivitat ......................... 1.2.2. Simulaci de la recursivitat amb piles ........................... 1.3. Aplicacions clssiques de recursivitat ....................................... 1.3.1. El problema de les torres de Hanoi ................................ 1.3.2. El mtode dordenaci rpida ......................................... 2. Arbres .................................................................................................. 2.1. Arbres binaris .............................................................................. 2.1.1. Implementaci darbres binaris ...................................... 2.1.2. Algorismes de tractament en arbres binaris ................. 2.2. Arbres binaris de recerca ............................................................ 2.2.1. Algorisme de recerca ........................................................ 2.2.2. Algorisme dinserci ......................................................... 2.2.3. Algorisme deliminaci .................................................... 2.3. Arbres balancejats ....................................................................... 2.3.1. Algorisme dinserci ......................................................... 2.3.2. Algorisme deliminaci ................................................... 2.4. Arbres multicam ......................................................................... 2.4.1. Arbres B ............................................................................. 2.4.2. Arbres B+ .......................................................................... 2.4.3. Utilitat en arxius seqencials indexats ..........................

5 7 9 9 10 13 14 16 16 17 19 19 21 23 24 25 26 27 29 29 30 33 34 36 38 39 46 48

Estructures de dades dinmiques

Recursivitat. Arbres

Estructures de dades dinmiques

Recursivitat. Arbres

Introducci

En la unitat didctica Dades lineals en memria dinmica ens hem endinsat en la gesti dinmica de la memria i en la seva aplicaci per a la implementaci destructures de dades lineals: llistes, piles i cues. Ens manca, per, la seva aplicaci en els arbres, un tipus de dada no lineal molt utilitzat en informtica. Abans, per, dintroduir-nos en el coneixement dels arbres, ens cal endinsar-nos en laprenentatge de la recursivitat, ats que la implementaci dels arbres necessiten aquesta tcnica de programaci. Aix doncs, en el nucli dactivitat Recursivitat introdum aquesta tcnica de programaci consistent a resoldre un problema en termes de si mateix. El coneixement daquesta tcnica sacostuma a deixar per al final de laprenentatge de la programaci estructurada i modular pels motius segents: per efectuar i implementar dissenys recursius cal ser, primer de tot, un bon programador de dissenys no recursius (iteratius) i, a ms, cal tenir molta intuci per saber definir la recursivitat correctament. El fet que aquesta unitat didctica versi sobre recursivitat i arbres podria fer pensar que els dos temes han danar de la m, i no s el cas. Simplement, la implementaci del tipus de dada arbre necessita les tcniques recursives, per la recursivitat s aplicable tant al tractament del tipus de dada arbre com a moltes altres situacions en les quals els arbres no tenen res a veure. En el nucli dactivitat Arbres sintrodueix aquest tipus de dada, fonamental per a la gesti dels arxius seqencials indexats. El tipus de dada arbre introdueix el concepte destructura de ramificaci entre nodes. En les estructures lineals esttiques i dinmiques un element noms t un nic segent. Amb el tipus de dada arbre sinicia la introducci del concepte de ramificaci entre nodes. Per tant, s una estructura dinmica no lineal molt important, per no s lnica; nhi ha daltres com el graf. Daltra banda, aquest nucli dactivitat dedicat als arbres no pretn ser una bblia sobre els arbres. Aquest tipus de dada s tan important que sha estudiat llargament i, per tant, shan generat molts conceptes. Aqu noms en farem una introducci. Per aconseguir els nostres objectius, heu de reproduir en el vostre ordinador i, si pot ser, en diverses plataformes, tots els exemples incorporats en el text. Per a aix, trobareu tots els fitxers necessaris en la

Estructures de dades dinmiques

Recursivitat. Arbres

secci Recursos de contingut. Al web tamb trobareu activitats i exercicis dautoavaluaci. I un consell final: com que lassignaci dinmica de memria i la recursivitat sn tcniques molt potents, ens cal conixer-les i aplicar-les, per tamb sn complexes i, per tant, cal anar amb molt de compte!

Estructures de dades dinmiques

Recursivitat. Arbres

Objectius

En acabar la unitat didctica, heu de ser capaos del segent: 1. Distingir quan un problema es pot resoldre informticament amb la utilitzaci de tcniques recursives. 2. Aproximar leficincia dexecuci dels algorismes recursius dissenyats. 3. Avaluar la convenincia dutilitzar un algorisme recursiu o un algorisme iteratiu per al disseny de determinats programes. 4. Efectuar un seguiment acurat de les diferents crides recursives que es produeixen en lexecuci dalgorismes recursius. 5. Identificar diferents estructures darbre i implementar-les en llenguatge C. 6. Dissenyar algorismes eficients de recorregut, inserci, eliminaci i consulta. 7. Aplicar les estructures darbre en la implementaci de sistemes darxius seqencials indexats.

Estructures de dades dinmiques

Recursivitat. Arbres

1. Recursivitat

El concepte de recursivitat apareix en moltes activitats de la vida diria, per exemple en una fotografia duna fotografia, en un passads que t miralls als extrems, encarats lun amb laltre, en un programa de televisi on apareix un televisor per on semet el mateix programa... Per a nosaltres ens interessa el concepte de recursivitat dins lmbit de la programaci informtica.

1.1. Definici i exemples de recursivitat


La recursivitat s aplicable a la resoluci dun problema (matemtic, fsic, informtic...) si aquesta es pot efectuar en termes de si mateix, per en un grau de menys complexitat, de tal manera que el problema queda del tot resolt. Des del punt de vista informtic, la recursivitat implica que un subprograma es crida a si mateix i, per tant, la recursivitat no deixa de ser un cas particular de crides a subprogrames.

La recursivitat s un concepte que permet definir un objecte (problema o estructura de dades) en termes de si mateix. Un subprograma (acci o funci) s recursiu quan al llarg de la seva execuci efectua alguna crida a si mateix.

En els subprogrames la recursivitat es pot donar de dues maneres diferents: Directa: quan el subprograma es crida directament a si mateix. Indirecta: quan el subprograma crida un altre subprograma i aquest, o algun de ms intern, crida el primer. Davant duna situaci recursiva, ens hem de preguntar quan finalitza. El final dun procs recursiu queda garantit amb lexistncia dun estat bsic.

En un procs recursiu un estat bsic s una situaci en la qual ja no sactiva ms recursi.

Estructures de dades dinmiques

10

Recursivitat. Arbres

En un subprograma recursiu, direm que estem en un estat bsic quan la soluci al problema ja no es presenta de manera recursiva sin directament. A partir de la definici dun problema que exigeix una soluci informtica, direm que una definici recursiva s vlida si es pot determinar lestat bsic i es garanteix lapropament successiu del problema a lestat bsic esmentat. La recursi s una eina important que permet escriure un codi de manera ms compacta i, en certs casos, de manera ms fcil. Aix no obstant, ha de quedar clar que la recursi no facilita ms rapidesa dexecuci ni tampoc permet estalviar espai de memria. En general, s recomanable utilitzar recursi quan el problema ho exigeix. Si no s aix, ser ms convenient utilitzar eines de carcter repetitiu. ! Laprenentatge de laplicaci de la recursivitat en la programaci informtica passa sempre pel coneixement duns exemples clssics. A vegades s bo plantejar-se una soluci iterativa i avaluar el temps necessari per executar la soluci recursiva i la soluci iterativa.

1.1.1. Clcul del factorial dun nombre natural


Recordem que el factorial dun natural n es defineix com el producte dels naturals compresos entre 1 i n i matemticament sexpressa n! A ms, per definici, el factorial de zero s 1. Evidentment, es pot observar que n! = n * (n - 1)! Aquesta expressi ens defineix la recursi, ja que per calcular el factorial dun valor ens remet al clcul del factorial dun altre valor. A ms, observeu que el nou valor s el mateix valor decrementat en una unitat. Per tant, aplicant successivament la definici recursiva, arribarem al valor zero, el factorial del qual s 1. Per tant, tenim una definici recursiva del problema que ens acosta a una situaci (factorial de zero) el resultat de la qual coneixem de manera directa (estat bsic). La seva codificaci en pseudocodi seria:

funci factorial (n: natural) retorna natural s si n==0 /* estat bsic */ llavors retorna 1; /* final de la recursivitat */ sin retorna n*factorial (n-1); /* crida recursiva que assegura lapropament a lestat bsic */ fisi fifunci

Estructures de dades dinmiques

11

Recursivitat. Arbres

La seva codificaci en llenguatge C seria:


/* u2n1p01.c */ #include <stdio.h> #include <conio.h> #include "verscomp.h" unsigned long factorial (int n) { if (!n) return 1; return n * factorial (n-1); }

!!
Trobareu el fitxer u2n1p01.c i la resta darxius necessaris en la secci Recursos de contingut del web daquest crdit, concretament a Codi font en C.

void main() { int n,aux; clrscr(); do { printf ("Introdueixi valor no negatiu per a calcular-ne el factorial: "); aux=scanf("%d",&n); neteja_stdin(); } while (aux==0 || n<0); printf ("\n%d! = %lu\n",n,factorial (n)); }

Alerta en lexecuci daquest programa! Pensem que per a lusuari pot ser normal introduir un valor superior a 12 per calcular-ne el factorial, oi? Si agafeu una calculadora que permeti calcular el factorial dun valor (per exemple la calculadora cientfica de Windows) i calculeu 12! i 13! obtindreu els resultats segents: 12! = 479001600 13! = 6227020800 Observem que el resultat de 13! s superior al mxim valor tractable per un unsigned long en plataforma de 32 bits i el programa anterior ens donaria un valor incorrecte, ja que no hi controlem la superaci dels valors mxims permesos. Si ho volem comprovar, podem reversionar el programa anterior i obtenir el segent:
/* u2n1p02.c */ #include #include #include #include <stdio.h> <conio.h> <limits.h> "verscomp.h"

!!
Trobareu el fitxer u2n1p02.c i la resta darxius necessaris en la secci Recursos de contingut del web daquest crdit, concretament a Codi font en C.

unsigned long factorial (int n) /* La funci retorna ZERO si el valor s no calculable segons els tipus de dades emprats degut al fet que el valor "n" provoca resultats massa grans no tractables. */ { unsigned long result; if (!n) return 1; else { result = factorial (n-1); if (ULONG_MAX/n < result) return 0; else return n * result;

Estructures de dades dinmiques

12

Recursivitat. Arbres

} } void main() { int n,aux; unsigned long resultat; clrscr(); printf ("Recordem que el valor mxim per unsigned long s %lu\n",ULONG_MAX); do { printf ("Introdueixi valor no negatiu per a calcular-ne el factorial: "); aux=scanf("%d",&n); neteja_stdin(); } while (aux==0 || n<0); if ((resultat=factorial(n))==0) printf ("El resultat de %d! s massa elevat i no el podem calcular.\n",n); else printf ("\n%d! = %lu\n",n,resultat); }

En aquesta versi podem comprovar que lexecuci de 13! ens informa que no s calculable. Fixem-nos que utilitzem la constant simblic ULONG_MAX, que cont el valor ms gran perms per a tipus unsigned long. Recordem, per, que en plataformes de 32 bits algunes versions de C (gcc, per exemple) incorporen els tipus long long int i unsigned long long int, que permeten valors ms alts. Aix, podem considerar una nova versi del programa:
/* u2n1p03.c */ #include #include #include #include <stdio.h> <conio.h> <limits.h> "verscomp.h"

!!
Trobareu el fitxer u2n1p03.c i la resta darxius necessaris en la secci Recursos de contingut del web daquest crdit, concretament a Codi font en C.

unsigned long long factorial (int n) /* La funci retorna ZERO si el valor s no calculable segons els tipus de dades emprats degut al fet que el valor "n" provoca resultats massa grans no tractables. */ { unsigned long long result; if (!n) return 1; else { result = factorial(n-1); if (ULLONG_MAX/n < result) return 0; else return n * result; } } void main() { int n,aux; unsigned long long resultat; clrscr(); printf ("Recordem que el valor mxim per unsigned long s %lu\n",ULONG_MAX); do { printf ("Introdueixi valor no negatiu per a calcular-ne el factorial: "); aux=scanf("%d",&n); neteja_stdin(); } while (aux==0 || n<0); if ((resultat=factorial(n))==0) printf ("El resultat de %d! s massa elevat i no el podem calcular.\n",n); else printf ("\n%d! = %llu\n",n,resultat); }

Estructures de dades dinmiques

13

Recursivitat. Arbres

Per aconseguir la compilaci en gcc del darrer programa cal incloure lopci std=C99 en lordre de compilaci.

1.1.2. Clcul dun nombre de la srie de Fibonacci


La srie de Fibonacci consisteix a obtenir, a partir dels valors 0 i 1, nous valors sumant sempre els dos anteriors: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, ... s clar que aquesta successi de nombres segueix la definici recursiva:

si n = 0 o n = 1 N fibonacci ( n ) = fibonacci (n 2) + fibonacci (n 1) si n > 1


La seva codificaci en pseudocodi s:
funci fibonacci (n: natural) retorna natural s si n==0 o n==1 /* estats bsics */ llavors retorna n; /* final de la recursivitat */ sin retorna fibonacci(N-1)+fibonacci(N-2) /* crida recursiva amb apropament */ fisi fifunci

El programa en C segent mostra la codificaci de les funcions recursives i iteratives de la funci de Fibonacci i comprova la diferncia de temps dexecuci de les funcions recursives i iteratives.
/* u2n1p04.c */ #include #include #include #include <stdio.h> <conio.h> <time.h> "verscomp.h"

!!
Trobareu el fitxer u2n1p04.c i la resta darxius necessaris en la secci Recursos de contingut del web daquest crdit, concretament a Codi font en C.

unsigned long fibo_recursiu (unsigned long n) { if (n==0) return 0; if (n==1) return 1; return fibo_recursiu(n-1)+fibo_recursiu(n-2); } unsigned long fibo_iteratiu (unsigned int n) { unsigned long r1=0,r2=1,i=2,aux; if (n==0) return 0; if (n==1) return 1; while (i<=n) { aux=r2; r2=r2+r1; r1=aux; i++;} return r2; } void main() { int n,aux; time_t tini,tfin;

Estructures de dades dinmiques

14

Recursivitat. Arbres

clrscr(); do { printf ("Introdueixi valor no negatiu per a calcular-ne el fibonnacci: "); aux=scanf("%d",&n); neteja_stdin(); } while (aux==0 || n<0); tini=time(NULL); printf ("Calculant iterativament...\n"); printf ("ITERATIVAMENT: %lu",fibo_iteratiu(n)); tfin=time(NULL); printf (" Segons: %f\n",difftime(tfin,tini)); tini=time(NULL); printf ("Calculant recursivament...\n"); printf ("RECURSIVAMENT: %lu",fibo_recursiu(n)); tfin=time(NULL); printf (" Segons: %f\n",difftime(tfin,tini)); }

Executeu el programa i comproveu, per a valors relativament grans (a partir de 30 o 40), la diferncia significativa de temps. Els valors obtinguts dependran, lgicament, de la velocitat de procs de la mquina on sexecutin.

1.1.3. Clcul del capital amb inters compost


Pretenem calcular el capital aconseguit desprs de tenir un capital C durant N anys a un inters anual I (percentatge) aplicant els termes del capital compost. Sabem que el capital acumulat en finalitzar el primer any s:
C * (1 + I / 100)

Sobre aquest capital tornem a efectuar el clcul per obtenir el capital acumulat a la fi del segon any. Per tant, es tracta dun procs recursiu que podem plantejar de dues maneres, les quals queden reflectides en les dues versions en pseudocodi.
funci capital_compost1 (C: real, N: natural, I: real) retorna real s si N==0 /* estat bsic */ llavors retorna C; /* fi de la recursivitat */ sin retorna (1+I/100) * capital_compost1 (C, N-1, I); /* crida recursiva */ fisi fifunci funci capital_compost2 (C: real, N: natural, I: real) retorna real s si N==0 /* estat bsic */ llavors retorna C; /* fi de la recursivitat */ sin retorna capital_compost2 ((1+I/100)*C, N-1, I); /* crida recursiva */ fisi fifunci

Estructures de dades dinmiques

15

Recursivitat. Arbres

Vegem un programa en llenguatge C que incorpora les dues modalitats i en comprova lexecuci.
/* u2n1p05.c */ #include #include #include #include <stdio.h> <conio.h> <math.h> "verscomp.h"

!!
Trobareu el fitxer u2n1p05.c i la resta darxius necessaris en la secci Recursos de contingut del web daquest crdit, concretament a Codi font en C.

double arrodonir (double r, unsigned int n) { unsigned int i; for (i=1;i<=n;i++) r=r*10; if (r-floor(r)>=0.5) r = ceil(r); else r = floor (r); for (i=1;i<=n;i++) r=r/10; return r; } double capital_rec1 (double inicial, float interes, unsigned int n, unsigned int dec) { if (n==0) return inicial; return arrodonir((1+inters/100)*capital_rec1(inicial,inters,n-1,dec),dec); } double capital_rec2 (double inicial, float inters, unsigned int n, unsigned int dec) { if (n==0) return inicial; return capital_rec2(arrodonir(inicial*(1+inters/100),dec),inters,n-1,dec); } void main() { int n,dec,aux; double inicial; float interes; clrscr(); do { printf ("Capital inicial (no negatiu): "); aux=scanf("%lf",&inicial); neteja_stdin(); } while (aux==0 || inicial<0); do { printf ("Nombre d'anys (no negatiu): "); aux=scanf("%d",&n); neteja_stdin(); } while (aux==0 || n<0); do { printf ("Inters anual (no negatiu): "); aux=scanf("%f",&interes); neteja_stdin(); } while (aux==0 || inters<0); do { printf ("Nombre de decimals de la moneda (no negatiu): "); aux=scanf("%d",&dec); neteja_stdin(); } while (aux==0 || dec<0); printf ("\nVersi 1: %lf\n",capital_rec1(inicial,inters,n,dec)); printf ("\nVersi 2: %lf\n",capital_rec2(inicial,inters,n,dec)); }

En aquest programa hem aplicat el clcul real que sefectua en les entitats bancries (o que caldria efectuar) per calcular el capital compost, ja que cal tenir en compte els arrodoniments de la moneda corresponent. Per aix hem codificat la funci arrodonir, mitjanant la qual, donat un valor

Estructures de dades dinmiques

16

Recursivitat. Arbres

double i un valor unsigned int, sarrodoneix el double al nombre de decimals que indica lunsigned int. Hem de suposar que ja no tindreu cap problema per comprendre aquesta funci. Posteriorment, cal utilitzar-la en els clculs dels diversos capitals acumulats.

1.2. Recursivitat i piles


Ja coneixem alguns exemples daplicaci de la recursivitat. En general, davant la resoluci informtica dun problema utilitzarem la recursivitat si som capaos dobservar-ne laplicaci en el cas concret. Simplement haurem de trobar el disseny recursiu amb lexistncia de lestat base que assegura el final del problema. Per a banda de tenir la intuci necessria per aplicar-la, s convenient conixer el procs dexecuci que en porta implcit la utilitzaci. I aquest procs es basa en la utilitzaci continuada de piles. Coneixerem ara el funcionament intern de la recursivitat i la possibilitat de simular-lo amb la utilitzaci de piles.

1.2.1. Funcionament intern de la recursivitat


Sabem que quan es t un programa que crida un subprograma, internament sutilitzen piles per guardar lestat de les variables del programa en el moment que es fa la crida. Aix, quan sacaba lexecuci del subprograma, els valors emmagatzemats en la pila es poden recuperar i es pot continuar lexecuci del programa en el punt on va ser interromput. A ms de les variables, sha demmagatzemar ladrea del programa on es va fer la crida, ja que s en aquesta posici on retorna el control del procs. Aix doncs, amb cada crida recursiva es crea una cpia de totes les variables i constants que estiguin vigents i es guarda en la pila. A ms, es guarda una referncia a la instrucci segent a executar. En retornar duna crida recursiva, sagafa la imatge guardada al capdamunt de la pila i es continua lexecuci del subprograma en el punt on shavia quedat en efectuar la crida recursiva. Aquesta acci es repeteix fins que la pila queda buida. Efectuem una simulaci de la recursivitat per a alguns casos. Clcul de factorial(4)
Pas 0 1 2 4 3 n Instrucci que sexecuta factorial (4) 4 * factorial (3) 3 * factorial (2) 4 4,3 Pila Factorial

Estructures de dades dinmiques

17

Recursivitat. Arbres

Pas 3 4 5 6 7 8 9

n 2 1 0

Instrucci que sexecuta 2 * factorial (1) 1 * factorial (0) factorial (0) producte pendent del pas 4 producte pendent del pas 3 producte pendent del pas 2 producte pendent del pas 1

Pila 4,3,2 4,3,2,1 4,3,2,1 4,3,2 4,3 4

Factorial

1 1 (1 * 1) 2 (2 * 1) 6 (3 * 2) 24 (4 * 6)

Clcul de fibonacci(4)
Pas 0 1 2 3 4 5 6 7 8 9 10 11 12 13 2 2 1 1 4 3 2 1 0 n Instrucci que sexecuta fibo(4) fibo(3) + fibo(2) fibo(2) + fibo(1) fibo(1) + fibo(0) fibo(1) fibo(0) pendent del pas 3 suma pendent del pas 3 fibo(1) pendent del pas 2 suma pendent del pas 2 fibo(1) + fibo(0) que s el fibo(2) pendent del pas 1 fibo(1) fibo(0) pendent del pas 8 suma pendent del pas 8 suma pendent del pas 1 fibo(2) fibo(2), fibo(1) fibo(2), fibo(1), fibo(0) fibo(2), fibo(1), fibo(0) fibo(2), fibo(1), 1 fibo(2), fibo(1) fibo(2), 1 fibo(2) 2 2, fibo(0) 2, 1 2 1 0 1 (1 + 0) 3 (2 + 1) 1 0 1 (1 + 0) 1 2 (1 + 1) Pila Fibonacci

Enteneu per qu la versi recursiva Fibonacci s molt ineficient? Fixeu-vos que van quedant un munt de crides pendents dexecutar en la pila. Quan arriba el moment de fer-ne lexecuci, sexecuten. Algunes ja shavien calculat abans, per lordinador no ho pot saber i les torna a executar. Enteneu que lordinador pot quedar penjat a causa de la saturaci de la pila? En aquest cas, la versi recursiva hauria de quedar totalment descartada.

1.2.2. Simulaci de la recursivitat amb piles


No tots els llenguatges de programaci disposen de recursivitat. Daltra banda, la utilitzaci de la recursivitat no s prou eficient. Resulta convenient, per tant, tenir algun procediment que permeti simular la recursivitat.

Estructures de dades dinmiques

18

Recursivitat. Arbres

I com que ja som coneixedors del tipus de dada pila, podem utilitzar-la gestionant nosaltres mateixos la memria disponible. Un subprograma pot tenir variables locals i parmetres (arguments). Quan es fa una crida recursiva al subprograma, els valors actuals de variables i parmetres shan de conservar. Tamb sha de conservar ladrea a la qual ha de tornar el control una vegada executat el subprograma cridat. En realitat, aquest procediment s el que sutilitza sempre que es fa la crida dun subprograma a un altre (encara que no hi hagi recursivitat). El procediment que es proposa per simular la recursivitat dun algorisme que tingui N parmetres i M variables locals consisteix a tenir N+M piles (o una pila de N+M valors per element) on es puguin guardar les imatges corresponents del moment en qu cal fer la crida i refer la recursivitat en un procs iteratiu. Utilitzarem les piles amb les dues operacions ja conegudes:
funci push (var top: ^node, elem: T) retorna natural; /* 0: O.K. - 1: Pila plena */ funci pop (var top: ^node, var elem: T) retorna natural; /* 0: O.K. - 1: Pila buida */

Ara solucionarem el clcul del factorial dun nombre natural simulant la recursivitat.
funci factorial (n: natural) retorna natural s var top: ^natural; r: natural; aux: natural; fivar top = NUL; /* Punter al capdamunt de la pila */ /* El segent mentre equival a anar guardant el valor n de manera que quan es tingui r=factorial(n-1) es pugui recuperar per calcular n*r */ mentre n > 0 fer si push (top, n) != 0 llavors ERROR("Pila plena"); avortar; fisi n = n - 1; fimentre r = 1; /* Soluci per lestat base */ /* El segent mentre equival a tornar de les diferents crides recursives recuperant els valors de la pila i fent els clculs oportuns */ mentre pop (top, aux) == 0 fer r = r * aux; fimentre retorna r; fifunci

En veure-ho daquesta manera ens adonem que ens podem estalviar lemmagatzematge en la pila del valor n, ja que consisteix a anar guardant els diferents valors des de n fins a 1 (de manera descendent), recuperar-los posteriorment dun en un i anar calculant r. En aquest cas tindrem la soluci iterativa coneguda per tothom:
funci factorial (n: natural) retorna natural s var r: natural; aux: natural; fivar r=1; aux=1; mentre aux <= n fer r = r*aux; aux = aux+1; fimentre retorna r; fifunci

Estructures de dades dinmiques

19

Recursivitat. Arbres

1.3. Aplicacions clssiques de recursivitat


Ja ens sn coneguts els tpics exemples senzills dutilitzaci de recursivitat: factorial, Fibonacci i capital compost. Hi ha, per, dos exemples clssics daplicaci de recursivitat. El primer s la resoluci dun problema (torres de Hanoi) en qu es pot apreciar que el disseny recursiu el simplifica increblement en comparaci amb un disseny iteratiu. El segon s el mtode dordenaci rpida (quicksort), al qual sha alludit en moltes ocasions.

1.3.1. El problema de les torres de Hanoi


Les torres de Hanoi s un clssic de la recursivitat, ja que la seva soluci recursiva s molt simple. Es tenen tres torres (T1, T2 i T3) i un conjunt de N discos de diferents dimetres. Cadascun t una perforaci central que li permet lliscar per qualsevol de les torres. Inicialment (figura 1), els N discos estan situats en la torre T1, ordenats per dimetre, de ms gran (sota) a ms petit (dalt). Shan de passar els N discos a la torre T2 (figura 2), on han de quedar en el mateix ordre, utilitzant la torre T3 com a auxiliar i respectant les regles segents: En cada moviment noms pot intervenir un disc; per tant, sempre ser el disc superior el que es pugui moure. No pot quedar en cap moment un disc damunt dun altre que tingui menys dimetre.
Figura 1. Situaci inicial dels N discos en el problema de les Torres de Hanoi

Figura 2. Situaci final dels N discos en el problema de les Torres de Hanoi

Estructures de dades dinmiques

20

Recursivitat. Arbres

Lnica manera de passar el disc inferior de T1 a T2 respectant les regles s:


1) Movent els N-1 discos superiors de T1 a T3, utilitzant la torre T2 com

a auxiliar.
2) Movent el disc inferior de T1 a T2. 3) Movent els N-1 discos existents de T3 a T2, utilitzant la torre T1 com

a auxiliar. Observeu que si els moviments dels apartats 1 i 3 respecten les regles (considerant noms els N-1 discos que mouen), llavors la totalitat dels moviments 1-2-3 tamb les respecten, ja que els discos que es mouen sempre sn de menys dimetre que els que ja estan situats en les torres. Per tant, sha aconseguit redefinir el problema de grau N en termes de grau N-1. Ens estem apropant a un estat base (un nic disc), on el moviment entre la torre font i la torre destinaci s immediat, s a dir, sense lajut de la torre auxiliar.
acci hanoi (N, FONT, DEST, AUXILIAR: natural) s si N==1 llavors escriure ("Posar disc de ",FONT," a ", DEST); /* Estat bsic */ sin hanoi (N-1, FONT, AUXILIAR, DEST); escriure ("Posar disc de ",FONT," a ", DEST); hanoi (N-1, AUXILIAR, DEST, FONT); fisi fiacci

Presentem, a continuaci, una versi no recursiva utilitzant piles per simular la recursi.
tipus sit_hanoi = tuple N, TF, TD, TA: natural; fituple /* El tipus sit_hanoi permet emmagatzemar una situaci concreta del problema */ node = tuple inf: sit_hanoi; seg: ^node; fituple /* El tipus node correspon al node per a una pila implementada com a llista */ fitipus acci hanoi (N, FONT, DEST, AUXILIAR: natural) s var top: ^node; sit: sit_hanoi; aux, crida: natural; fivar crida=1; mentre N>1 i crida==1 fer /* El segent mentre posa a la pila totes les primeres crides */ mentre N > 1 fer sit.N=N; sit.TF=FONT; sit.TD=DEST; sit.TA=AUXILIAR; si push (top, sit)!=0 llavors ERROR("Pila plena"); avortar; fisi N=N-1; aux=DEST; DEST=AUXILIAR; AUXILIAR=aux; fimentre escriure ("Posar disc de ",FONT," a ", DEST); crida=2; si pop(p,sit)==0 llavors

Estructures de dades dinmiques

21

Recursivitat. Arbres

N=sit.N; FONT=sit.TF; DEST=sit.TD; AUXILIAR=sit.TA; escriure ("Posar disc de ",FONT," a ", DEST); /* Simularem la 2a crida a hanoi corresponent a la que acabem de tractar */ N=N-1; aux=FONT; FONT=AUXILIAR; AUXILIAR=aux; crida=1; fisi fimentre fiacci

Una simple ullada entre els algorismes recursiu i iteratiu permet concloure que la soluci recursiva del problema de les torres de Hanoi s molt ms compacta i ms fcil dentendre que la soluci no recursiva. De tota manera, s important disposar dun formalisme per traduir els processos recursius en processos no recursius, ja que alguns llenguatges no disposen de recursivitat i en certs problemes el cost de la recursivitat s molt significatiu.

1.3.2. El mtode dordenaci rpida


El mtode dordenaci rpida, batejat daquesta manera pel seu dissenyador (Hoare) i tamb conegut com a mtode dordenaci per partici, s un mtode dordenaci de taules molt millor que els mtodes de selecci, inserci i intercanvi i molts llenguatges el faciliten en les seves biblioteques de funcions. Aquest mtode dordenaci t un disseny recursiu molt fcil, a partir del qual i utilitzant piles es pot aconseguir una versi iterativa. Fonamentalment, lalgorisme consisteix en els passos segents:
1) Sagafa un element X duna posici qualsevol de la taula. 2) Sintenta collocar X en la posici correcta de la taula, de tal manera

que tots els elements que es trobin a la seva esquerra siguin ms petits o iguals que X i que tots els elements que es trobin a la seva dreta siguin ms grans o iguals que X. Per aconseguir-ho, probablement caldr moure diversos elements de la taula.
3) Es repeteixen els passos anteriors, per ara per als conjunts de dades que

es troben a lesquerra i a la dreta de la posici correcta de X dins la taula.


4) El procs acaba quan tots els elements es troben en la posici correcta

dins la taula. Del que sha exposat es pot deduir que aquest algorisme s fcilment programable si sutilitza la recursi. Vegem-ne la versi recursiva. Seleccionarem un element X qualsevol. Considerarem, per exemple, t[0]. Comencem a recrrer la taula de dreta a esquerra comparant si els ele-

Estructures de dades dinmiques

22

Recursivitat. Arbres

ments sn ms grans o iguals que X. Si un element no compleix la condici, sintercanvia amb X. Sinicia novament el recorregut a partir don ara est collocat X, per desquerra a dreta, comparant si els elements sn ms petits o iguals que X. Si un element no compleix la condici, sintercanvia amb X. Es repeteixen els passos anteriors (a partir don ara est collocat X) fins que lelement X troba la seva posici correcta dins la taula. Per ordenar una taula t[MAX] de T, caldria executar quicksort (0,MAX-1), on:
acci quicksort (inici, final: natural) s var esq, dre, pos: natural; situat: boole; aux: T; fivar esq = inici; dre = final; pos = inici; situat = fals; mentre no situat fer situat = cert; mentre t[dre].V >= t[pos].V i dre != pos fer dre = dre -1; fimentre si dre != pos llavors aux = t[pos]; t[pos] = t[dre]; t[dre] = aux; pos = dre; mentre t[esq].V <= t[pos].V i esq != pos fer esq = esq + 1; fimentre si esq != pos llavors situat = fals; aux = t[pos]; t[pos] = t[esq]; t[esq] = aux; pos = esq; fisi fisi fimentre /* En aquest moment l'element que es troba a la posici "pos" t tots els elements de la seva esquerra menors o iguals que ell i tots els elements de la seva dreta majors o iguals que ell. */ si inici < pos - 1 llavors quicksort (inici, pos - 1); fisi si final > pos + 1 llavors quicksort (pos + 1, final); fisi fiacci

Clculs matemtics asseguren que aquest algorisme s dordre (n * log2 n.). Encara que lalgorisme del quicksort en versi recursiva sigui clar, s possible augmentar-ne leficincia eliminant les crides recursives. La recursi s un instrument molt poders, per leficincia dexecuci s un factor molt important en un procs dordenaci que cal administrar molt b. Aquestes crides recursives es poden substituir utilitzant piles, cosa que dna lloc a la versi iterativa. Us atreviu a dissenyar-ne la versi iterativa?

Estructures de dades dinmiques

23

Recursivitat. Arbres

2. Arbres

Un arbre s una estructura jerrquica aplicada sobre una collecci delements, anomenats nodes, un dels quals s conegut com a arrel. Entre els diferents nodes es crea una relaci o parentesc que dna lloc a termes com pare, fill, germ...

Un arbre de tipus T s una estructura homognia fruit de la concatenaci dun element de tipus T, anomenat arrel, amb un nombre finit darbres disjunts (que no tenen cap element en com), anomenats subarbres. Un cas particular darbre pot ser lestructura buida.

Observeu que la definici darbre ha estat recursiva, ja que per definir un arbre sha utilitzat el mateix concepte darbre. Lltima part de la definici (un arbre pot ser buit) constitueix lestat base de la definici recursiva que nassegura la finitud. Els arbres tenen una gran varietat daplicacions: representaci de frmules matemtiques, representaci darbres genealgics, anlisi de circuits elctrics, esquemes de continguts... Per, sobretot, sutilitzen en la gesti dels ndexs en els arxius seqencials indexats. Les caracterstiques i propietats dels arbres en general sn: !
a) Tot arbre no buit t un nic node arrel. b) Un node X s descendent directe dun node Y, si el node X s apuntat

pel node Y. En aquest cas sacostuma a utilitzar lexpressi X s fill de Y.


c) Un node X s ascendent directe dun node Y, si el node X apunta el

node Y. En aquest cas sacostuma a utilitzar lexpressi X s pare de Y.


d) Tots els nodes que sn fills dun mateix node sanomenen germans. e) Tot node sense fills es coneix com a node terminal o fulla. f) Tot node que no s arrel ni fulla es coneix com a node interior. g) El grau dun node es defineix com el nombre de fills del node, i el

grau dun arbre es defineix com el grau ms gran de tots els nodes de larbre.
h) El nivell dun node es defineix com el nombre de generacions entre

larrel i aquest node. Per definici, el node arrel s de nivell 1.


i) Laltura dun arbre es defineix com el nivell ms gran de tots els no-

des de larbre. Vegem aquestes propietats a partir de larbre de la figura 3.

Estructures de dades dinmiques

24

Recursivitat. Arbres

Figura 3. Exemple darbre genric

A s larrel. D, I, J, F, K i H sn nodes terminals fulles. B, C, E i G sn nodes interiors. E s pare de I i J, i aquests sn fills de E. G s pare de K, i aquest s fill de G. B s pare de D i E, i aquests sn fills de B. C s pare de F, G i H, i aquests sn fills de C. A s pare de B i C, i aquests sn fills de A. El grau de B s 2. El grau de larbre s 3, ja que C t grau 3 i s el grau ms gran. Laltura de larbre s 4, ja que s el nivell ms alt (per a les fulles I, J i K). A partir de la figura 3 i de la nostra experincia prvia, intum que informatitzar una estructura daquest estil implicar la utilitzaci de nodes en els quals emmagatzemarem les dades (A, B, C, D...) i els punters, tants com fills tingui aquell node. No informatitzarem, per, qualsevol tipus darbre, sin que anirem filtrant els tipus darbres interessants per al tractament informtic.

2.1. Arbres binaris


Els primers arbres que tenen una certa importncia i que ens interessa tractar informticament sn els arbres binaris.

Un arbre ordenat s un arbre que t branques dels nodes ordenades o, millor dit, es poden enumerar. Un arbre binari s un arbre ordenat de grau 2. Per tant, cada node pot tenir, com a mxim, dos fills. Quan sordena un arbre binari sempre es pot distingir entre el subarbre esquerre (arbre que t com a arrel el fill esquerre) i el subarbre dret (arbre que t com a arrel el fill dret). Un arbre binari s complet si tots els seus nodes que no siguin fulles tenen dos fills i totes les fulles es troben al mateix nivell.

Estructures de dades dinmiques

25

Recursivitat. Arbres

En un arbre complet es verificar que: Nombre de nodes = 2h 1 (h s laltura de larbre) La importncia dels arbres binaris radica en el seu dinamisme, la seva programaci senzilla, la no-linealitat i el fet que existeixen algorismes mitjanant els quals qualsevol estructura en arbre pot ser reduda a un arbre binari i, per tant, tenir el tractament informtic corresponent a un arbre binari.

Conversi a arbre binari No sinclou en els objectius daquest crdit la mecnica de transformaci de qualsevol arbre no binari en binari. En els llibres de la bibliografia especfica corresponents a aquest aspecte en trobareu les explicacions.

2.1.1. Implementaci darbres binaris


De la mateixa manera que en el tipus de dada pila i cua hi ha la possibilitat de fer una implementaci basada en taules, encara que s millor que es basi en llistes, en els arbres binaris ens passa una cosa semblant. s possible una implementaci basada en taules, per no s gens lgica. Aix doncs, la implementaci normal darbres passa per la gesti dinmica de la memria.

Un node dun arbre binari consta de tres parts: Una part que cont la informaci que es vol emmagatzemar en larbre. Una part que cont el lligam cap al fill esquerre. Contindr el valor NUL si no t fill esquerre. Una part que cont el lligam cap al fill dret. Contindr el valor
NUL si no t fill dret.

Per tant, si volem gestionar un arbre per emmagatzemar-hi dades dun cert tipus T, caldr tenir en compte la definici segent:
tipus node = tuple inf : T; /* cont la informaci */ esq, dre : ^node; /* punters als dos fills */ fituple

Figura 4. Utilitzaci de punters en nodes dels arbres binaris

La figura 4 ens ho mostra grficament. Per tant s clar el segent: un arbre binari s una estructura ramificada de nodes per a la qual hi ha dhaver un punter inicial; les fulles tenen el valor NUL (N) en els dos punters; un arbre buit t en el punter inicial el valor NUL.

Estructures de dades dinmiques

26

Recursivitat. Arbres

2.1.2. Algorismes de tractament en arbres binaris


A continuaci analitzem els principals algorismes de tractament en arbres binaris: creaci darbre buit, crrega i recorreguts. Podrem estudiar altres algorismes, per sobretot ens interessen els recorreguts que es poden aplicar. Per poder-los comprovar necessitem tenir algun arbre amb informaci introduda. Per aix tamb considerem un algorisme de crrega dun arbre binari a partir dun conjunt de valors inicial.
1) Creaci darbre buit
var arbre: ^node; arbre = NUL;

Evidentment, crear larbre no consisteix a fer res ms que crear el punter inicial. Cal tenir, per, la precauci dinicialitzar-lo amb el valor NUL.
2) Crrega dun arbre binari

No ens complicarem la vida. Simplement volem disposar dalgun mtode per carregar en memria un arbre binari que tinguem en paper per tal de poder comprovar posteriorment els algorismes de recorregut.
acci crrega (var arbre:^node) retorna natural s /* Argument arbre : Punter per apuntar larrel de larbre */ var element: T; sn: carcter; fivar si arbre != NUL llavors esborrar (arbre); fisi escriure ("Introdueixi lelement a inserir:"); llegir (element); assignar_memria (arbre); si arbre == NUL llavors escriure ("Larbre no pot crixer ms."); sin arbre^.inf = element; arbre^.esq = NUL; arbre^.dre = NUL; pregunta ("T fill per lesquerra?", sn, "SN"); si sn == 'S' llavors crrega (arbre^.esq); fisi /* crida recursiva */ escriure ("Situs en el node que t com a element", element); /* Pregunta perqu lusuari se situ en cas dhaver-se executat la crida recursiva i haver deixat "penjat" el node dret daquest element */ fisi pregunta ("T fill per la dreta?", sn, "SN"); si sn == 'S' llavors crrega (arbre^.dre); fisi /* crida recursiva */ fisi fiacci

3) Algorismes de recorregut

Els algorismes de recorregut sn els ms importants en el tractament darbres binaris en general, ja que recrrer un arbre significa visitar-ne els nodes sistemticament, de manera que tots siguin visitats una nica vegada.

Estructures de dades dinmiques

27

Recursivitat. Arbres

Cal entendre per visita el fet de tractar la informaci que cont. No es considera visita el fet de passar pel node per consultar els punters esq i dre i aix poder passar als nodes fills corresponents. Hi ha tres maneres de fer el recorregut darbres binaris. Totes sn de naturalesa recursiva: preordre, inordre i postordre.

a) El recorregut en preordre consisteix a visitar, en primer lloc,

larrel, en segon lloc, el subarbre esquerre en preordre i, en tercer lloc, el subarbre dret en preordre.
b) El recorregut en inordre consisteix a visitar, en primer lloc, el sub-

arbre esquerre en inordre, en segon lloc, larrel i, en tercer lloc, el subarbre dret en inordre.
c) El recorregut en postordre consisteix a visitar, en primer lloc, el

subarbre esquerre en postordre, en segon lloc, el subarbre dret en postordre i, en tercer lloc, larrel.

Observeu que les tres definicions sn recursives i, per tant, la codificaci dels tres recorreguts ser recursiva.
acci preordre (arbre:^node) s si arbre != NUL llavors tractament (arbre^.inf); preordre (arbre^.esq); preordre (arbre^.dre); fisi fiacci acci inordre (arbre:^node) s si arbre != NUL llavors inordre (arbre^.esq); tractament (arbre^.inf); inordre (arbre^.dre); fisi fiacci acci postordre (arbre:^node) s si arbre != NUL llavors postordre (arbre^.esq); postordre (arbre^.dre); tractament (arbre^.inf); fisi fiacci

2.2. Arbres binaris de recerca


Els arbres binaris sn molt interessants, per encara ho serien ms si disposssim de mtodes de recerca eficients. Com cercareu un element en

Estructures de dades dinmiques

28

Recursivitat. Arbres

un arbre binari genric? Noms hi ha una manera de fer-ho: considerar un dels tres recorreguts possibles (preordre, inordre i postordre) i anar cercant fins a trobar lelement o fins a arribar al final del recorregut sense xit. Gens eficient! Aquest algorisme s tan ineficient com ho s la recerca seqencial en taules. Recordeu com podem millorar el cost lineal de la recerca seqencial? Ho podem aconseguir en les taules ordenades, ja que llavors es pot aplicar la recerca dicotmica. En el tipus de dada arbre succeeix una cosa semblant i per aquest motiu interessa treballar amb arbres binaris de recerca.

Un arbre binari de recerca s un arbre binari tal que: tots els valors emmagatzemats en el subarbre esquerre de qualsevol node T han de ser ms petits o iguals que el valor emmagatzemat en el node T; tots els valors emmagatzemats en el subarbre dret de qualsevol node T han de ser ms grans que el valor emmagatzemat en el node T.

Intuu per on anir la recerca dun determinat element? Donat un node, si lelement cercat t un valor ms petit que el valor emmagatzemat en el node, continuarem la recerca pel subarbre esquerre, i si el seu valor s ms gran, seguirem la recerca pel subarbre dret. Evidentment, si el valor coincideix amb el valor del node, aturarem la recerca amb un resultat positiu. Fixeu-vos que s una recerca dicotmica en arbres, ja que en cada node obviem un dels dos subarbres mitjanant el procs de recerca. Aquests arbres no solament tenen importncia grcies al seu algorisme de recerca, sin que a ms permeten realitzar de manera eficient les operacions dinserci i eliminaci de manera que larbre mantingui sempre la categoria darbre de recerca.
Figura 5. Arbre binari de recerca de valors enters

Comparaci amb altres tipus de dades Observeu que en les taules ordenades la recerca s eficient, per mantenir-la ordenada s costs. En les llistes ordenades sn costosos el manteniment i la recerca.

Estructures de dades dinmiques

29

Recursivitat. Arbres

La figura 5 ens mostra un arbre binari de recerca. Observeu que un recorregut en inordre provoca una classificaci ascendent de tots els seus nodes: 10 - 20 - 30 - 35 - 40 - 50 - 55 - 60 - 62 - 70 - 80 Vegem els algorismes de recerca, inserci i esborrament en arbres binaris de recerca, suposant que no hi ha elements repetits (cas ms freqent).

2.2.1. Algorisme de recerca


Lalgorisme de recerca consisteix en el fet que en cada node pel qual es passa es produeixi una dicotomia.
funci recerca (arbre:^node, var elem:T, ref: T*) retorna natural s /* Arguments: arbre: Punter a larrel de larbre elem: Variable on sha de recollir lelement cercat ref: Dada que identifica lelement a cercar Retorna: 0 : Recerca efectuada amb xit 1 : Element cercat no trobat */ var res: natural; fivar /* per emmagatzemar el resultat a retornar */ si arbre == NUL llavors retorna 1; fisi opci cas s_menor (arbre^.inf, ref): res = recerca (arbre^.dre, elem, ref); cas s_major (arbre^.inf, ref): res = recerca (arbre^.esq, elem, ref); altrament: elem = arbre^.inf; res = 0; fiopci retorna res; fifunci funci s_menor (element: T, referncia: T*) retorna boole s /* Codi que comprovi si la part T* delement s ms petita que referncia */ fifunci funci s_major (element: T, referncia: T*) retorna boole s /* Codi que comprovi si la part T* delement s ms gran que referncia */ fifunci

Observeu el carcter recursiu de lalgorisme.

2.2.2. Algorisme dinserci


Lalgorisme dinserci s molt semblant al de recerca. Donat un element que volem inserir de manera ordenada en un arbre, si estem situats en un node i lelement s ms gran (segons el criteri dordenaci) que el valor emmagatzemat en el node, caldr inserir lelement en el subarbre dret (crida recursiva). Si, al contrari, lelement s ms petit que el valor emmagatzemat en el node, caldr inserir lelement en el subarbre esquerre (crida recursiva).

Estructures de dades dinmiques

30

Recursivitat. Arbres

Observeu que es tracta dun procs recursiu que finalitza quan es dna alguna de les dues situacions segents: Lelement coincideix amb el valor emmagatzemat en el node arrel de larbre actual, fet que indica que lelement ja existia en larbre. Larbre actual s buit, fet que indica que som en el subarbre on cal inserir el valor.
funci inserir (var arbre:^node, elem:T) retorna natural s /* Arguments: arbre: Punter a larrel de larbre elem: Dada a inserir Retorna: 0 : Inserci efectuada amb xit 1 : Error per manca de memria 2 : Ja existeix un element amb el mateix identificador */ var res: natural; fivar /* per emmagatzemar el resultat a retornar */ si arbre == NUL llavors assignar_memria (arbre); si arbre == NUL llavors retorna 1: fisi arbre^.esq = NUL; arbre^.dre = NUL; arbre^.inf = elem; retorna 0; sin opci cas s_menor* (arbre^.inf, elem): res = inserir (arbre^.dre, elem); cas s_major* (arbre^.inf, elem): res = inserir (arbre^.esq, elem; altrament: res = 2; fiopci retorna res; fisi fifunci funci s_menor* (ele1: T, ele2: T) retorna boole s /* Codi que comprovi si la part T* dele1 s ms petita que la dele2 */ fifunci funci s_major* (ele1: T, ele2: T) retorna boole s /* Codi que comprovi si la part T* dele1 s ms gran que la dele2 */ fifunci

2.2.3. Algorisme deliminaci


Lalgorisme desborrament s una mica ms complicat que lalgorisme dinserci. Evidentment, per poder esborrar un element, primer cal cercar-lo. Una vegada trobat lelement, cal aplicar el mtode basat en els punts segents: Si lelement que sha desborrar es troba en una fulla, simplement selimina. Si lelement que sha desborrar es troba en un node que t un nic fill, el node que cont el valor a eliminar se substitueix pel node fill.

Estructures de dades dinmiques

31

Recursivitat. Arbres

Si lelement que sha desborrar es troba en un node que t dos nodes fill, el node que cont el valor que sha deliminar se substitueix adequadament pel node que s ms a la dreta del subarbre esquerre o pel node que s ms a lesquerra del subarbre dret. Comprovarem el funcionament dels passos anteriors. Suposem que volem eliminar el valor 10 de larbre de la figura 6.
Figura 6. Arbre binari de recerca on cal eliminar el valor 10 Figura 7. Arbre binari de recerca una vegada eliminat el valor 10

En efectuar la recerca el trobem en una fulla. En aquest cas, el node selimina i observem que larbre obtingut (figura 7) continua essent de recerca. Suposem que volem eliminar el valor 40 en larbre de la figura 7. En efectuar la recerca, el trobem en un node interior, el qual nicament t un fill. Segons les regles convingudes, se substitueix pel node fill i observem que larbre obtingut (figura 8) continua essent de recerca.
Figura 8. Arbre binari de recerca de la figura 7 una vegada eliminat el valor 40

Suposem que volem eliminar el valor 60. Desprs de cercar-lo el trobem en un node interior que t dos fills. Segons les regles convingudes, cal substituir-lo pel node de ms a lesquerra del subarbre dret (node que cont el valor 62, i sobt larbre de la figura 9) o pel node de ms a la dreta del subarbre esquerre (node que cont el valor 55, i sobt larbre de la figura 10).

Estructures de dades dinmiques

32

Recursivitat. Arbres

Figura 9. Arbre binari de recerca de la figura 8 una vegada eliminat el valor 60 substituint-lo pel node de ms a l'esquerra del subarbre dret

Figura 10. Arbre binari de recerca de la figura 8 una vegada eliminat el valor 60 substituint-lo pel node ms a la dreta del subarbre esquerre

Observem que tant en un cas (procs que obt larbre de la figura 9) com en laltre (procs que obt larbre de la figura 10), els nodes escollits per substituir el node que contenia el valor 60 (62 i 55 de la figura 8) no tenien cap fill. s clar que el node que contenia el valor 62 podria haver tingut fills per la dreta (i continuaria essent el node de ms a lesquerra del subarbre dret figura 8), de la mateixa manera que el node que contenia el valor 55 podria haver tingut fills per lesquerra (i continuaria essent el node de ms a la dreta del subarbre esquerre figura 8). Evidentment, els possibles subarbres fill dels nodes que contenen els valors 62 i 55 no poden desaparixer i, per tant: En la figura 9, el possible subarbre dret del node que contenia el valor 62 en la figura 8 hauria dhaver passat a ser subarbre esquerre del node que cont el valor 70 (o mantenir-se com a subarbre dret del node que cont el valor 62 si el node eliminat no tenia subarbre dret). En la figura 10, el possible subarbre esquerre del node que contenia el valor 55 en la figura 8 hauria dhaver continuat essent el subarbre esquerre del node que cont el valor 55 (o passar a ser el subarbre dret del subarbre esquerre del node eliminat si hagus existit). Lestructura de larbre resultant s diferent si sexecuta luna o laltra opci, per en tots dos casos continua tractant-se dun arbre binari de recerca. Quin resultat final us sembla ms adequat? s ms adequat el resultat final de la figura 9, ja que deixa un arbre ms ben repartit. Aix no vol dir que shagi daplicar sempre lelecci que ha possibilitat aquest resultat final, ja que aquest depn de la situaci de partida. Aix doncs, ja estem en condicions de presentar el pseudocodi de la funci esborrar en un arbre binari de recerca.
funci esborrar(var arbre:^node, var elem:T, ref:T*) retorna natural s /* Arguments: arbre: Punter a larrel de larbre elem: Variable on sha de recollir lelement a esborrar ref: Dada de tipus T* que identifica lelement a esborrar Retorna: 0 : Esborrament efectuat amb xit 1 : Error ja que no existeix un tal element identificat per ref */ var res: natural; /* per emmagatzemar el resultat a retornar */

Estructures de dades dinmiques

33

Recursivitat. Arbres

aux, auxbis: ^node; fivar opci cas arbre == NUL: res = 1; cas s_major(arbre^.inf, ref): res = esborrar (arbre^.esq, elem, ref); cas s_menor(arbre^.inf, ref): res = esborrar (arbre^.dre, elem, ref); altrament: /* lelement a esborrar est en el node apuntat per arbre */ aux = arbre; res = 0; element = arbre^.inf; opci cas aux^.esq == NUL i aux^.dre == NUL: /* s una fulla */ arbre = NUL; alliberar_memria (aux); cas aux^.esq == NUL i aux^.dre != NUL: /* noms fill dret */ arbre = aux^.dre; alliberar_memria (aux); cas aux^.esq != NUL i aux^.dre == NUL: /* noms fill esquerre */ arbre = aux^.esq; alliberar_memria (aux); altrament: /* dos fills */ /* substitum pel node ms a la dreta del subarbre de lesquerra */ auxbis = aux^.esq; mentre auxbis^.dre != NUL fer aux = auxbis; auxbis = auxbis^.dre; fimentre si aux == arbre llavors aux^.esq = auxbis^.esq; sin aux^.dre = auxbis^.esq fisi arbre^.inf = auxbis^.inf; alliberar_memria (auxbis); fiopci fiopci retorna res; fifunci

Observeu el carcter recursiu de lalgorisme. Tamb s important remarcar que en cas de substituci per lelement que es troba ms a la dreta del subarbre esquerre no se substitueix node per node, sin lelement que sha desborrar per lelement del node ms a la dreta del subarbre esquerre.

2.3. Arbres balancejats


Els arbres binaris de recerca permeten realitzar de manera eficient les operacions de recerca, eliminaci i inserci, per tenen un defecte: el creixement i/o decreixement descontrolats, que provoquen que no quedin ben repartits. Observeu els exemples de les figures 11 i 12.
Figura 11. Arbre binari de recerca desprs de la seqncia dinsercions dels valors 22, 33, 44 i 55 Figura 12. Arbre binari de recerca desprs de la seqncia dinsercions dels valors 80, 70, 60, 65 i 62

Estructures de dades dinmiques

34

Recursivitat. Arbres

Oi que no estan ben repartits? Aix provoca que la recerca de valors no aprofiti leficincia que el seu disseny aporta en ls del procs dicotmic. Per solucionar aquesta situaci apareix el concepte darbre balancejat.

Un arbre balancejat s un arbre binari de recerca tal que, per a qualsevol node, les altures dels subarbres dret i esquerre no poden diferir en ms duna unitat.

La idea central s la darreglar larbre desprs de les insercions i les eliminacions de manera que es mantingui lequilibri. Per poder mantenir aquest equilibri, cal tenir informaci referent a lequilibri de cada node de larbre. Aix provoca laparici del concepte factor dequilibri dun node.

El factor dequilibri dun node s el resultat de la resta de laltura del subarbre dret menys laltura del subarbre esquerre.

Perqu larbre sigui balancejat cal mantenir en tots els nodes el factor dequilibri en els valors 1, 0 o 1. Aquest factor semmagatzema en cada node i es recalcula, de manera adequada, en cada inserci i eliminaci. En cas de prdua dequilibri en algun node es reestructura larbre per mantenir-lo com a arbre balancejat. De lapartat anterior es dedueix que la implementaci dun node per a arbre balancejat necessita un nou apartat:
tipus node = tuple inf : T; /* cont la informaci */ esq, dre : ^node; /* punters als dos fills */ fe : enter; fituple

El nou camp fe hauria de valer sempre -1, 0 o 1, per en determinats moments pot valer -2 o 2, a causa de la prdua momentnia de lequilibri. Ara presentem el funcionament dels algorismes dinserci i esborrament per als arbres balancejats. No arribarem a escriuren el pseudocodi, ho deixem per a vosaltres. Us hi animeu? Lalgorisme de recerca no canvia respecte als arbres binaris de recerca.

2.3.1. Algorisme dinserci


En primer lloc, sinsereix lelement, segons lalgorisme per a arbres binaris de recerca (sempre sinsereix en una fulla), calculant-ne el factor

Estructures de dades dinmiques

35

Recursivitat. Arbres

dequilibri (FE, a partir dara) que, evidentment, ser zero. Cal tornar enrere pel cam de recerca daquest nou node i recalcular els FE dels nodes pels quals es passa, fins a trobar un node que perdi lequilibri o fins a arribar a larrel sense que perdi lequilibri. Si es localitza un node amb prdua dequilibri, cal refer larbre en aquest node i no cal continuar recalculant lFE per a la resta de nodes, ja que aquest mtode ens assegura que no haur variat. Per refer larbre cal aplicar el mtode adequat segons quina situaci es produeixi, que pot ser una de les quatre que mostra la figura 13.
Figura 13. Mtodes a aplicar per refer larbre i recuperar el factor dequilibri

Estructures de dades dinmiques

36

Recursivitat. Arbres

No hi ha res millor que un exemple per entendre les diferents situacions que es poden presentar. Volem construir un arbre balancejat a partir de la seqncia de valors 55 - 40 - 13 - 60 - 72 - 58 - 29. La figura 14 ens mostra els diferents passos que hem de seguir.
Figura 14. Creaci darbre balancejat provocat per les insercions 55, 40, 13, 60, 72, 58 i 29

2.3.2. Algorisme deliminaci


Lalgorisme deliminaci consisteix en lalgorisme desborrament en arbres binaris de recerca mantenint lequilibri de larbre: una vegada eliminat un

Estructures de dades dinmiques

37

Recursivitat. Arbres

node, es retorna pel cam de recerca daquest nou node fins a larrel, recalculant els FE dels nodes pels quals es passa fins a arribar a larrel. Cal reestructurar larbre en aquest node en el qual sha perdut lequilibri. A diferncia de lalgorisme dinserci, cal comprovar lFE fins a larrel, ja que hi pot haver diversos nodes en els quals es perdi lequilibri. La figura 15 ens mostra diverses situacions que es presenten en eliminar valors en un arbre balancejat.
Figura 15. Processos deliminaci de valors en arbres balancejats

Estructures de dades dinmiques

38

Recursivitat. Arbres

Lanlisi matemtica dels algorismes dinserci i eliminaci demostra que tots sn dordre logartmic. Daltra banda, diverses anlisis mostren que sn ms freqents les rotacions en les operacions dinserci que en les deliminaci.

2.4. Arbres multicam


Les variants darbres binaris vistes fins ara sn desenvolupades per funcionar en la memria principal. Hi ha aplicacions, per, que gestionen grans volums dinformaci que no caben en la memria principal i que necessiten emmagatzemar-se en arxius perqu puguin ser localitzats de forma eficient. Daquesta manera, apareixen les tcniques dindexaci darxius, les quals es basen en arbres (un per a cada ndex) que emmagatzemen la clau i ladrea on es troben les dades (arxius de dades). s a dir, la part dinformaci dun node s compon de la clau i ladrea. A part, hi ha els punters (dos en tractarse darxius binaris) i lFE (si sn arbres balancejats). Cada node semmagatzema en un registre de larxiu ndex. Suposem que indexem un arxiu d1.000.000 de registres amb un arbre binari balancejat. Necessitarem, per cercar un element, uns 20 accessos a disc (logaritme en base 2 d1.000.000), ja que cada accs a un nou node implica laccs a un nou registre de larxiu ndex. Ara b, si larbre estigus organitzat en pgines, cadascuna de les quals contingus 100 elements com a mnim, lordre daccessos baixaria espectacularment a logaritme en base 100 d1.000.000, s a dir, 3 accessos a disc. Per aquest motiu entren en acci els arbres multicam.

Un arbre multicam s un arbre balancejat que en un node cont diversos valors i diversos punters a altres nodes. Si considerem que cont N valors, haur de contenir N + 1 punters.

Grficament, un node amb 4 elements tindria laparena segent:

Les caselles Inf1, Inf2, Inf3 i Inf4 contindrien els valors i les caselles P1, P2, P3, P4 i P5 contindrien els punters a nous nodes. Des dun node es pot tenir accs a cinc nodes diferents, s a dir, disposem de cinc camins a seguir. Es veu clar ara don prov el nom darbres multicam? Hi ha diferents tipus darbres multicam. En presentarem dos de molt coneguts: els arbres B i els arbres B+.

Estructures de dades dinmiques

39

Recursivitat. Arbres

2.4.1. Arbres B
Els arbres B sn una generalitzaci dels arbres balancejats per aconseguir arbres multicam. Vegem-ne la definici.

Autors dels arbres B El disseny dels arbres B s obra de Bayer i McCreight el 1970. El seu nom prov de Bayer? s una incgnita.

Un arbre B dordre d s un arbre que t les caracterstiques segents: Cada node, excepte larrel, cont entre d i 2d elements. Cada node, excepte larrel i les fulles, t entre d + 1 i 2d + 1 fills. El node arrel o no t fills (perqu s una fulla) o en t dos com a mnim. Totes les fulles es troben en un mateix nivell (balancejat perfecte). Els elements emmagatzemats en un node estan ordenats de ms petit a ms gran (desquerra a dreta). Cada element dun node que no s fulla t dos fills. Tots els elements del seu subarbre esquerre sn ms petits que ell i tots els elements del seu subarbre dret sn ms grans que ell.

Per poder treballar amb arbres B, cal que en cada node hi hagi informaci referent al nombre de dades que emmagatzema en un moment donat. Hi ha diferents maneres de poder tenir aquesta informaci: Mitjanant una dada afegida que permet obtenir aquesta informaci, de manera que lestructura dun node seria semblant a aquesta:

Es pot observar que tenim 2d + 1 punters (P1, P2, P3,..., P2d + 1) i 2d valors (Inf1, Inf2,..., Inf2d). La marca X correspondria a la quantitat de valors que en un determinat moment cont el node, que exceptuant larrel ha de ser sempre entre d i 2d. Sense una dada afegida i calculant el valor corresponent com a quantitat, disminuda en una unitat, de punters amb valor no nul. Aquest funcionament s possible en els nodes interiors, per no en les fulles, ja que en aquestes tot punter s nul. De fet, podrem considerar estructures de nodes diferents per als nodes interiors i per a les fulles. En les fulles no fan falta els punters, per en canvi s que cal saber quants valors estan emmagatzemant en un moment donat.

Estructures de dades dinmiques

40

Recursivitat. Arbres

Algorisme de recerca
Lalgorisme de recerca per a arbres multicam no s altra cosa que una generalitzaci de lalgorisme de recerca per a arbres binaris. Vegem-ne el pseudocodi.
funci recerca (arbre:^node, var elem:T, ref: T*) retorna natural s /* Arguments: arbre: Punter a larrel de larbre elem: Variable on sha de recollir lelement cercat ref: Dada que identifica lelement a cercar Retorna: 0 : Recerca efectuada amb xit 1 : Element cercat no trobat */ var res: natural; fivar /* per emmagatzemar el resultat a retornar */ si arbre == NUL llavors retorna 1; fisi opci cas s_incls_en_el_node (arbre, ref, elem): res = 0; cas s_major (arbre^.inf1, ref): res = recerca (arbre^.P1, elem, ref); cas s_menor (arbre^.inf1, ref): res = recerca (arbre^.P2, elem, ref); cas s_menor (arbre^.inf2, ref): res = recerca (arbre^.P3, elem, ref); ... cas s_menor (arbre^.inf2d, ref): res = recerca (arbre^.P2d+1, elem, ref); fiopci retorna res; fifunci funci s_incls_en_el_node (p: ^node, ref: T*, var elem: T) retorna boole s /* Codi que comprovi si en el node apuntat per p hi ha un element amb part T* igual a ref. En aquest cas retorna cert i copia lelement en el parmetre elem. En cas contrari, retorna fals. */ fifunci
Figura 16. Exemple darbre B dordre 2

La figura 16 ens mostra la representaci grfica dun arbre B dordre 2. Primer de tot, observem que no representem les caselles corresponents a punters en cap node. Cada fletxa parteix duna casella punter i apunta el node corresponent. Daltra banda, hem de tenir clar que cada node cont fins a 4 caselles informaci, per noms representem les caselles que contenen valor. Per tant, veiem nodes amb 1, 2, 3 o 4 valors. Tamb observem que per poder fer el seguiment corresponent de lalgorisme de recerca hem numerat els nodes com a Node0, Node1,..., Node9. En la realitat, els nodes no estan numerats.

Estructures de dades dinmiques

41

Recursivitat. Arbres

1) Recerca de lelement 77

Visitem larrel (node 0) i, en comparar el valor cercat 77 amb el valor 56 del node, com que 77 s ms gran que 56, seguim pel punter (fletxa) de la dreta del valor 56, la qual ens porta al node 2. Visitem el node 2, on trobem el valor cercat.
2) Recerca de lelement 79

Visitem larrel (node 0), el qual ens envia al node 2. Visitem el node 2, on posicionem el valor cercat 79 entre els valors 77 i 84, la qual cosa ens porta a seguir el cam cap al node 8. Visitem el node 8, on trobem el valor cercat.
3) Recerca de lelement 80

Visitem larrel (node 0), el qual ens envia al node 2. Visitem el node 2, el qual ens envia al node 9. Visitem el node 9, on no hi ha lelement cercat. Ja som en una fulla. La recerca ha finalitzat sense trobar lelement desitjat.

Algorisme dinserci
Els arbres B creixen de baix cap a dalt: de les fulles cap a larrel. Lalgorisme consisteix, en primer lloc, a aplicar lalgorisme de recerca per situarse en el node fulla, on hi hauria dhaver lelement a inserir. Una vegada en el node, hi ha diferents possibilitats:
1) Si hi ha espai (el node cont menys de 2d elements), sinsereix adequa-

dament (mantenint lordre dins la fulla) i lalgorisme finalitza.


2) Si no hi ha espai (el node cont exactament 2d elements), el node fulla es

divideix en dos (en realitat, es crea dinmicament un nou node), i els 2d + 1 elements (els 2d que ja existien en la fulla, ms lelement que cal inserir) es distribueixen ordenadament entre els dos nodes fulla, amb d valors en cada node fulla (els d valors ms petits en el node fulla esquerre i els d valors ms grans en el node fulla dret). Aleshores lelement central puja cap al node pare del node fulla inicial i shi insereix adequadament. La inserci en el node pare consisteix a repetir el mateix procs, cosa que pot provocar la creaci dun nou node amb la pujada del valor central cap al pare corresponent. Quan el node pare en qu cal inserir un element s el node arrel de larbre i ja no hi ha espai disponible, aquest provoca la creaci de dos nodes nous (en lloc de noms un!), ja que lun s el corresponent al procs normal i laltre, al nou node arrel (el node pare al qual puja lelement central).
Terminologia anglesa El procs descrit, que consisteix en la divisi dun node en dos, en qu es reparteixen els valors i el valor central passa al node pare, sanomena split en terminologia informtica anglesa. Per aix s molt normal indicar quan cal aplicar el procs sobre un node A, que el node A esplita, en un clar abs de terminologia. Per estareu dacord que dir el node A esplita s molt clar i molt ms simple que dir es crea un nou node que recull la meitat superior del conjunt ordenat de valors format pels

Estructures de dades dinmiques

42

Recursivitat. Arbres

valors del node A ms el valor a inserir; el node A es queda amb la meitat inferior del mateix conjunt de valors i el valor central sinsereix en el node pare del node A. Per tant, utilitzarem lexpressi el node esplita per fer referncia a tot aquest procs.

Vegem-ne un exemple per entendre les diferents situacions que es poden presentar. Volem construir un arbre B dordre 2 a partir de la seqncia de valors 5 - 22 - 24 - 12 - 20 - 16 - 10 - 26 - 8 - 46 - 15 - 19 - 43 - 14 - 55 - 30 - 61. La figura 17 ens mostra els passos que hem de seguir.
Figura 17. Creaci dun arbre B amb els valors 5, 22, 24, 12, 20, 16, 10, 26, 8, 46, 15, 19, 43, 14, 55, 30 i 61

Estructures de dades dinmiques

43

Recursivitat. Arbres

Estructures de dades dinmiques

44

Recursivitat. Arbres

Algorisme deliminaci
Lalgorisme deliminaci ha de fer una cosa contrria a lalgorisme dinserci, ja que un node (excepte larrel) mai no pot quedar amb menys de d valors. Per tant, hi haur algun procs invers a lsplit, consistent en una fusi de nodes. En efecte, lalgorisme consisteix a cercar lelement que sha desborrar i, una vegada localitzat, hi ha dues possibilitats:
1) Si el valor que sha desborrar es troba en una fulla, se suprimeix. 2) Si el valor que sha desborrar es troba en un node no fulla, se substitueix

pel valor que es troba ms a la dreta del subarbre apuntat pel seu punter esquerre o pel valor que es troba ms a lesquerra del subarbre apuntat pel seu punter dret. Aquest valor sempre es troba en una fulla. En qualsevol dels dos casos, sha de verificar si la fulla que ha acabat perdent el valor continua tenint d valors com a mnim. Si s aix, no sha de fer res ms. En cas contrari, sha daplicar una reorganitzaci o fusi de la fulla amb la fulla germana de la dreta, si existeix, o amb la fulla germana de lesquerra (si no tenia germana per la dreta). Tota fulla que no sigui arrel sempre t una fulla germana. Reorganitzarem quan la fulla germana tingui ms de d valors. En aquest cas, aquesta cedir valors a la fulla que ha perdut lelement suprimit. Aquesta cessi comporta un moviment del valor mitj existent en el pare de les dues fulles. Fusionarem quan la fulla germana tingui exactament d valors. En aquest cas, passa a haver-hi una nica fulla que cont els valors de les dues ms el valor mitj que residia en el pare. Per tant, el pare es queda amb un valor menys i cal aplicar-hi el mateix procs de comprovaci que sobre la quantitat de valors que cont. Si s inferior a d cal aplicar-hi el mateix procs de reorganitzaci o fusi. Vegem exemples deliminaci sobre el darrer arbre de la figura 17. Suposem que volem eliminar els valors 20 - 19 - 24 - 22 - 43 - 14 - 46 - 16. La figura 18 ens mostra els passos que hem de seguir.

Estructures de dades dinmiques

45

Recursivitat. Arbres

Figura 18. Exemples deliminaci de valors en un arbre B

Estructures de dades dinmiques

46

Recursivitat. Arbres

2.4.2. Arbres B+
Els arbres B+ sn molt semblants als arbres B. La caracterstica principal daquests arbres s que tots els valors es troben en les fulles. Per tant: Qualsevol cam des de larrel per arribar a un element t la mateixa longitud. En els nodes interiors no cal tenir emmagatzemats els elements sencers, que es trobaran en les fulles. Noms cal tenir-hi emmagatzemats els valors de classificaci. Un arbre B+ dordre d s un arbre que verifica el segent: Cada node, excepte larrel, cont entre d i 2d valors de classificaci. Cada node, excepte larrel i les fulles, t entre d + 1 i 2d + 1 fills. El node arrel o no t fills (perqu s una fulla) o en t dos com a mnim. Totes les fulles es troben a un mateix nivell (balancejat perfecte) i sn les que contenen els elements que emmagatzema larbre. Els valors emmagatzemats dins un node estan ordenats de ms petit a ms gran (desquerra a dreta). Cada valor dun node interior t dos fills. Tots els valors del seu subarbre esquerre sn ms petits que ell i tots els valors del seu subarbre dret sn ms grans o iguals que ell.

Observeu que, a diferncia dels arbres B, en els quals tots els elements del subarbre dret de qualsevol element sn ms grans que lelement en qes-

Estructures de dades dinmiques

47

Recursivitat. Arbres

ti, en els arbres B+ tots els valors del subarbre dret de qualsevol valor sn ms grans o iguals que el valor en qesti. Observeu, tamb, que en el pargraf anterior utilitzem el terme element per fer referncia al contingut dels nodes dels arbres B i el terme valor per fer referncia al contingut dels nodes dels arbres B+, ja que en aquests els elements noms sn en els nodes fulles. En els arbres B+ sevita la costosa operaci de reorganitzaci, per aix ja ho comprovarem en lalgorisme deliminaci corresponent.

Algorisme de recerca
s molt similar al dels arbres B, per amb la particularitat que en trobar el valor cercat en un node interior, cal continuar la recerca pel node apuntat per la dreta. El fet que un valor de recerca existeixi en un node interior no implica que hi hagi un element amb aquell valor en una de les fulles; simplement vol dir que en algun moment de la vida de larbre s que havia existit. Podrem constatar aquest fet en aplicar lalgorisme deliminaci.

Algorisme dinserci
s molt similar al dels arbres B, per amb la particularitat que quan una fulla no t ms espai i saplica el procs de split, lelement central es mant en la nova fulla (que quedar amb d + 1 valors) i una cpia del seu valor de classificaci passa a afegir-se al node pare de la fulla inicial. En els arbres B, era lelement central i no pas el valor de classificaci el que passava a formar part del node pare. En canvi, laplicaci del procs de split a un node interior s idntica a la que saplica en els arbres B. La figura 19 ens en mostra un exemple.
Figura 19. Exemple dinserci en un arbre B+ dordre 1

Estructures de dades dinmiques

48

Recursivitat. Arbres

Algorisme deliminaci
s molt ms simple que en arbres B. Aix s degut al fet que els elements que shan deliminar sempre es troben a les fulles i no hi ha cap problema que el valor de classificaci corresponent a lelement eliminat continu estant en nodes interiors, tal com havem comentat en lalgorisme de recerca. Tenim dues possibilitats:
1) Si en eliminar un element la fulla queda amb d valors com a mnim, no

es fa res ms, encara que en algun node interior o en el node arrel hi hagi una cpia del valor de classificaci de lelement eliminat.
2) Si en eliminar un element la fulla queda amb menys de d valors, cal in-

tentar fer una reorganitzaci de valors en les fulles i en lndex. Caldr fusionar quan no hi hagi ms remei. La figura 20 ens en mostra un exemple.
Figura 20. Exemple deliminaci en un arbre B+ dordre 1

2.4.3. Utilitat en arxius seqencials indexats


En aquests moments coneixem diferents tipus darbres, des dels ms genrics fins als ms especfics (arbres B i B+). Quan sutilitzen? Ja sabem que els arbres tenen diverses aplicacions, una de les quals s la gesti dels ndexs en els arxius seqencials indexats.

Estructures de dades dinmiques

49

Recursivitat. Arbres

La figura 21 ens mostra un arxiu de dades amb diferents camps pel qual es vol disposar daccs directe i seqencial per valor de dos camps. Per aconseguir-ho tenim la necessitat de dos ndexs, tal com sobserva en la figura 21.
Figura 21. Exemple dun arxiu de dades indexat per dos camps diferents

En lexemple sutilitza un ndex lineal simple. Podrem, per, utilitzar els arbres B per als ndexs, de manera que lelement a emmagatzemar en les 2d caselles de cada node sigui la parella (clau, punter). Aix, si suposem arbres B dordre 1 i que es produeix la successi dinsercions en el mateix ordre en qu tenim els registres en larxiu de dades de la figura 21, podem anar construint els dos arbres B (un per a cada ndex). La figura 22 ens mostra els passos que se succeirien. Observeu que la instrucci llegir=_fi, facilitada pel sistema gestor darxius indexat, per a cercar el registre amb cognom Coromina per a lndex cognom aplicar lalgorisme de recerca per a aquest ndex. Trobar el valor Coromina en el node arrel acompanyat del valor 6, que indica ladrea on es troba el corresponent registre en larxiu (o zona) de dades. Fixeu-vos que per aconseguir laccs seqencial per valor segons una via daccs simplement cal dissenyar un algorisme dinordre generalitzat per als diferents elements de cada node. Aix, a partir de Coromina, passar al segent implicaria continuar pel cam que indica el seu punter dret. Anirem aix a Esteve. El recorregut preordre generalitzat ens portaria, posteriorment, a Miralles, Oll i Pelfort. Refem els passos de la figura 22 per al cas que els ndexs siguin arbres B+ dordre 1. La figura 23 ens mostra la seqncia de passos.

Estructures de dades dinmiques

50

Recursivitat. Arbres

Figura 22. Construcci darbres B per a ndexs dun arxiu de dades

Estructures de dades dinmiques

51

Recursivitat. Arbres

Figura 23. Construcci darbres B+ per a ndexs dun arxiu de dades

Estructures de dades dinmiques

52

Recursivitat. Arbres

Observeu que en els nodes interiors dels arbres B+ noms hi ha el valor clau (valor de classificaci), mentre que en les fulles s on es troben el valor clau i ladrea, on hi ha la posici del registre corresponent a la zona de dades. Fixeu-vos que en cas de mantenir els nodes fulla encadenats (cosa independent de la gesti dun arbre B+), laccs seqencial pel valor de la via daccs corresponent seria molt fcil, ja que ens trobem Brito, Coromina, Esteve, Miralles, Oll i Pelfort. Si en lloc duna cadena simple es mant una doble cadena, tindrem el mateix accs seqencial per valor cap endavant i cap enrere.

You might also like