Outline Árboles Árboles Binarios Árboles binarios Java Inserción de un nodo Eliminación de un nodo Árboles Roberto Carlos Abreu Dı́az October 28, 2009 Roberto Carlos Abreu Dı́az Árboles Outline Árboles Árboles Binarios Árboles binarios Java Inserción de un nodo Eliminación de un nodo 1 Árboles 2 Árboles Binarios 3 Árboles binarios Java Código Java para búsqueda 4 Inserción de un nodo Código Java para inserción 5 Eliminación de un nodo Caso 1 Caso 2 Caso 3 Roberto Carlos Abreu Dı́az Árboles Outline Árboles Árboles Binarios Árboles binarios Java Inserción de un nodo Eliminación de un nodo Árboles Definición Un árbol consiste de nodos conectados entre sı́ por ejes. Roberto Carlos Abreu Dı́az Árboles Outline Árboles Árboles Binarios Árboles binarios Java Inserción de un nodo Eliminación de un nodo Terminologı́a Camino: una secuencia de pasos para llegar desde un nodo A hasta un nodo B. Raı́z: es el nodo en el tope de un árbol, no tiene padre y sólo puede haber una raı́z. Padre e hijo: si A y B están conectados y B está por encima de A, B es el padre de A y A es el hijo de B. Hoja: Es un nodo que no tiene hijos. Sub-árbol: Cualquier nodo puede ser considerado la raı́z de un sub-árbol. Nivel: a cuántas generaciones un nodo está de la raı́z. Llave: campo de data. Recorrido: visitar los nodos de un árbol en cierto orden. Roberto Carlos Abreu Dı́az Árboles Outline Árboles Árboles Binarios Árboles binarios Java Inserción de un nodo Eliminación de un nodo Árboles Binarios Definición Si cada nodo en un árbol puede tener a lo sumo dos hijos, el árbol es llamado árbol binario. Los dos hijos de cada nodo se llaman hijo izquierdo e hijo derecho. Los nombres corresponden a sus posiciones al dibujarlos. Nota El tipo de árbol binario con el que estaremos trabajando se llama árbol binario de búsqueda. Estos se caracterizan porque el hijo izquierdo de un nodo debe tener una llave menor que la de su padre, y el hijo derecho de un nodo debe tener una llave mayor o igual a su padre. Roberto Carlos Abreu Dı́az Árboles Outline Árboles Árboles Binarios Árboles binarios Java Inserción de un nodo Eliminación de un nodo Código Java para búsqueda Código Java para árboles binarios c l a s s Node { i n t d a t a ; // l l a v e p r i v a t e Node l e f t C h i l d ; // h i j o i z q u i e r d o p r i v a t e Node r i g h t C h i l d ; // h i j o d e r e c h o } class BinaryTree { p r i v a t e Node r o o t ; // r aı́ z // y l a s o p e r a c i o n e s c o r r e s p o n d i e n t e s . . . } Roberto Carlos Abreu Dı́az Árboles Outline Árboles Árboles Binarios Árboles binarios Java Inserción de un nodo Eliminación de un nodo Código Java para búsqueda Búsqueda de un elemento Roberto Carlos Abreu Dı́az Árboles Outline Árboles Árboles Binarios Árboles binarios Java Inserción de un nodo Eliminación de un nodo Código Java para búsqueda Búsqueda de un elemento Aprovecha el orden en que los nodos están organizados para buscar los elementos. Roberto Carlos Abreu Dı́az Árboles Outline Árboles Árboles Binarios Árboles binarios Java Inserción de un nodo Eliminación de un nodo Código Java para búsqueda Búsqueda de un elemento Aprovecha el orden en que los nodos están organizados para buscar los elementos. Como un nodo tiene a lo sumo un hijo izquierdo menor que él y un hijo derecho mayor que él, el algoritmo se mueve recursivamente por los sub-árboles hasta que encuentre el nodo con la llave. El dice: si estoy en un nodo y la llave no es la buscada, si la llave buscada es menor entonces visita su hijo izquierdo. De lo contrario, visita su hijo derecho. Roberto Carlos Abreu Dı́az Árboles Outline Árboles Árboles Binarios Árboles binarios Java Inserción de un nodo Eliminación de un nodo Código Java para búsqueda Búsqueda de un elemento Aprovecha el orden en que los nodos están organizados para buscar los elementos. Como un nodo tiene a lo sumo un hijo izquierdo menor que él y un hijo derecho mayor que él, el algoritmo se mueve recursivamente por los sub-árboles hasta que encuentre el nodo con la llave. El dice: si estoy en un nodo y la llave no es la buscada, si la llave buscada es menor entonces visita su hijo izquierdo. De lo contrario, visita su hijo derecho. Consecuentemente, si aterriza a una dirección nula, esto significa que el nodo buscado no existe en el árbol. Roberto Carlos Abreu Dı́az Árboles Outline Árboles Árboles Binarios Árboles binarios Java Inserción de un nodo Eliminación de un nodo Código Java para búsqueda Código Java para búsqueda p u b l i c Node f i n d ( i n t k e y ) { Node c u r r = r o o t ; w h i l e ( c u r r . d a t a != k e y ) { i f ( key < c u r r . data ) curr = curr . leftChild ; else curr = curr . rightChild ; i f ( c u r r == n u l l ) return n u l l ; } return c u r r ; } Roberto Carlos Abreu Dı́az Árboles Outline Árboles Árboles Binarios Árboles binarios Java Inserción de un nodo Eliminación de un nodo Código Java para inserción Inserción de un nodo Roberto Carlos Abreu Dı́az Árboles Outline Árboles Árboles Binarios Árboles binarios Java Inserción de un nodo Eliminación de un nodo Código Java para inserción Inserción de un nodo Para insertar un nodo, primero debemos averiguar dónde corresponde en el árbol. (¡Wao!) Roberto Carlos Abreu Dı́az Árboles Outline Árboles Árboles Binarios Árboles binarios Java Inserción de un nodo Eliminación de un nodo Código Java para inserción Inserción de un nodo Para insertar un nodo, primero debemos averiguar dónde corresponde en el árbol. (¡Wao!) El código prácticamente es el mismo que el de buscar un nodo (no existente). No existente porque en ese espacio libre es que se colocará el nuevo nodo. Roberto Carlos Abreu Dı́az Árboles Outline Árboles Árboles Binarios Árboles binarios Java Inserción de un nodo Eliminación de un nodo Código Java para inserción Código Java para inserción p u b l i c v o i d i n s e r t ( Node newNode ) { // E s t e e s e l c a s o base , // donde e l á r b o l e s t á v a cı́ o i f ( r o o t == n u l l ) { r o o t = newNode ; return ; } // p a r t e dos en p r ó x i m o s l i d e Roberto Carlos Abreu Dı́az Árboles Outline Árboles Árboles Binarios Árboles binarios Java Inserción de un nodo Eliminación de un nodo Código Java para inserción Código Java para inserción Node c u r r = r o o t , p a r e n t ; while ( true ) { parent = c u r r e n t ; i f ( newNode . d a t a < c u r r . d a t a ) { curr = curr . leftChild ; i f ( c u r r == n u l l ) { p a r e n t . l e f t C h i l d = newNode ; r e t u r n ; } } else { curr = curr . rightChild ; i f ( c u r r == n u l l ) { p a r e n t . r i g h t C h i l d = newNode ; r e t u r n ; } } }} Roberto Carlos Abreu Dı́az Árboles Outline Árboles Árboles Binarios Árboles binarios Java Inserción de un nodo Eliminación de un nodo Caso 1 Caso 2 Caso 3 Eliminación de un nodo Acerca de la eliminación Hay varios casos a considerar al eliminar un nodo. ¿Qué hacer con los hijos de ese nodo? Se distinguen tres casos base: El nodo a eliminar es una hoja El nodo a eliminar tiene un hijo El nodo a eliminar tiene dos hijos Todos sin embargo tienen algo en común: utilizan una función de búsqueda similar a las de buscar e insertar. Roberto Carlos Abreu Dı́az Árboles Outline Árboles Árboles Binarios Árboles binarios Java Inserción de un nodo Eliminación de un nodo Caso 1 Caso 2 Caso 3 CASO 1: el nodo es hoja Es el caso más sencillo Simplemente se fija a null el hijo apropiado del padre de ese nodo En Java, el Garbage Collector se encarga del resto En este ejemplo, el nodo con la llave 9 es el padre. Se harı́a: nodoPadre.rightChild = null; Roberto Carlos Abreu Dı́az Árboles Outline Árboles Árboles Binarios Árboles binarios Java Inserción de un nodo Eliminación de un nodo Caso 1 Caso 2 Caso 3 p u b l i c boolean d e l e t e ( i n t k e y ) { Node c u r r = r o o t ; Node p a r e n t = r o o t ; boolean i s L e f t = t r u e ; w h i l e ( c u r r . d a t a != k e y ) { parent = curr ; i f ( key < c u r r . data ){ i s L e f t = true ; curr = curr . leftChild ; } else { isLeft = false ; curr = curr . rightChild ; } Roberto Carlos Abreu Dı́az Árboles i f ( c u r r == n u l l ) return f a l s e ; } // end w h i l e i f ( NoChild ( c u r r )){ i f ( c u r r == r o o t ) root = null ; else i f ( i s L e f t ) parent . l e f t C h i l d = null ; else parent . rightChild = null ; } Outline Árboles Árboles Binarios Árboles binarios Java Inserción de un nodo Eliminación de un nodo Caso 1 Caso 2 Caso 3 CASO 2: el nodo a eliminar tiene un hijo Este caso es relativamente sencillo también El nodo tiene a lo sumo dos conexiones: Una con su padre y una con su hijo El objetivo es reemplazar al nodo en el padre con su hijo O sea, si 9 se va a eliminar, el objetivo es fijar a 6 como el rightChild de 4 Roberto Carlos Abreu Dı́az Árboles Outline Árboles Árboles Binarios Árboles binarios Java Inserción de un nodo Eliminación de un nodo Caso 1 Caso 2 Caso 3 // c o n t i n u a c i o n . . . e l s e i f ( c u r r . r i g h t C h i l d == n u l l ) { i f ( c u r r == r o o t ) r o o t = r o o t . l e f t C h i l d ; else i f ( i s L e f t ) parent . l e f t C h i l d = curr . l e f t C h i l d ; else parent . rightChild = curr . l e f t C h i l d ; e l s e i f ( c u r r . l e f t C h i l d == n u l l ) i f ( c u r r == r o o t ) r o o t = r o o t . r i g h t C h i l d ; else i f ( i s L e f t ) parent . l e f t C h i l d = curr . rightChild ; else parent . rightChild = curr . rightChild ; Roberto Carlos Abreu Dı́az Árboles Outline Árboles Árboles Binarios Árboles binarios Java Inserción de un nodo Eliminación de un nodo Caso 1 Caso 2 Caso 3 CASO 3: el nodo a eliminar tiene dos hijos Si tiene, no se puede reemplazar simplemente con uno de sus hijos (por lo menos cuando el hijo también tiene hijos). El objetivo es reemplazar al nodo por su sucesor. Especı́ficamente, su sucesor En-Orden. Éste es el nodo más pequeño del conjunto de nodos que son mayores que el nodo a eliminar. Roberto Carlos Abreu Dı́az Árboles Outline Árboles Árboles Binarios Árboles binarios Java Inserción de un nodo Eliminación de un nodo Caso 1 Caso 2 Caso 3 p r i v a t e node g e t S u c c e s s o r ( Node node ) { Node p a r e n t = node , s u c c e s s o r = node , c u r r e n t = node . r i g h t C h i l d ; w h i l e ( c u r r e n t != n u l l ) { parent = successor ; successor = current ; current = currente . leftChild ; } i f ( s u c c e s s o r != node . r i g h t C h i l d ) { parent . l e f t C h i l d = successor . rightChild ; s u c c e s s o r . r i g h t C h i l d = node . r i g h t C h i l d ; } return s u c c e s s o r ; } Roberto Carlos Abreu Dı́az Árboles Outline Árboles Árboles Binarios Árboles binarios Java Inserción de un nodo Eliminación de un nodo Caso 1 Caso 2 Caso 3 // c o n t i n u a c i o n else { Node s u c c e s s o r = g e t S u c c e s s o r ( c u r r e n t ) ; i f ( c u r r == r o o t ) root = successor ; else i f ( i s L e f t ) parent . l e f t C h i l d = successor ; else parent . rightChild = successor ; successor . leftChild = curr . leftChild ; } return true ; } // end d e l e t e Roberto Carlos Abreu Dı́az Árboles