Tipos Arbóreos Nociones de Árbol Los árboles son conjuntos de nodos con un estructura jerárquica que parte de un nodo principal o raíz. Cada nodo de un árbol junto con todos sus descendientes constituye otro árbol. Los árboles se pueden definir como estructuras recursivas que presentan recursión múltiple. Según la ramificación que presenten los nodos, fija o variable, aparecen distintos tipos de árboles: árboles de orden N o árboles generales. 2 Árboles Binarios Árboles binarios: ArbolB[X] = {vacio} | ArbolB[X] × Elt.X × ArbolB[X] (fmod ARBOLB [X :: TRIV] is protecting MACHINE-INT . sorts ArbolB[X] ArbolBNv[X] . subsort ArbolBNv[X] < ArbolB[X] . op vacio : -> ArbolB[X] [ctor] . op _’[_’]_ : ArbolB[X] Elt.X ArbolB[X] -> ArbolBNv[X] [ctor] . op raiz : ArbolBNv[X] -> Elt.X . ops ri rd : ArbolBNv[X] -> ArbolB[X] . op altura : ArbolB[X] -> MachineInt . op n-nodos : ArbolB[X] -> MachineInt . ... endfm) 4 Recorridos (fmod RECORRIDOS [X :: TRIV] is protecting LISTA[X] . protecting ARBOLB[X] . op preorden : ArbolB[X] -> Lista[X] . op inorden : ArbolB[X] -> Lista[X] . op postorden : ArbolB[X] -> Lista[X] . ... endfm) 5 Árboles binarios etiquetados ArbolBEt[N,H] = Elt.H | ArbolBEt[N,H] × Elt.N × ArbolBEt[N,H] (fmod ARBOLBEt[N :: TRIV, H :: TRIV] is protecting MACHINE-INT . sorts ArbolBEt[N,H] ArbolBEtNh[N,H] . subsort Elt.H < ArbolBEt[N,H] . subsort ArbolBEtNh[N,H] < ArbolBEt[N,H] . op _‘[_’]_ : ArbolBEt[N,H] Elt.N ArbolBEt[N,H] -> ArbolBEtNh[N,H] [ctor] . op raiz : ArbolBEtNh[N,H] -> Elt.N . ops ri rd : ArbolBEtNh[N,H] -> ArbolBEt[N,H] . op altura : ArbolBEt[N,H] -> MachineInt . op n-nodos : ArbolBEt[N,H] -> MachineInt . op n-hojas : ArbolBEt[N,H] -> MachineInt . op n-nodosNivel : MachineInt ArbolBEt[N,H] -> MachineInt . ... 6 endfm) Árboles de expresiones (I) (fmod OP is sort Op . ops + * - / : -> Op . endfm) (view Op from TRIV to OP is sort Elt to Op endv) (view IntM from TRIV to MACHINE-INT is sort Elt to MachineInt . endv) 7 Árboles de expresiones (II) (fmod ARBOLEXP is protecting ArbolBEt[Op, IntM] . sort MachineInt? . subsort MachineInt < MachineInt? . op valor : ArbolBEt[Op, IntM] -> MachineInt? . var N : MachineInt . var O : Op . var Ri Rd : ArbolBEt[Op, IntM] . eq valor(N) = N . eq valor(Ri [+] Rd) = valor(Ri) + valor(Rd) . eq valor(Ri [-] Rd) = valor(Ri) - valor(Rd) . eq valor(Ri [*] Rd) = valor(Ri) * valor(Rd) . ceq valor(Ri [/] Rd) = valor(Ri) / valor(Rd) if valor(Rd) =/= 0 . endfm) 8 Propiedades var A : ArbolBEt[N H] . var N : MachineInt . n-hojas(A) == 1 + n-nodos(A) n-hojas(A) <= 2 ** altura(A) altura(A) <= n-nodos(A) n-nodosNivel(N,A) =< 2 ** N 9 Árboles completos y llenos sorts ArbBCompleto[N H] ArbBLleno[N H] . subsorts Elt.H < ArbBCompleto[N H] < ArbBLleno[N H] < ArbolBEtq[N H] . vars Ac1 Ac2 : ArbBCompleto[N H] . var R : Elt.N . cmb Ac1[R]Ac2 : ArbBCompleto[N H] if altura(Ac1) == altura(Ac2) . vars A1 A2 : ArbBLleno[N H] . cmb A1[R]Ac2 : ArbBLleno[N H] if altura(A1) == 1 + altura(Ac2)) . cmb Ac1[R]A2 : ArbBLleno[N H] if altura(Ac1) == altura(A2) . 10 Árboles equilibrados en altura sorts ArbBheq[N H] . subsorts Elt.H < ArbBheq[N H] < ArbolBEtq[N H] . vars Ah1 Ah2 : ArbBheq[N H] . var R : Elt.N . cmb Ah1[R]Ah2 : ArbBheq[N H] if altura(Ah2) altura(Ah1) cmb Ah1[R]Ah2 : ArbBheq[N H] if altura(Ah1) altura(Ah2) <= altura(Ah1) and - altura(Ah2) <= 1 . <= altura(Ah2) and - altura(Ah1) <= 1 . 11 Árboles equilibrados en peso sort ArbBpeq[N H] . subsorts Elt.H < ArbBpeq[N H] < ArbolBEtq[N H] . vars Ap1 Ap2 : ArbBpeq[N H] . var R : Elt.N . cmb Ap1[R]Ap2 : ArbBpeq[N H] if n-nodos(Ap2) n-nodos(Ap1) cmb Ap1[R]Ap2 : ArbBpeq[N H] if n-nodos(Ap1) n-nodos(Ap2) <= n-nodos(Ap1) and - n-nodos(Ap2) <= 1 . <= n-nodos(Ap2) and - n-nodos(Ap1) <= 1 . 12 Propiedades especiales var Ac : ArbBCompleto[N H] . n-hojas(Ac) == 2 ** altura(Ac) . n-nodosNivel(N,Ac) == 2 ** N si 0 < N <= altura(Ac) . var Al : ArbBLleno[N H] . n-hojas(Al) <= 2 ** altura(Al) . altura(Al) == natsup(log2(n-hojas(Al))) . var Ap : ArbBpeq[N H] . altura(Ap) == natsup(log2(n-hojas(Al))) . var Ah : ArbBheq[N H] . altura(Ah) <= 1.44 * natsup(log2(n-hojas(Al))) . *** natsup(X) es el menor natural mayor o igual que X 13 Árboles Binarios Ordenados Pares Ordenados (fth PARORD is including ORDTOT . sorts ParOrd Cont Cont? . subsort Cont < Cont? . op <_,_> : Elt Cont -> ParOrd . op clave : ParOrd -> Elt . op contenido : ParOrd -> Cont . op actualizar : Cont Cont -> Cont . op no-encontrado : -> Cont? . var K : Elt . var C : Cont . eq clave(<K,C>) = K . eq contenido(<K,C>) = C . endfth) 15 Árboles binarios ordenados (I) (view Par from TRIV to PARORD is sort Elt to ParOrd . endv) (fmod ABB[X :: PARORD] is protecting ARBOLB[Par][X] . sorts Abb[X] AbbNv[X] . subsorts AbbNv[X] < Abb[X] < ArbolB[Par][X] . subsort AbbNv[X] < ArbolBNv[Par][X] . op insertar : ParOrd.X Abb[X] -> AbbNv[X] . op eliminar : Elt.X Abb[X] -> Abb[X] . op consulta : Elt.X Abb[X] -> Cont?.X . op esta? : Elt.X Abb[X] -> Bool . ops min max : AbbNv[X] -> Par.X . 16 Árboles binarios ordenados (II) vars P Q : ParOrd.X . var K : Elt.X . var C : Cont.X . var A : Abb[X] . vars Ai Ad : AbbNv[X] . mb cmb cmb cmb vacio : Abb[X] vacio [P] Ad : Ai [P] vacio : Ai [P] Ad : . mb vacio [P] vacio : AbbNv[X] . AbbNv[X] if clave(P) < clave(min(Ad)) . AbbNv[X] if clave(max(Ai)) < clave(P) . AbbNv[X] if clave(max(Ai)) < clave(P) and clave(P) < clave(min(Ad)) . eq min(Ai) = if ri(Ai) == vacio then raiz(Ai) else min(ri(Ai)) fi . eq max(Ai) = if rd(Ai) == vacio then raiz(Ai) else max(rd(Ai)) fi . 17 Árboles binarios ordenados (III) eq insertar(P,A) = if A == vacio then vacio [P] vacio else if clave(P) == clave(raiz(A)) then *** actualizar ri(A) [<clave(P),actualizar(contenido(raiz(A)), contenido(P))>] rd(A) else *** insertar en una rama if clave(P) < clave(raiz(A)) then insertar(P,ri(A)) [raiz(A)] rd(A) else ri(A) [raiz(A)] insertar(P,rd(A)) fi fi fi . 18 Eliminación en un Abb 19 Árboles binarios ordenados (IV) eq eliminar(K,A) = if A == vacio then vacio else if K == clave(raiz(A)) then if ri(A) == vacio then rd(A) else if rd(A) == vacio then ri(A) else eliminar(clave(max(ri(A))),ri(A)) [max(ri(A))] rd(A) fi fi else if K < clave(raiz(A)) then eliminar(K,ri(A)) [raiz(A)] rd(A) else ri(A) [raiz(A)] eliminar(K,rd(A)) fi fi fi . 20 Árboles binarios ordenados (V) eq esta?(K,A) = if A == vacio then false else if K == clave(raiz(A)) then true else if K < clave(raiz(A)) then esta?(K,ri(A)) else esta?(K,rd(A)) fi fi fi . eq consulta(K,A) = if A == vacio then no-encontrado else if K == clave(raiz(A)) then contenido(raiz(A)) else if K < clave(raiz(A)) then consulta(K,ri(A)) else consulta(K,rd(A)) fi fi fi . 21 Árboles binarios ordenados equilibrados en altura (AVL) (fmod AVL[X :: PARORD] is protecting MACHINE-INT . protecting ABB[X] . sort Avl[X] AvlNv[X] . subsorts AvlNv[X] < Avl[X] < Abb[X] . subsort AvlNv[X] < AbbNv[X] . op insertarEq : ParOrd.X Avl[X] -> AvlNv[X] . op eliminarEq : Elt.X Avl[X] -> Avl[X] . op equilibrar : Abb[X] -> Abb[X] . ops rotIzq rotDer : AbbNv[X] -> AbbNv[X] . op pendiente : ArbolB[X] -> MachineInt . 22 Avl (II) vars P Q : ParOrd.X . var T:ArbolBNv[X] . var A:Avl[X] . vars A1 A2 : AvlNv[X] . mb vacio : Avl[X] . cmb A [P] A2 : Avl[X] if clave(P)<clave(min(A2)) and altura(A2)==1 . cmb A1 [P] A : Avl[X] if clave(max(A1))<clave(P) and altura(A1)==1 . cmb A1 [P] A2 : Avl[X] if clave(max(A1))<clave(P) and clave(P)<clave(min(A2)) and altura(A1)<=altura(A2) and altura(A2)-altura(A1)<=1 . cmb A1 [P] A2 : Avl[X] if clave(max(A1))<clave(P) and clave(P)<clave(min(A2)) and altura(A2)<=altura(A1) and altura(A1)-altura(A2)<=1 . 23 Avl (III) eq pendiente(vacio) = 0 . eq pendiente(T) = altura(rd(T)) - altura(ri(T)) . vars B B1 B2 B3 : ABB[X] . ceq rotIzq(B1 [P] vacio) = B1 [P] vacio if B1 [P] vacio : Abb[X] . ceq rotIzq(B1 [P] (B2[Q]B3)) = (B1[P]B2) [Q] B3 if B1 [P] (B2[Q]B3) : Abb[X] . ceq rotDer(vacio [P] B2) = vacio [P] B2 if vacio [P] B2 : Abb[X] . ceq rotDer((B1[P]B2) [Q] B3) = B1 [P] (B2[Q]B3) if (B1[P]B2) [Q] B3 : Abb[X] . 24 Consideraciones En un avl todos los subárboles tendrán pendientes comprendidas entre –1 y 1. Una inserción sólo puede modificar la pendiente de los subárboles con raíz en el camino de acceso al nodo insertado. Esta modificación sólo puede dar lugar a pendientes con valores –2 o 2 en el peor caso. El árbol se equilibra a partir del nodo más próximo al punto de inserción que haya quedado desequilibrado. En el caso de la eliminación de un nodo, la situación es parecida. 25 Equilibrado (I) rotDer 26 Equilibrado (II) rotIzq rotDer 27 Avl : equilibrar eq equilibrar(B) = if B == vacio then vacio else if pendiente(B) == -2 then if pendiente(ri(B)) == 1 then rotDer(rotIzq(ri(B)) [raiz(B)] rd(B)) else rotDer(B) fi else if pendiente(B) == 2 then if pendiente(rd(B)) == -1 then rotIzq(ri(B) [raiz(B)] rotDer(rd(B))) else rotIzq(B) fi else B fi fi fi . 28 Avl : insertar en equilibrio eq insertarEq(P,A) = if A == vacio then vacio [P] vacio else if clave(P) == clave(raiz(A)) then *** actualizar ri(A) [<clave(P),actualizar(contenido(raiz(A)),contenido(P))>] rd(A) else *** insertar en una rama if clave(P) < clave(raiz(A)) then equilibrar(insertarEq(P,ri(A)) [raiz(A)] rd(A)) else equilibrar(ri(A) [raiz(A)] insertarEq(P,rd(A))) fi fi fi . 29 Avl : eliminar en equilibrio var K : Elt.X . eq eliminarEq(k,A) = if A == vacio then vacio else if K == clave(raiz(A)) then if ri(A) == vacio then rd(A) else if rd(A) == vacio then ri(A) else equilibrar( eliminarEq(clave(max(ri(A))),ri(A))) [max(ri(A))] rd(A) ) fi fi else if K < clave(raiz(A)) then equilibrar(eliminarEq(K,ri(A)) [raiz(A)] rd(A)) else equilibrar(ri(A) [raiz(A)] eliminarEq(K,rd(A))) fi fi fi . endfm) 30 Árboles Binarios Parcialmente Ordenados Heap (árbol lleno parcialmente ordenado) Árbol lleno de ramas ordenadas con el menor elemento en la raíz. Operaciones características: Agregar un elemento Eliminar la raíz 32 Árboles llenos ordenados parcialmente (heaps) (fmod HEAP[X :: PARORD] is protecting ARBOLB[Par][X] . sorts Heap[X] HeapNv[X] . subsorts HeapNv[X] < Heap[X] < ArbolB[Par][X] . subsort HeapNv[X] < ArbolBNv[Par][X] . op amontonar : ParOrd.X Heap[X] -> HeapNv[X] . op cima : HeapNv[X] -> ParOrd.X . op retCima : HeapNv[X] -> Heap[X] . *** ops auxiliares op fondo : HeapNv[X] -> ParOrd.X . op retFondo : HeapNv[X] -> Heap[X] . op hundir : Heap[X] ParOrd.X Heap[X] -> ArbolBNv[X] . op completo? : ArbolB[X] -> Bool . 33 Heaps (I) var P : ParOrd.X . vars A1 A2 : ArbolNv[Par][X] . vars H1 H2 : HeapNv[X] . eq completo?(vacio) = true . eq completo?(A1) = altura(ri(A1))==altura(rd(A1)) and completo?(ri(A1)) and completo?(rd(A1)) . mb vacio : Heap[X] . mb vacio [P] vacio : HeapNv[X] . cmb H1 [P] vacio : HeapNv[X] if clave(raiz(H1)) <= clave(P) and altura(H1) == 1 . cmb H1 [P] H2 : HeapNv[X] if clave(raiz(H1)) <= clave(P) and clave(raiz(H2)) <= clave(P) and ((altura(H1) == altura(H2) and completo?(H1)) or (altura(H1) == 1+altura(H2) and completo?(H2))) . 34 Heaps (II) eq cima(H1) = raiz(H1) . eq amontonar(P,vacio) = vacio [P] vacio . eq amontonar(P,H1) = if completo?(H1) or not completo?(ri(H1)) then *** amontonar por la izq if clave(raiz(H1))<=clave(P) then amontonar(raiz(H1),ri(H1)) [P] rd(H1) else amontonar(P,ri(H1)) [raiz(H1)] rd(H1) fi else *** amontonar por la der if clave(raiz(H1))<=clave(P) then ri(H1) [P] amontonar(raiz(H1),rd(H1)) else ri(H1) [raiz(H1)] amontonar(P,rd(H1)) fi fi . 35 Heaps (III) eq fondo(H1) = if (ri(H1) == vacio and rd(H1) == vacio) then raiz(H1) else if altura(rd(H1)) < altura(ri(H1)) then fondo(ri(H1)) else fondo(rd(H1)) fi fi . eq retFondo(H1) = if (ri(H1) == vacio and rd(H1) == vacio) then vacio else if altura(rd(H1)) < altura(ri(H1)) then retFondo(ri(H1)) [raiz(H1)] rd(H1) else ri(H1) [raiz(H1)] retFondo(rd(H1)) fi fi . 36 Heaps (IV) var H : Heap[X] . eq hundir(vacio,P,H) = vacio [P] H . eq hundir(H1,P,H) = if H == vacio then if clave(raiz(H1)) < clave(P) then H1 [P] H else hundir(ri(H1),P,rd(H1)) [raiz(H1)] H fi else if (clave(raiz(H1)) < clave(P) and clave(raiz(H)) < clave(P)) then H1 [P] H else if clave(raiz(H1)) < clave(raiz(H)) then H1 [raiz(H)] hundir(ri(H),P,rd(H)) else hundir(ri(H1),P,rd(H1)) [raiz(H1)] H fi fi fi . 37 Heaps (V) eq retCima(H1) = if ri(H1) == vacio then vacio else hundir(ri(retFondo(H1)), fondo(H1), rd(retFondo(H1))) fi . endfm) 38 Árboles Generales Árboles Generales (I) (fmod ARBOL [N :: TRIV] is protecting LISTA[N] . protecting MACHINE-INT . sorts Arbol[N] Bosque[N] . op _`[_`] : Elt.N Bosque[N] -> Arbol[N] [ctor]. op bosqueV : -> Bosque[N] [ctor]. op _:_ : Arbol[N] Bosque[N] -> Bosque[N] [ctor]. op raiz : Arbol[N] -> Elt.N . op hijos : Arbol[N] -> Bosque[N] . ops altura grado #nodos : Arbol[N] -> MachineInt . ops alturaB gradoB #nodosB : Bosque[N] -> MachineInt . op longitud : Bosque[N] -> MachineInt . op esHoja? : Arbol[N] -> Bool . ops preorden postorden : Arbol[N] -> Lista[N] . 40 ops preordenB postordenB : Bosque[N] -> Lista[N] . Árboles Generales (II) op max : MachineInt MachineInt -> MachineInt . var R : Elt.N . var T : Arbol[N] . vars I J : MachineInt . var B : Bosque[N] . eq raiz(R [B]) = R . eq hijos(R [B]) = B . eq eq eq eq max(I,J) = if I < J then J else I fi . altura(R [B]) = 1 + alturaB(B) . alturaB(bosqueV) = 0 . alturaB(T : B) = max(altura(T),alturaB(B)) . eq longitud(bosqueV) = 0 . eq longitud(T : B) = 1 + longitud(B) . eq esHoja?(R [B]) = B == bosqueV . 41 Árboles Generales (III) eq grado(R [B]) = max(longitud(B),gradoB(B)) . eq gradoB(bosqueV) = 0 . eq gradoB(T : B) = max(grado(T),gradoB(B)) . eq #nodos(R [B]) = 1 + #nodosB(B) . eq #nodosB(bosqueV) = 0 . eq #nodosB(T : B) = #nodos(T) + #nodosB(B) . eq preorden(R [B]) = R : preordenB(B) . eq preordenB(bosqueV) = nil . eq preordenB(T : B) = preorden(T) ++ preordenB(B) . eq postorden(R [B]) = postordenB(B) ++ (R:nil) . eq postordenB(bosqueV) = nil . eq postordenB(T : B) = postorden(T) ++ postordenB(B) . endfm) 42 Ejercicios Especificad las siguientes operaciones sobre árboles generales: op pertenece? : Elt.N Arbol[N] -> Bool . que compruebe si un elemento pertenece o no a un árbol, op mismaForma? : Arbol[N] Arbol[N] -> Bool . que compruebe si dos árboles tienen o no la misma forma. Adaptar la especificación de árbol general para poder especificar las operaciones op subArbol : Elt.N Arbol[N] -> Arbol[N]? . que produzca el subárbol del árbol dado con raíz en el nodo dado ( el primero en preorden si hay más de uno) y op camino : Elt.N Arbol[N] -> Lista[N] que produzca una lista con todos los nodos desde la raíz hasta el nodo dado inclusive o una lista vacía si el nodo no está en el árbol. 43 Árboles de Orden K Intervalos de orden K (fth GRADO is protecting MACHINE-INT . op k : -> MachineInt . eq k >= 2 = true . endth) *** grado k > 2 (fmod NAT [K :: GRADO] is *** intervalos [0..k-1] sort Nat[K] . subsort Nat[K] < MachineInt . var N : MachineInt . cmb N : Nat[K] if 0 <= N and N < k.K . endfm) 45 Árboles de orden K (I) (fmod ARBOL [K :: GRADO, X :: TRIV] is protecting NAT[K] . protecting LISTA[X] . sorts ArbolNv[K,X] Arbol[K,X] TuplaA[K,X] . subsort ArbolNv[K,X] < Arbol[K,X] . *** constructoras de árboles op arbolV : -> Arbol[K,X] [ctor] . op _`[_`] : Elt.X TuplaA[K,X] -> ArbolNv[K,X] [ctor] . *** constructoras de tuplas de árboles/ramas op tuplaV : -> TuplaA[K,X] [ctor] . op _`[_/_`] : TuplaA[K,X] Nat[K] Arbol[K,X] -> TuplaA[K,X] [ctor] . 46 Árboles de orden K (II) *** operaciones de consulta op raiz : ArbolNv[K,X] -> Elt.X . op rama : Nat[K] ArbolNv[K,X] -> Arbol[K,X] . op ramaT : Nat[K] TuplaA[K,X] -> Arbol[K,X] . ops altura grado #nodos: Arbol[K,X] -> MachineInt . ops preorden postorden : Arbol[K,X] -> Lista[X] . *** operaciones auxiliares op max : MachineInt MachineInt -> MachineInt . ops alturaT #nodosT : TuplaA[K,X] Nat[K] -> MachineInt . ops preordenT postordenT : TuplaA[K,X] Nat[K] -> Lista[X] . vars I J : MachineInt . eq max(I,J) = if I < J then J else I fi . 47 Árboles de orden K (III) var E : Elt.X . var T : TuplaA[K,X] . vars A B : Arbol[K,X] . ceq (T[I/A])[J/B] = T[J/B] if I == J . ceq (T[I/A])[J/B] = (T[J/B])[I/A] if I > J . eq ramaT(I,tuplaV) = arbolV . eq ramaT(I,T[J/A]) = if I == J then A else ramaT(I,T) fi . eq raiz(E[T]) = E . eq rama(I,E[T]) = ramaT(I,T) . eq grado(E[T]) = k.K . eq altura(arbolV) = 0. eq altura(E[T]) = 1 + alturaT(T,0) . eq alturaT(T,I) = if I == k.K - 1 then altura(ramaT(I,T)) else max(altura(ramaT(I,T)),alturaT(T,I+1)) fi . 48 Árboles de orden K (IV) eq #nodos(arbolV) = 0 . eq #nodos(E[T]) = 1 + #nodosT(T,0) . eq #nodosT(T,I) = if I == k.K - 1 then #nodos(ramaT(I,T)) else #nodos(ramaT(I,T))+ #nodosT(T,I+1) fi . eq preorden(arbolV) = nil . eq preorden(E[T]) = E : preordenT(T,0) . eq preordenT(T,I) = if I == k.K - 1 then preorden(ramaT(I,T)) else preorden(ramaT(I,T))++preordenT(T,I+1) fi . eq postorden(arbolV) = nil . eq postorden(E[T]) = postordenT(T,0) ++ (E:nil) . eq postordenT(T,I) = if I == k.K - 1 then postorden(ramaT(I,T)) else postorden(ramaT(I,T))++postordenT(T,I+1) fi . 49 endfm) Ejercicios Especificad las operaciones: pertenece?, mismaForma?, subArbol, camino para árboles de orden K. 50