ESTRUCTURAS DE DATOS II
CAPITULO 8
ÁRBOLES
LUIS F. AGUAS B. 1
CAPITULO 8
1. Árboles en general
Definiciones
Terminología
2. Recorrido de árboles
Postorden
Preorden
3. Tipos de árboles
Binarios
AVL
Multicamino
Balanceado (B, B*, B+)
LUIS F. AGUAS B. 2
ÁRBOL: DEFINICIÓN
En computación, un
árbol es un modelo Computadores
abstracto de una
estructura ventas Manufactura Reclamo
jerárquica.
Local Internacional Laptops Desktops
Aplicaciones:
Organigramas
Sistemas de archivos Europa Asia Canada
Ambientes de
programación
LUIS F. AGUAS B. 3
ÁRBOLES EN GENERAL Y CON RAÍZ
En teoría de grafos, un árbol (tree) es un conjunto de nodos
(vértices) y arcos (links, lines) conectando los nodos tal que:
No existen ciclos
cada dos nodos están conectados por un solo arco
En muchas aplicaciones informáticas, un nodo particular del
el árbol es designado raíz (root), los otros nodos son
arreglados por niveles a partir del nodo raíz.
root
Nivel 0
Nivel 1
Nivel 2
Árbol general Un árbol con raíz
LUIS F. AGUAS B. 4
TERMINOLOGÍA DE ÁRBOLES
Una estructura de árbol es una colección de nodos, c/u con:
Puede tener uno o mas sucesores
Tiene solo un predecesor, con excepción del nodo raíz.
El nodo primero o inicial de la estructura árbol es llamado raíz
Un nodo predecesor es llamado padre (parent)
Un nodo sucesor es llamado hijo (children)
Nodos con padre común son llamados hermanos (siblings)
Un nodo sin hijos es llamado hoja (leaf)
Un nodo que tiene hijos es llamado nodo interior
Un nodo sin hijos es llamado nodo exterior
Los nodos descendientes consisten en hijos, nietos hasta
llegar a las hojas.
Los nodos ancestros consisten de padres, abuelos hasta llegar
a la raíz.
LUIS F. AGUAS B. 5
TERMINOLOGÍA DE ÁRBOLES
Un lado (edge or branch) es la línea que conecta un padre
con el hijo.
Un camino (path) es la secuencia de lados que conectan un
nodo con uno de sus descendientes
La longitud del camino (path length) es el número de lados
en el camino.
La profundidad o nivel (depth o level) de un nodo es igual a
la longitud de nodo a la raíz.
La profundidad de la raíz es cero
El peso (height) de un árbol es igual a la longitud del
camino más largo.
Un sub-árbol (subtree) es un árbol formado al considerar
un nodo como “raíz”. El nuevo árbol consiste de este nodo y
su descendencia.
2012 Octubre LUIS F. AGUAS B. 6
Terminología de árboles
PROPIEDAD VALOR
Numero de nodos 10
H
Peso 3
Nodo raíz H
B F
Hojas ACJL
MN
A C J E Nodos interiores HBFE
Nodos a nivel 2 ACJE
L M N
2012 Octubre LUIS F. AGUAS B. 7
NODO DE ÁRBOL
La clase TreeNode
Representa un node de un árbol
Es similar al Nodo de lista doble (left y right)
public class TreeNode
{ Referencia al hijo
private Object value; izquierdo
private TreeNode left;
private TreeNode right; Referencia al hijo
... derecho
LUIS F. AGUAS B. 8
LA CLASE TREENODE 2
... ... ...
// Constructores:
public TreeNode (Object v)
{ value = v; left = null; right = null; }
public TreeNode (Object v, TreeNode lt, TreeNode rt)
{ value = v; left = lt; right = rt; }
// Métodos:
public Object getValue () { return value; }
public TreeNode getLeft () { return left; }
public TreeNode getRight () { return right; }
public void setValue (Object v) { value = v; }
public void setLeft (TreeNode lt) { left = lt; }
public void setRight (TreeNode rt) { right = rt; }
}
LUIS F. AGUAS B. 9
TREENODE EJEMPLO 1
public int countNodes (TreeNode root)
{
if (root == null) Caso base
return 0;
else
return 1 + countNodes ( [Link] ( ) ) +
countNodes ( [Link] ( ) );
}
Para root
LUIS F. AGUAS B. 10
ÁRBOLES Y RECURSIÓN
La estructura árbol es recursiva por naturaleza,
los lados derechos e izquierdo son árboles
también.
public void traverse (TreeNode root)
{
if (root != null)
{
visit (root);
for (... <each child of the root> )
traverse (< that child’s subtree>);
}
}
LUIS F. AGUAS B. 11
RECORRIDO PREORDEN
Preorden: primero visita la raíz, entonces
atraviesa la izquierda, y luego atraviesa el
subarbol derecho
private void traversePreorder (TreeNode root) A
{ / \
if (root != null) B C
{ / \
visit ([Link]()); D E
traversePreorder ([Link]());
traversePreorder ([Link]()); ABDEC
}
}
LUIS F. AGUAS B. 12
RECORRIDO POSORDEN
Posorden: primero atraviesa la izquierda
entonces atraviesa el subarbol izquierdo,
entonces visita la raíz.
private void traversePostorder (TreeNode root) A
{ / \
if (root != null) B C
{ / \
traversePostorder ([Link]()); D E
traversePostorder ([Link]());
process ([Link]()); DEBCA
}
}
LUIS F. AGUAS B. 13
RECORRIDO INORDEN
Inorden: primero atraviesa el subarbol izquierdo,
entonces visita la raíz, entonces atraviesa el
subarbol derecho
A
private void traverseInorder (TreeNode root) / \
{ B C
if (root != null) / \
{ D E
traverseInorder ([Link]());
process ([Link]());
DBEAC
traverseInorder ([Link]());
}
}
LUIS F. AGUAS B. 14
ÁRBOL CON ESTRUCTURAS NODO
A D
LUIS F. AGUAS B. 15
1 // Fig. 20.17: [Link]
2 // Declaration of class TreeNode and class Tree.
3 package [Link].jhtp5.ch20;
4
5 // class TreeNode declaration
6 class TreeNode {
7
8 // package access members
9 TreeNode leftNode; Nodo izquierdo y derecho
10 int data;
11 TreeNode rightNode;
12
13 // initialize data and make this a leaf node
14 public TreeNode( int nodeData )
15 {
16 data = nodeData;
17 leftNode = rightNode = null; // node has no children
18 }
19
20 // locate insertion point and insert new node; ignore duplicate values
21 public synchronized void insert( int insertValue )
22 {
Si no se puede ingresar ir a derecho
23 // insert in left subtree
24 if ( insertValue < data ) {
25
26 // insert new TreeNode
27 if ( leftNode == null )
28 leftNode = new TreeNode( insertValue );
29
LUIS F. AGUAS B. 16
30 else // continue traversing left subtree
31 [Link]( insertValue );
32 }
33
34 // insert in right subtree
35 else if ( insertValue > data ) {
36 Si el valor es mayor
37 // insert new TreeNode
enotnces inserte al lado
38 if ( rightNode == null )
39 rightNode = new TreeNode( insertValue );
derecho
40
41 else // continue traversing right subtree
42 [Link]( insertValue );
43 }
44
45 } // end method insert
46
47 } // end class TreeNode
48
49 // class Tree declaration
50 public class Tree {
51 private TreeNode root;
52
53 // construct an empty Tree of integers
54 public Tree()
55 {
56 root = null;
57 }
58
59 // insert a new node in the binary search tree
60 public synchronized void insertNode( int insertValue )
61 {
LUIS F. AGUAS B. 17
62 if ( root == null )
63 root = new TreeNode( insertValue ); // create the root node here
64
65 else
66 [Link]( insertValue ); // call the insert method
67 }
68
69 // begin preorder traversal
70 public synchronized void preorderTraversal()
71 {
72 preorderHelper( root );
73 }
74
75 // recursive method to perform preorder traversal
76 private void preorderHelper( TreeNode node )
77 {
78 if ( node == null )
79 return;
80
81 [Link]( [Link] + " " ); // output node data Recorrido en preorden
82 preorderHelper( [Link] ); // traverse left subtree
83 preorderHelper( [Link] ); // traverse right subtree
84 }
85
86 // begin inorder traversal
87 public synchronized void inorderTraversal()
88 {
89 inorderHelper( root );
90 }
91
LUIS F. AGUAS B. 18
92 // recursive method to perform inorder traversal
93 private void inorderHelper( TreeNode node )
94 {
95 if ( node == null )
96 return;
97
98 inorderHelper( [Link] ); // traverse left subtree
99 [Link]( [Link] + " " ); // output node data
100 inorderHelper( [Link] ); // traverse right subtree
Recorrido inorden
101 }
102
103 // begin postorder traversal
104 public synchronized void postorderTraversal()
105 {
106 postorderHelper( root );
107 }
108
109 // recursive method to perform postorder traversal
110 private void postorderHelper( TreeNode node )
111 {
112 if ( node == null )
113 return;
114
115 postorderHelper( [Link] ); // traverse left subtree
116 postorderHelper( [Link] ); // traverse right subtree Recorrido postorden
117 [Link]( [Link] + " " ); // output node data
118 }
119
120 } // end class Tree
LUIS F. AGUAS B. 19
1 // Fig. 20.18: [Link]
2 // This program tests class Tree.
3 import [Link];
4
5 public class TreeTest {
6
7 public static void main( String args[] )
8 {
9 Tree tree = new Tree();
10 int value;
11
12 [Link]( "Inserting the following values: " );
13
14 // insert 10 random integers from 0-99 in tree
15 for ( int i = 1; i <= 10; i++ ) {
Insertar 10 enteros
16 value = ( int ) ( [Link]() * 100 ); en árbol
17 [Link]( value + " " );
18 [Link]( value );
19 }
20
21 [Link] ( "\n\nPreorder traversal" );
Recorrido preorden
22 [Link](); // perform preorder traversal of tree
23
24 [Link] ( "\n\nInorder traversal" );
Recorrido inorden
25 [Link](); // perform inorder traversal of tree
LUIS F. AGUAS B. 20
ÁRBOL IMPLEMENTACIÓN
26
27 [Link] ( "\n\nPostorder traversal" );
Recorrido postorden
28 [Link](); // perform postorder traversal of tree
29 [Link]();
30 }
31
32 } // end class TreeTest
Inserting the following values:
39 69 94 47 50 72 55 41 97 73
Preorder traversal
39 69 47 41 50 55 94 72 73 97
Inorder traversal
39 41 47 50 55 69 72 73 94 97
Postorder traversal
41 55 50 47 73 72 97 94 69 39
LUIS F. AGUAS B. 21
ÁRBOLES BINARIOS
Árboles binarios
Estructuras de datos donde cada nodo tiene dos
sucesores, a izquierda y a derecha.
Ejemplo
Creación
Inserción
Borrado
Árbol balanceado: un árbol está balanceado cuando la
altura de la trayectoria más corta hacia una hoja no
difiere de la altura de la trayectoria más grande.
Inconveniente de los binarios: se desbalancean
fácilmente.
LUIS F. AGUAS B. 22
ÁRBOLES AVL
Árboles AVL
Árbol binario balanceado en altura (BA(1)) en el que las
inserciones y eliminaciones se efectúan con un mínimo
de accesos.
Árbol balanceado en altura:
Para cada nodo existe un límite en la diferencia que se permite
entre las alturas de cualquiera de los subárboles del nodo
(BA(k)), donde k es el nivel de balance)
Ejemplos:
LUIS F. AGUAS B. 23
ÁRBOLES CARACTERÍSTICAS
Características Árboles binarios paginados
Estructura que debe ser respetada Problemas de almacenamiento
Mantener árbol, rotaciones
secundario, buffering, páginas
de memoria, varios registros
restringidas a un área local del
individuales, minimiza el
árbol número de accesos
Binario: profundos. Búsqueda: Problema: construcción
Log2(N+1)
descendente, como se elige la
AVL: diferencia de 1. Búsqueda: raíz?, cómo va construyendo
1.44 log2(N+2) balanceado?
(búsqueda en el peor caso)
LUIS F. AGUAS B. 24
ÁRBOLES MULTICAMINO Y B
Árboles multicamino
Generalización de árboles binarios, c/nodo tiene k
punteros y k-1 claves (o registros), disminuye la
profundidad del árbol,
Orden del árbol.
Árboles B (balanceados)
Son árboles multicamino con una construcción especial
en forma ascendente que permite mantenerlo
balanceado a bajo costo.
LUIS F. AGUAS B. 25
ÁRBOLES B PROPIEDADES
Propiedades de un árbol B de orden M:
Ningún nodo tiene más de M hijos
C/nodo (menos raíz y los terminales) tienen como mínimo [M/2]
hijos
La raíz tiene como mínimo 2 hijos (o sino ninguno)
Todos los nodos terminales a igual nivel
Nodos no terminales con K hijos contienen K-1 registros. Los
nodos terminales tienen:
Mínimo [M/2] –1 registros
Máximo M – 1 registros
Formato del nodo
PO R1 P1 R2 P2 R3 P3 R4 P4 R5 P5 Nro de registros
LUIS F. AGUAS B. 26
ÁRBOLES OPERACIONES
Definición: nodo adyacente hermano
Dos nodos son adyacentes hermanos si tienen el mismo padre y son apuntados
por punteros adyacentes en el padre.
Operaciones
Búsqueda
Borrado
Creación e inserción
Modificación
LUIS F. AGUAS B. 27
ÁRBOLES: BÚSQUEDA
Búsqueda de información
Comienza desde el nodo raíz
Busca la llave en el nodo
Si no la localiza se toma el puntero anterior a la llave mayor
Si no es puntero nulo se toma ese nodi y se repite del principio. Si es
un puntero nulo el elemento no se encuentra en el árbol.
Performance
Orden M, # de nodos terminales N, N+1 punteros nulos.
Accesos:
Mejor caso: 1 lectura
Pero caso: h lecturas (con h altura del árbol)
LUIS F. AGUAS B. 28
ÁRBOLES: # LECTURAS
Como acotamos h
Nivel # mínimo de descendientes
1 2
2 2 * [M/2]
3 2 * [M/2] * [M/2]
………………………………………………….
h 2 * [M/2]h-1
Relación entre h y # de nodos
N+1 >= 2 * [M/2]h-1
h <= [ 1 + log[M/2] ((N+1)/2) ]
M = 512 y N = 1000000
h <= 3.37 (4 lecturas encuentra un registro)
LUIS F. AGUAS B. 29
ARBOLES ALGORITMOS
Algoritmo (iterativo) Algoritmo (recursivo)
encontro := false (k llave) orden M estruc. del registro
tomar la raíz Record
contador llaves
Repeat llaves (arreglo M-1 elem.)
N nro de elementos nodo hijos (arreglo M elem.)
End
Case Function Busca (Nrr, llave,NRR_encon, Pos_enc)
k = llave del registro Si Nrr = nulo
encontro := true entonces devuelve (‘no encon’)
sino lee nodo apuntado x NRR en página
k < llave( R1) busca la llave en nodo;
P := Po Pos:= Posición donde encuentra o
k > llave (Rn) debería estarla llave
Si encontro llave
P := Pn entonces
otherwise nrr_encon := Nrr (nodo con la llave)
P := Pi (i/ Ri-1 < k <Ri) pos_enc := pos (posición dentro de
EndCase llave)
devuelve (encontrada)
IF P not null then sino {busco en el nivel inferior}
leer nodo apuntado por P devuelve (busca(
Until encontro or P null hijo[pos],llave,
nrr_encon, pos_enc))
Fin S
Fin S
Fin Function
LUIS F. AGUAS B. 30
ÁRBOLES: INSERCIÓN
Inserción (creación)
Los registros se insertan en un nodo Terminal
Casos posibles
El registro tiene lugar en el nodo Terminal (no se produce overflow): solo se hacen
reacomodamientos internos en el nodo
El registro no tiene lugar en el nodo Terminal (se produce overflow): el nodo se
divide y los elementos se reparten entre los nodos, hay una promoción al nivel
superior, y esta puede propagarse y generar una nueva raíz.
LUIS F. AGUAS B. 31
ÁRBOLES: INSERCIÓN
Repeat
Algoritmo (iterativo) IF nodo no esta lleno
{ reg.: reg a insertar Then
fin: inserción finalizada poner reg y reordenar
encontro
encontro: elemento ya está Else
P: puntero al nodo copiar el nodo en N_G
N_G: nodo sobredimensionado insertar reg. en N_G
N : # reg } reg:= centro de N_G
nodo corr.:=1/2 N_G izq
{busco la llave en el árbol}
nodo nuevo:=1/2 N_G der
If encontro If nodo raiz nuevo
Then Informar llave repetida then generar nuevos
Else { insertar elemento } punteros
P := nil Until encontro
encontro := falso
LUIS F. AGUAS B. 32
ÁRBOLES: INSERCIÓN
Algoritmo (recursivo) Si valordevuelto <> promocion
Funcion inserta (Nrr_Actual, llave, entonces devuelve(valordevuelto)
hijo_promo, llave_promo) sino
Si Nrr_Actual = nulo si hay espacio en pagina para llave_p_a
entonces entonces insertar(llave_p_a, nrr_p_a
llave_promo := llave en pagina) promovida abajo
hijo_promo := nulo devuelve (no promocion)
devuelve Promocion (promueve llave
sino divide( llave_p_a, nrr_p_a,
original y nulo)
pagina, llave_promo,
sino
leer página de Nrr_acutal en pagina hijo_promo, página_nueva)
buscar llave en pagina escribe pagina en archivo en
pos := posicion donde deberia estar nrr_actual
en llave escribe pagina_nueva en
Si encuentra llave hijo_promo
entonces devuelve (error) devuelve promoción promociona
valordevuelto := inserta(pagina, Fin Si llave_promo, hijo_promo
hijo[pos], llave, nrr_P_A, fin funcion
llave_P_a)
LUIS F. AGUAS B. 33
DIRECTORIO
Procedimiento Divide (llave_i, nrr_i, Performance
pagina, llave_promo, hijo_promo,
pagina_nueva ) Mejor caso (sin overflow)
copiar pagina + llave a un nodo que H lecturas
pueda contener a todas las llaves. 1 escritura
insertar llave_i, nrr_i en los
lugares correctos de la pagina Peor caso (overflow hasta la
crear una nueva pagina para raíz, aumenta en uno el nivel
pagina_nueva
asignar a llave_promo el valor de la del árbol)
llave de enmedio de la pagina grande H lecturas
asignar a hijo_d_promo el nrr de 2h+1 escrituras (dos por nivel
pagina_nueva
copiar las llaves y apuntadores que más la raíz)
preceen a llave_promo en pagina Estudios realizados
idem posteriores pagina_nueva M = 10 25% divisiones
fin procedimiento
M = 100 2% divisiones
LUIS F. AGUAS B. 34
ÁRBOLES: ELIMINACIÓN
Eliminación
Mejor caso: borra un elemento del nodo y no produce
underflow, solo reacomodos ( # elementos >= [M/2]-1
Peor caso: se produce underflow, #elementos < [M/2] –
1
Eliminar
Nodo Terminal
Nodo no Terminal ( llevar a un nodo Terminal)
Dos soluciones
Redistribuir
concatenar
LUIS F. AGUAS B. 35
ÁRBOLES: REDISTRIBUIR
Redistribuir
Cuando un nodo tiene underflow puede trasladarse llaves de un nodo adyacente
hermano (en caso que este tenga suficientes elementos)
Concatenación:
Si un nodo adyacente hermano está al mínimo (no le sobra ningún elemento) no se
puede redistribuir, se concatena con un nodo adyacente disminuyendo el # de
nodos (y en algunos casos la altura del árbol)
LUIS F. AGUAS B. 36
ÁRBOLES: PERFORMANCE
Performance
Mejor caso (borra de un nodo Terminal)
H lecturas
1 escritura
Peor caso (concatenación lleva a decrementar el nivel del árbol en 1)
2h – 1 lecturas
H + 1 escrituras
LUIS F. AGUAS B. 37
ÁRBOLES: ELIMINACIÓN
Algoritmo de eliminación (iterativo) copiar ady y nodo actual en n_g
{ fin: indica fin del borrado dividir n_g
n_g:nodo tamaño mayor al normal promover nueva llave a padre
ady: nodo adyacente hermano armar nodo actual y ady con la
reg: reg. a borrar} mitad de n_g en c/u
{buscar reg en el árbol } fin := true
If reg no está en un nodo terminal else {concatenar}
then elegir el mejor ady para concat.
buscar el sucesor de reg en un poner ady y nodo actual juntos y
nodo terminal acoplarle elemnto nodo padre
intercalar reg con su sucesor eliminar nodo que sobra y producir
{ eliminación de reg } enganches
fin := falso nuevo reg elemento que bajo nodo
repeat padra y que debemos eliminar
remover reg y el puntero asociado Until fin
If nodo corriente > [M/2] -1 elem. IF no hay registro en la raiz
then fin := true then
else if es posible redistribuir nueva raiz nodo corriente
then {redistribuir}{ady.>min.} liberar vieja raíz
LUIS F. AGUAS B. 38
CAPITULO 8
PREGUNTAS Y RESPUESTAS
LUIS F. AGUAS B. 39