You are on page 1of 26

rboles

Organizacin Jerrquica con rboles


Un rbol es un grupo finito de nodos, donde uno de esos nodos sirve como raz y el resto de los nodos se organizan debajo de la raz de una forma jerrquica. Un nodo que referencia un nodo debajo suyo es un nodo padre. De forma similar, un nodo referenciado por un nodo encima de l, es un nodo hijo. Los nodos sin hijos, son nodos hoja. Un nodo podra ser un padre e hijo, o un nodo hijo y un nodo hoja. Un nodo padre podra referenciar tantos hijos como sea necesario. En muchas situaciones, los nodos padre slo referencian un mximo de dos nodos hijos. Los rboles basados en dichos nodos son conocidos como arboles binarios. La siguiente figura representa un rbol binario que almacena siete palabras en orden alfabtico.

Insertar nodos, borrar nodos, y atravesar los nodos en rboles binarios o de otros tipos se realiza mediante la recursin (vea el captulo siguiente). Por brevedad, no entraremos en los algoritmos recursisvos de insercin, borrado y movimiento por los nodos. En su lugar, presentar el cdigo fuente de una aplicacin de contaje de palabras para demostrar la insercin y el movimiento por los nodos. Este cdigo utiliza insercin de nodos para crear un rbol binario, donde cada nodo contiene una palabra y un contador de ocurrencias de esa palabra, y muestra estas palabras y contadores en orden alfabtico mediante una variante del algoritmo de movimiento por rboles move-left-examine-node-move-right: // WC.java import java.io.*; class TreeNode { String word; int count = 1; TreeNode left; TreeNode right; // // // // Word being stored. Count of words seen in text. Left subtree reference. Right subtree reference.

public TreeNode (String word) { this.word = word; left = right = null; } public void insert (String word) { int status = this.word.compareTo (word); word if (status > 0) { // word argument precedes current

node as searching left.

// If left-most leaf node reached, then insert new // its left-most leaf node. Otherwise, keep if (left == null) left = new TreeNode (word); else left.insert (word); } else if (status < 0) { // word argument follows current

word new node as searching right.

// If right-most leaf node reached, then insert // its right-most leaf node. Otherwise, keep if (right == null) right = new TreeNode (word); else right.insert (word); } else } } class WC { public static void main (String [] args) throws IOException int ch; TreeNode root = null; // Read each character from standard input until a letter // is read. This letter indicates the start of a word. while ((ch = System.in.read ()) != -1) { // If character is a letter then start of word if (Character.isLetter ((char) ch)) { // Create StringBuffer object to hold word StringBuffer sb = new StringBuffer (); // Place first letter character into StringBuffer object. sb.append ((char) ch); // Place all subsequent letter characters into StringBuffer // object. do { ch = System.in.read (); if(Character.isLetter ((char) ch)) sb.append((char) ch); else break; } { this.count++;

detected.

letters.

while (true); // Insert word into tree. if (root == null) root = new TreeNode (sb.toString ()); else root.insert (sb.toString ()); } } display (root);

static void display (TreeNode root) { // If either the root node or the current node is null, // signifying that a leaf node has been reached, return. if (root == null) return; // Display all left-most nodes (i.e., nodes whose words // precede words in the current node). display (root.left); // Display current node's word and count. System.out.println ("Word = " + root.word + ", Count = " + root.count); // Display all right-most nodes (i.e., nodes whose words // follow words in the current node). display (root.right); } }

Como tiene muchos cometarios no explicar el cdigo. En su lugar le sugiero que juegue con esta aplicacin de esta forma: cuente el nmero de palabras de un fichero, lance una lnea de comandos que incluya el smbolo de redireccin <. Por ejemplo, cuente el nmero de palabras en WC.java lanzando java WC <WC.java. Abajo puede ver un extracto de la salida de este comando: Word Word Word Word Word Word Word Word Word Word Word Word Word Word = = = = = = = = = = = = = = Character, Count = 2 Count, Count = 2 Create, Count = 1 Display, Count = 3 IOException, Count = 1 If, Count = 4 Insert, Count = 1 Left, Count = 1 Otherwise, Count = 2 Place, Count = 2 Read, Count = 1 Right, Count = 1 String, Count = 4 StringBuffer, Count = 5

Recursin
La ciencia de la computacin hace tiempo que descubri que se puede reemplazar a un mtodo que utiliza un bucle para realizar un clculo con un mtodo que se llame repetidamente a s mismo para realizar el mismo clculo. El echo de que un mtodo se llame repetidamente a s mismo se conoce como recursion.

La recursin trabaja dividiendo un problema en subproblemas. Un programa llama a un mtodo con uno o ms parmetros que describen un problema. Si el mtodo detecta que los valores no representan la forma ms simple del problema, se llama a s mismo con valores de parmetros modificados que describen un subproblema cercano a esa forma. Esta actividad contina hasta que el mtodo detecta la forma ms simple del problema, en cuyo caso el mtodo simplemente retorna, posiblemente con un valor, si el tipo de retorno del mtodo no es void. La pila de llamadas a mtodo empieza a desbobinarse como una llamada a mtodo anidada para ayudar a completar una evaluacin de expresin. En algn punto, la llamada el mtodo original se completa, y posiblemente se devuelve un valor. Para entender la recursin, consideremos un mtodo que suma todos los enteros desde 1 hasta algn lmite superior: static int sum (int limit) { int total = 0; for (int i = 1; i <= limit; i++) total += i; return total; } Este mtodo es correcto porque consigue el objetivo. Despus de crear una variable local total e inicializarla a cero, el mtodo usa un bucle for para sumar repetidamente enteros a total desde 1 hasta el valor del parmetro limit. Cuando la suma se completa, sum(int limit) devuelve el total, mediante return total;, a su llamador. La recursin hace posible realizar est suma haciendo que sum(int limit) se llame repetidamente a s mismo, como demuestra el siguiente fragmento de cdigo: static int sum (int limit) { if (limit == 1) return 1; else return limit + sum (limit - 1); } Para entender como funciona la recursin, considere los siguientes ejemplos:

1. sum (1): El mtodo detecta que limit contiene 1 y vuelve. 2. sum (2): Como limit contiene 2, se ejecuta return limit + sum (limit - 1);. 3.
Lo que implica que se ejecute return 2 + sum (1);. La llamada a sum (1) devuelve 1, lo que hace que return 2 + sum (1); devuelva 3. sum (3): Como limit contiene 3, se ejecuta return limit + sum (limit - 1);. Esto implica que se ejecute return 3 + sum (2);. La llamada a sum (2) ejecuta return 2 + sum (1);. Luego, sum (1) devuelve 1, lo que hace que sum (2) devuelva 3, y al final return 3 + sum (2); devuelve 6.

Cuidado: Asegurese siempre que un mtodo recursivo tiene una condicin de parada (como if (limit == 1) return 1;). Por el contrario, la recursin continuar hasta que se sobrecargue la pila de llamadas a mtodos.

Conceptos y Terminologa bsica


Si vamos a es que es rbol:

trabajar con un rbol.

rboles, lo primero que Aqu tenemos algunas

tenemos que ver definiciones para

Un rbol es una estructura de datos no lineal y homognea en el que cada elemento puede tener varios elementos posteriores, pero tan slo puede tener un elemento anterior. Es una estructura jerrquica aplicada sobre una coleccin de elementos u objetos llamados nodos; de los cuales uno es conocido como raz. Adems se crea una relacin o parentesco entre los nodos dando lugar a trminos como padre, hijo, hermano, antecesor, sucesor, ancestro, etc. Un rbol es una estructura compuesta por un dato y varios rboles. Dado un nodo cualquiera de la estructura, podemos considerarlo como una estructura independiente. Es decir, un nodo cualquiera puede ser considerado como la raz de un rbol completo. Son estructuras dinmicas no lineales. Dinmicas porque las estructuras de rbol pueden cambiar durante la ejecucin de un programa. No lineales, puesto que a cada elemento del rbol pueden seguirle varios elementos. En las estructuras de datos lineales cada elemento tiene un nico elemento anterior y un nico elemento posterior.

El tipo de estructura ms general son los grafos. En un grafo cada elemento puede tener varios elementos anteriores y varios elementos posteriores. Los rboles no son ms que un tipo especial de grafo en el que cada elemento puede tener varios elementos posteriores, pero tan slo puede tener un elemento anterior. Tanto grafos como rboles son estructuras no lineales. Creo que la mayora, sino es que todos, hemos utilizado los rboles cuando hemos hecho un rbol genealgico o alguna estructura jerrquica de alguna organizacin. Y que me dicen de la forma en la que organizamos la informacin en nuestras maquinas (se hace en una estructura de directorios y subdirectorios en forma de rbol, para facilitar su bsqueda). Talvez sin darnos cuenta, pero hemos manejado el concepto de rbol Adems de la definicin debemos conocer otros importantes, pues estos pudieran ser tiles a la un rbol: En relacin con otros nodos:

conceptos hora de

bastante codificar

Nodo padre. Nodo que contiene un puntero al nodo actual. En un rbol un nodo solo puede tener un nodo padre. X es padre de

Y s y solo s el nodo X apunta a Y. Tambin se dice que X es antecesor de Y. En la Figura 1: B es padre de E y F. Nodo hijo. Cualquiera de los nodos apuntados por uno de los nodos del rbol. Un nodo puede tener varios hijos. X es hijo de Y, s y solo s el nodo X es apuntado por Y. Tambin se dice que X es descendiente directo de Y. En la Figura 1: E es hijo de B. Hermano. Dos nodos sern hermanos si son descendientes directos de un mismo nodo. En la Figura 1: E y F son hermanos.

En cuanto a la posicin dentro del rbol:

Nodo raz. Es el nico nodo del rbol que no tiene padre. Este es el nodo que usaremos para referirnos al rbol. En la Figura 1 A es el nodo raz. Nodo hoja. Nodo que no tiene hijos. Se le llama hoja o terminal a aquellos nodos que no tienen ramificaciones (hijos). En la Figura 1 N es un nodo hoja. Nodo interior. Es un nodo que no es raz ni hoja. En la Figura 1 D es un nodo interior. que definen las caractersticas del rbol,

Existen otros conceptos en relacin a su tamao:

Orden. Es el nmero potencial de hijos que puede tener cada elemento de rbol. De este modo, diremos que un rbol en el que cada nodo puede apuntar a otros dos es de orden dos, si puede apuntar a tres ser de orden tres, etc. Podramos decir que nuestro rbol de ejemplo (Figura 1) es de orden tres. Grado. El nmero de hijos que tiene el elemento con ms hijos dentro del rbol. En el rbol del ejemplo, el grado es tres, ya que tanto A como D tienen tres hijos, y no existen elementos con ms de tres hijos. Nivel. Se define para cada elemento del rbol como la distancia a la raz, medida en nodos. El nivel de la raz es cero, el de sus hijos uno y as sucesivamente. En el ejemplo, el nodo D tiene nivel 1, el nodo G tiene nivel 2, y el nodo N nivel 3. Altura. La altura de un rbol se define como el nivel del nodo de mayor nivel. Como cada nodo de un rbol puede considerarse a su vez como la raz de un rbol, tambin podemos hablar de altura de ramas; el mximo nmero de nodos que hay que recorrer para llegar de la raz a una de las hojas. El rbol de la Figura 1 tiene altura 3, la rama B tiene altura 2, la rama G tiene altura 1, la N cero. Peso. Es el nmero de nodos del rbol sin contar la raz. Camino. Es una secuencia de nodos, en el que dos nodos consecutivos cualesquiera son padre e hijo. En el ejemplo A-D-H y A-C-G-M son caminos.

Longitud de camino. Es el nmero de arcos que deben ser recorridos para llegar desde la raz al nodo X. Por definicin la raz tiene longitud de camino 1, y sus descendientes directos longitud de camino 2 y as sucesivamente. En nuestro rbol de ejemplo G tiene longitud de camino 3 y N tiene longitud de camino 4. Rama. Es el camino desde el nodo raz a una hoja. En el ejemplo A-B-E-K y A-B-F son ramas.

Figura 1. rbol de grado tres Los rboles tienen una gran variedad de aplicaciones. Por ejemplo, se pueden utilizar para representar frmulas matemticas, para organizar adecuadamente la informacin, para construir un rbol genealgico, para el anlisis de circuitos elctricos, para numerar los captulos y secciones de un libro, etc. Bueno y como dijimos que lo que se vera aqu es rboles binarios pues yo creo que mejor nos vamos centrando en estos

rboles binarios
Los rboles de orden dos son bastante especiales. Estos rboles se conocen tambin como rboles binarios, ya que cada nodo del rbol no tendr ms de dos descendientes directos. Algunas definiciones pueden ser:

Un rbol binario es un rbol de grado 2. Un rbol binario es aquel que: o Es vaco, o Esta formado por un nodo cuyos subrboles izquierdo y derecho son a su vez rboles binarios.

Figura 2. Ejemplo de un rbol binario En alguna de las definiciones del inicio del documento, la tercera para ser precisos, se utiliza la recursin para definir un rbol porque representa la forma ms apropiada y porque adems es una caracterstica inherente de los mismos. En cualquier rbol, no slo en los binarios, si eliminamos el nodo raz, obtenemos dos rboles; en el caso de que sea un rbol binario. Aquel que colgaba del enlace izquierdo del nodo raz se denomina subrbol izquierdo y aquel que colgaba del enlace derecho se denomina subrbol derecho. Adems, en un rbol binario, todos los subrboles son tambin rboles binarios. De hecho, a partir de cualquier nodo de un rbol podemos definir un nuevo rbol sin ms que considerarlo como su nodo raz. Por tanto, cada nodo tiene asociados un subrbol derecho y uno izquierdo. Existen dos tipos de rboles binarios que se en funcin de ciertas propiedades. Estos son los siguientes: 1. rbol binario equilibrado 2. rbol binario completo rbol binario equilibrado Es un rbol propiedad: en el que en todos sus nodos se cumple la siguiente consideran especiales

| altura(subrbol_izquierdo) altura(subrbol_derecho) | <= 1

Figura 3. rbol equilibrado

Figura 4. rbol binario completo

rbol

NO

equilibrado

Es un rbol en el que todos los nodos tienen dos hijos y todas las hojas estn en el mismo nivel. Se denomina completo porque cada nodo, excepto las hojas, tiene el mximo de hijos que puede tener.

Figura 5. Recorridos por rboles

rbol

binario

completo

Una de las cosas que debemos poder hacer con un rbol es poder movernos a travs de la informacin que este contiene. El modo evidente de moverse a travs de las ramas de un rbol es siguiendo las referencias de los nodos que las componen. Los recorridos dependen en gran medida del tipo y propsito del rbol, pero hay ciertos recorridos que usaremos frecuentemente. Se trata de aquellos recorridos que incluyen todo el rbol.

Hay tres formas de recorrer un rbol completo, y las tres se suelen implementar mediante recursividad. En los tres casos se sigue siempre a partir de cada nodo todas las ramas una por una. Estos tres casos son:

Pre-orden In-orden Post-orden

Recorrido Pre-orden (N I D) En este recorrido lo primero que se obtiene o evala es el nodo, antes de recorrer las ramas; posteriormente se recorre la rama izquierda y finalmente la rama derecha. El orden es: Nodo Izquierda Derecha (N I D). El recorrido Pre-orden de nuestro rbol de la Figura 3 es: M E A R O N Q V Y el recorrido Pre-orden del rbol de la Figura 5 es: N E A G R O V Recorrido In-orden (I N D) En este recorrido se procesa la primera rama (rama izquierda), despus el nodo y finalmente la ultima rama (rama derecha). El orden es: Izquierda Nodo Derecha (I N D). El recorrido In-orden de nuestro rbol de la Figura 3 es: A E M N O Q R V Y el recorrido In-orden del rbol de la Figura 5 es: A E G N O R V Recorrido Post-orden (I D R) En este recorrido se primero se procesan las ramas procesar el nodo. El orden de este Izquierda Derecha Nodo (I D N). para finalmente recorrido es:

El recorrido Post-orden del rbol de la Figura 3 es: A E N Q O V R M Y el recorrido Post-orden del rbol de la Figura 5 es: A G E O V R N Y como se que a la mayora de nosotros no nos agrada mucho la teora, aunque sea muy necesaria :-), pues vamos viendo algo prctico.

Implementaciones del rbol binario


Para poder implementar un rbol binario primero debemos definir la estructura de los nodos. Cada nodo del rbol estar formado por tres partes:

La informacin contenida en el nodo, la cual puede ser un tipo primitivo o puede ser cualquier tipo de objeto. Un enlace al hijo derecho (raz del subrbol derecho) Un enlace al hijo izquierdo (raz del subrbol izquierdo)

Grficamente:

Figura 6. Nodo de un rbol binario Frecuentemente, aunque tampoco es estrictamente necesario, para hacer ms fcil moverse a travs del rbol, aadiremos un puntero a cada nodo que apunte al nodo padre. De este modo podremos avanzar en direccin a la raz, y no slo hacia las hojas. Si implementamos este puntero nuestro nodo estara compuesto por cuatro partes:

Un enlace al padre del nodo. La informacin contenida en el nodo, la cual puede ser un tipo primitivo o puede ser cualquier tipo de objeto. Un enlace al hijo derecho (raz del subrbol derecho) Un enlace al hijo izquierdo (raz del subrbol izquierdo)

Grficamente:

Figura 7. Nodo de un rbol binario con referencia hacia su padre Los rboles pueden ser construidos con estructuras estticas y dinmicas. Las estticas son arreglos, registros y conjuntos, mientras que las dinmicas estn representadas por listas.

Implementacin dinmica de un rbol binario


Si aadimos a los rboles la restriccin de que cada elemento puede tener un solo posterior, llegamos a las estructuras lineales, y ms concretamente a las listas. As pues, las listas no son ms que un caso particular de los rboles. En este punto, si aadimos

ciertas restricciones de acceso a las listas llegamos a o a las pilas. Por lo tanto, tanto colas como pilas, particulares de listas. As que se han implementado dinmica lo que vamos a ver debe ser fcil. Y como reciclar el cdigo que generamos para el rbol dentro ser ms parecido a una lista doblemente ligada. La estructura Figura 7 de nuestro y el nodo sigue mostrado siendo en

las colas son tipos una lista vamos a del vector de la figura:

la misma que la la siguiente

Figura 15. Nodo de un rbol binario con referencia hacia su padre Solo que en este caso las referencias hacia el padre, el hijo izquierdo y el hijo derecho son apuntadores hacia objetos (objetos nodo iguales al mostrado en la figura), de modo que al formar nuestro rbol dinmico se armara una estructura ms o menos parecida a la mostrada en la figura:

Figura 16. Estructura del rbol dinmico Bueno, pues entonces vamos a ver la definicin en Java de la clase que representar nuestro rbol. En esta ocasin no voy a describir los mtodos ya que estamos reciclando el cdigo que se genero para el rbol en el vector, por lo tanto es muy parecido y creo que lo entendern para que sirve cada mtodo si lo relacionan con los mtodos del rbol visto anteriormente

view plaincopy to clipboardprint? 1. 2. 3. 4. 5. 6. 7. 8. 9. package org.neos.arboles.binarios.dinamicos; import java.util.ArrayList; import org.neos.arboles.binarios.dinamicos.beans.Informacion; import org.neos.arboles.binarios.dinamicos.beans.Nodo; import org.neos.arboles.binarios.dinamicos.exceptions.ExceptionElementoDupli cado;

10. 11. import org.neos.arboles.binarios.dinamicos.exceptions.ExceptionNoEncontrado; 12. 13. public class ArbolBinario { 14. 15. private Nodo raiz; 16. 17. private ArrayList recorrido; 18. 19. public ArbolBinario() { 20. 21. this.raiz = null; 22. 23. this.recorrido = null; 24. 25. } 26. 27. public boolean esArbolVacio() { 28. 29. return (null == raiz) ? true : false; 30. 31. } 32. 33. public Nodo obtenerPosicionRaiz() { 34. 35. return raiz; 36. 37. } 38. 39. public boolean existeElemento(Object info) { 40. 41. Nodo nodo = obtenerElemento(info, raiz); 42. 43. if(null != nodo) { 44. 45. return true; 46.

47. 48. 49. 50. 51. 52. 53. 54. 55. 56. 57. 58. 59. 60. 61. 62. 63. 64. 65. 66. 67. 68. 69. 70. 71. 72. 73. 74. 75. 76. 77. 78. 79. 80. 81. 82. 83. 84. 85. 86. 87. 88. 89. 90. 91. 92. 93. 94. 95. 96.

} else { return false; } } public Nodo obtenerElemento(Object info, Nodo raiz) { if(null == raiz) { return raiz; } else { Informacion obj_info = new Informacion(info);

Informacion obj_info_pa = new Informacion( raiz.getInformacion() ); if( obj_info_pa.equals(obj_info) ) { return raiz; } else if( obj_info.compareTo(obj_info_pa) < 0 ) { return obtenerElemento(info, raiz.getIzquierdo()); } else { return obtenerElemento(info, raiz.getDerecho()); } } } public int obtenerNumeroElementos(Nodo nodo) { int num_elems = 0; if(null != nodo) { num_elems += obtenerNumeroElementos(nodo.getIzquierdo()); num_elems++; // contabilizar el nodo visitado num_elems += obtenerNumeroElementos(nodo.getDerecho());

97. 98. 99. 100. 101. 102. 103. 104. 105. 106. 107. 108. 109. 110. 111. 112. 113. 114. 115. 116. 117. 118. 119. 120. 121. 122. 123. 124. 125. 126. 127. 128. 129. 130. 131. 132. 133. 134. 135. 136. 137. 138. 139. 140. 141. 142. 143. 144. 145. 146.

} return num_elems; } public int obtenerPeso(Nodo nodo) { int peso = 0;

int num_h_izq = 0; int num_h_der = 0; if(null != nodo) { num_h_izq = obtenerNumeroElementos(nodo.getIzquierdo()); num_h_der = obtenerNumeroElementos(nodo.getDerecho()); peso = num_h_izq + num_h_der; } return peso; } public int obtenerAltura(Nodo nodo) { int altura = 0;

Nodo ref_h_izq; Nodo ref_h_der; int altura_r_izq = 0; int altura_r_der = 0; if(null != nodo) { altura = 1; ref_h_izq = nodo.getIzquierdo(); ref_h_der = nodo.getDerecho(); if( (ref_h_izq != null) && (ref_h_der != null) ) {

147. 148. 149. 150. 151. 152. 153. 154. 155. 156. 157. 158. 159. 160. 161. 162. 163. 164. 165. 166. 167. 168. 169. 170. 171. 172. 173. 174. 175. 176. 177. 178. 179. 180. 181. 182. 183. 184. 185. 186. 187. ) ); 188. 189. 190. 191. 192. 193. 194. 195.

altura_r_izq = obtenerAltura(ref_h_izq); altura_r_der = obtenerAltura(ref_h_der); if(altura_r_izq >= altura_r_der) { altura += altura_r_izq; } else { altura += altura_r_der; } } else if( (ref_h_izq != null) && (ref_h_der == null) ) { altura += obtenerAltura(ref_h_izq); } else if( (ref_h_izq == null) && (ref_h_der != null) ) { altura += obtenerAltura(ref_h_der); } else if( (ref_h_izq == null) && (ref_h_der == null) ) { altura -= 1; } } return altura; } private boolean insertarElemento(Object info, Nodo nodo) { Nodo nuevo_nodo = null; Informacion obj_info = new Informacion(info);

Informacion obj_info_pa = new Informacion( nodo.getInformacion( if( obj_info.compareTo(obj_info_pa) < 0 ) { if(nodo.getIzquierdo() == null) { nuevo_nodo = new Nodo(info); nuevo_nodo.setPadre(nodo);

196. 197. nodo.setIzquierdo(nuevo_nodo); 198. 199. return true; 200. 201. } else { 202. 203. return insertarElemento(info, nodo.getIzquierdo()); 204. 205. } 206. 207. } else { 208. 209. if(nodo.getDerecho() == null) { 210. 211. nuevo_nodo = new Nodo(info); 212. 213. nuevo_nodo.setPadre(nodo); 214. 215. nodo.setDerecho(nuevo_nodo); 216. 217. return true; 218. 219. } else { 220. 221. return insertarElemento(info, nodo.getDerecho()); 222. 223. } 224. 225. } 226. 227. } 228. 229. public boolean insertarElemento(Object info) throws ExceptionElemen toDuplicado { 230. 231. boolean se_inserto = false; 232. 233. if( this.esArbolVacio() ) { 234. 235. this.raiz = new Nodo(info); 236. 237. se_inserto = true; 238. 239. } else { 240. 241. if( existeElemento(info) ) { 242. 243. throw new ExceptionElementoDuplicado("El elemento ya exist e dentro del rbol!!");

244. 245. } else { 246. 247. se_inserto = insertarElemento(info, raiz); 248. 249. } 250. 251. } 252. 253. return se_inserto; 254. 255. } 256. 257. public boolean borrarElemento(Object info) throws ExceptionNoEnco ntrado { 258. 259. Nodo nodo = null; 260. 261. boolean se_borro = false; 262. 263. if( this.esArbolVacio() ) { 264. 265. throw new ExceptionNoEncontrado("El rbol esta vaco!!"); 266. 267. } else { 268. 269. if( existeElemento(info) ) { 270. 271. nodo = obtenerElemento(info, raiz); 272. 273. if(nodo.getPadre() != null) { 274. 275. if( (nodo.getIzquierdo() != null) || (nodo.getDerecho() != nul l) ) { 276. 277. se_borro = borrarNodoInterior(nodo); 278. 279. } else { 280. 281. se_borro = borrarNodoHoja(nodo); 282. 283. } 284. 285. } else { 286. 287. se_borro = borrarNodoRaiz(nodo); 288. 289. } 290. 291. } else {

292. 293. throw new ExceptionNoEncontrado("El elemento no existe den tro del rbol!!"); 294. 295. } 296. 297. } 298. 299. return se_borro; 300. 301. } 302. 303. private boolean borrarNodoInterior(Nodo nodo) { 304. 305. boolean respuesta = false; 306. 307. Nodo nodo_padre = nodo.getPadre(); 308. 309. Nodo nodo_izq = nodo.getIzquierdo(); 310. 311. Nodo nodo_der = nodo.getDerecho(); 312. 313. Nodo nodo_c = null; 314. 315. if( (nodo.getIzquierdo() != null) && (nodo.getDerecho() != null) ) { 316. 317. 318. 319. 320. 321. 322. 323. 324. 325. 326. 327. 328. 329. 330. 331. 332. 333. 334. 335. 336. 337. 338. 339. if(nodo_padre.getIzquierdo() == nodo) { nodo_padre.setIzquierdo(nodo_der); } else { nodo_padre.setDerecho(nodo_der); } nodo_der.setPadre(nodo_padre); nodo_c = new Nodo(nodo_izq.getInformacion()); nodo_c.setDerecho(nodo_izq.getDerecho()); nodo_c.setIzquierdo(nodo_izq.getIzquierdo()); nodo = null;

nodo_izq = null; insertarElemento(nodo_c.getInformacion(), nodo_der);

340. 341. 342. 343. 344. 345. 346. 347. 348. 349. 350. 351. 352. 353. 354. 355. 356. 357. 358. 359. 360. 361. 362. 363. 364. 365. 366. 367. 368. 369. 370. 371. 372. 373. 374. 375. 376. 377. 378. 379. 380. 381. 382. 383. 384. 385. 386. 387. 388. 389.

respuesta = true; } else if(nodo.getIzquierdo() != null) { nodo_izq.setPadre(nodo_padre); if(nodo_padre.getDerecho() == nodo) { nodo_padre.setDerecho(nodo_izq); } else { nodo_padre.setIzquierdo(nodo_izq); } nodo = null; respuesta = true; } else { nodo_der.setPadre(nodo_padre); if(nodo_padre.getDerecho() == nodo) { nodo_padre.setDerecho(nodo_der); } else { nodo_padre.setIzquierdo(nodo_der); } nodo = null; respuesta = true; } return respuesta; } private boolean borrarNodoHoja(Nodo nodo) { boolean se_borro = false; Nodo nodo_padre = nodo.getPadre();

390. 391. 392. 393. 394. 395. 396. 397. 398. 399. 400. 401. 402. 403. 404. 405. 406. 407. 408. 409. 410. 411. 412. 413. 414. 415. 416. 417. 418. 419. 420. 421. 422. 423. 424. 425. 426. 427. 428. 429. 430. 431. 432. 433. 434. 435. 436. 437. 438.

if(nodo_padre.getDerecho() == nodo) { nodo_padre.setDerecho(null); } else { nodo_padre.setIzquierdo(null); } nodo = null;

se_borro = true; return se_borro; } private boolean borrarNodoRaiz(Nodo nodo) { boolean se_borro = false; Nodo nodo_izq Nodo nodo_der Nodo nodo_c = nodo.getIzquierdo(); = nodo.getDerecho(); = null;

if( (nodo.getIzquierdo() != null) && (nodo.getDerecho() != null) ) { this.raiz = nodo_der; this.raiz.setPadre(null); nodo_c = new Nodo(nodo_izq.getInformacion()); nodo_c.setDerecho(nodo_izq.getDerecho()); nodo_c.setIzquierdo(nodo_izq.getIzquierdo()); nodo = null;

nodo_izq = null; insertarElemento(nodo_c, raiz); se_borro = true;

439. 440. 441. 442. 443. 444. 445. 446. 447. 448. 449. 450. 451. 452. 453. 454. 455. 456. 457. 458. 459. 460. 461. 462. 463. 464. 465. 466. 467. 468. 469. 470. 471. 472. 473. 474. 475. 476. 477. 478. 479. 480. 481. 482. 483. 484. 485. 486. 487. 488.

} else if(nodo.getIzquierdo() != null) { this.raiz = nodo_izq; this.raiz.setPadre(null); nodo = null;

se_borro = true; } else if(nodo.getDerecho() != null) { this.raiz = nodo_der; this.raiz.setPadre(null); nodo = null;

se_borro = true; } else { this.raiz = null; se_borro = true; } return se_borro; } public ArrayList recorridoPreorden(Nodo nodo) { if(nodo == raiz) { recorrido = new ArrayList(); } if(null != nodo) { recorrido.add(nodo.getInformacion()); recorridoPreorden(nodo.getIzquierdo()); recorridoPreorden(nodo.getDerecho()); }

489. 490. 491. 492. 493. 494. 495. 496. 497. 498. 499. 500. 501. 502. 503. 504. 505. 506. 507. 508. 509. 510. 511. 512. 513. 514. 515. 516. 517. 518. 519. 520. 521. 522. 523. 524. 525. 526. 527. 528. 529. 530. 531. 532. 533. 534. 535. 536. 537.

return recorrido; } public ArrayList recorridoInorden(Nodo nodo) { if(nodo == raiz) { recorrido = new ArrayList(); } if(null != nodo) { recorridoInorden(nodo.getIzquierdo()); recorrido.add(nodo.getInformacion()); recorridoInorden(nodo.getDerecho()); } return recorrido; } public ArrayList recorridoPostorden(Nodo nodo) { if(nodo == raiz) { recorrido = new ArrayList(); } if(null != nodo) { recorridoPostorden(nodo.getIzquierdo()); recorridoPostorden(nodo.getDerecho()); recorrido.add(nodo.getInformacion()); } return recorrido; } }

Y bueno, pues el ya tan tradicional pequeo ejemplo que utiliza nuestro rbol, para demostrar que este funciona, o que por lo menos funciona lo esencial. El cdigo de nuestro ejemplo es el cdigo del ltimo ejemplo del rbol contenido en el vector, solo que utilizando nuestro rbol dinmico, por lo que utiliza las mismas clases que se usaron en el ejemplo anterior para almacenar la informacin. view plaincopy to clipboardprint? 1. package org.neos.arboles.binarios.dinamicos; 2. 3. import java.util.ArrayList; 4. 5. import org.neos.arboles.binarios.dinamicos.exceptions.ExceptionElementoDupli cado; 6. 7. import org.neos.beans.Direccion; 8. 9. import org.neos.beans.Nombre; 10. 11. import org.neos.beans.Persona; 12. 13. public class Ejemplo { 14. 15. public static void main(String[] args) { 16. 17. ArbolBinario arbol = new ArbolBinario(); 18. 19. ArrayList recorrido = null; 20. 21. int i, num_elems; 22. 23. Direccion direccion = null; 24. 25. Nombre nombre = null; 26. 27. Persona persona = null; 28. 29. try { 30. 31. direccion = new Direccion("AAA", 1, "B-1", "CCC", "DDD", "EEE"); 32. 33. nombre = new Nombre("Eugenio", "Flores", "Barrera"); 34. 35. persona = new Persona(nombre, direccion, null); 36. 37. arbol.insertarElemento(persona); 38.

39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. 51. 52. 53. 54. 55. 56. 57. 58. 59. 60. 61. 62. 63. 64. 65. 66. 67. 68. 69. 70. 71. 72. 73. 74. 75. 76. 77. 78. 79. 80. 81. 82. 83. 84. 85. 86. 87. 88.

nombre = new Nombre("Nayeli", "Vazquez", "Vasquez"); persona = new Persona(nombre, direccion, null); arbol.insertarElemento(persona); nombre = new Nombre("Hector", "Hidalgo", "Martinez"); persona = new Persona(nombre, direccion, null); arbol.insertarElemento(persona); nombre = new Nombre("Mario", "Hidalgo", "Matinez"); persona = new Persona(nombre, direccion, null); arbol.insertarElemento(persona); nombre = new Nombre("Miguel", "Flores", "Barrera"); persona = new Persona(nombre, direccion, null); arbol.insertarElemento(persona); recorrido = arbol.recorridoPreorden(arbol.obtenerPosicionRaiz()); num_elems = recorrido.size(); for(i = 0; i < num_elems; i++) { System.out.print((Persona)recorrido.get(i) + " - "); } recorrido = arbol.recorridoInorden(arbol.obtenerPosicionRaiz()); System.out.print("nRecorrido Inorden: "); num_elems = recorrido.size(); for(i = 0; i < num_elems; i++) { System.out.print((Persona)recorrido.get(i) + " - "); } recorrido = arbol.recorridoPostorden(arbol.obtenerPosicionRaiz()); System.out.print("nRecorrido Postorden: ");

89. 90. 91. 92. 93. 94. 95. 96. 97. 98. 99.

num_elems = recorrido.size(); for(i = 0; i < num_elems; i++) { System.out.print((Persona)recorrido.get(i) + " - "); } System.err.println("nNumero de elementos: "+arbol.obtenerNumeroEle mentos(arbol.obtenerPosicionRaiz()));

System.err.println("Peso del rbol: "+arbol.obtenerPeso(arbol.obtener PosicionRaiz())); 100. 101. System.err.println("Altura del rbol: "+arbol.obtenerAltura(arbo l.obtenerPosicionRaiz())); 102. 103. } catch(ExceptionElementoDuplicado ed_e) { 104. 105. System.err.println(ed_e.getMessage()); 106. 107. } 108. 109. } 110. 111. }

You might also like