Professional Documents
Culture Documents
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
// 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
// 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.
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.
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,
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
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.
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:
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.
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.
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:
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.
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;
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.
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;
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.
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. }