arboles parte 2

23
Árboles Hilvanados

Upload: guest0b94e1

Post on 13-Jul-2015

1.081 views

Category:

Documents


2 download

TRANSCRIPT

Árboles Hilvanados

Existe un problema con los arboles

binarios….

• El recorrido con recursivo de los árboles resulta costoso, ya que implica un gasto adicional: Memoria

Tiempo de ejecución

• Esto puede provocar, en el caso de un árbol muy grande, que el stack del sistema se desborde rápidamente.

• Es posible recorrer los árboles de manera iterativa, en lugar de recursiva, pero para esto ocupamos una estructura de tipo PILA.

• En un árbol binario hay más punteros NULL que punteros a nodos.

¿Cuál es la solución?

Árboles Hilvanados

• Un árbol hilvanado utiliza los punteros nulos para poder conseguir ciertas ventajas.

• A esos punteros nulos, los llamaremos HEBRAS o HILOS, para diferenciarlos de los punteros no nulos.

• Existen varias formas de enhebrado. Veremos el entreorden. (De hecho, la definición de árbol hilvanado que veremos, estará basada en este tipo de recorrido)

Definición

• Es un árbol binario en el que cada hijo izquierdo de valor nulo es sustituido por un enlace al nodo que le antecede en entreorden (excepto el primer nodo) …. Esto es un árbol hilvanado por la izquierda.

• Es un árbol binario en el que cada hijo derecho de valor nulo es sustituido por un enlace al nodo que le sigue en el recorrido en entreorden (excepto el último nodo) …. Esto es un árbol hilvanado por la derecha.

Nodo tipo para árbol hilvanado por la

derecha…

struct nodo {

int info;

struct nodo *left;

struct nodo *right;

int rthread; //1 – Es Hilo, 0 – no Hilo

}

Construcción de los hilos

• Un NULL en un enlace derecho de un nodo p se reemplaza por un puntero al nodo que se visitaría después de p en un recorrido en entreorden. (sucesor)

• Un NULL en un enlace izquierdo de un nodo p se reemplaza por un puntero al nodo que se visitaría antes de p en un recorrido en entreorden. (predecesor)

Recorrer un árbol hilvanado a la

derecha• Iniciamos en el nodo más a la izquierda del árbol, lo

procesamos, y seguimos hacia su hilo derecho.

• Si seguimos hacia el hilo derecho, procesamos el nodo y continuamos hacia el vinculo a su derecha.

• Si seguimos a un vinculo a la derecha, nos movemos hacia el nodo más hacia la izquierda, procesamos el nodo y continuamos con la lógica.

Ejemplo

8

75

3

11

13

1

6

9

Iniciamos en el nodo más a la izquierda, y lo procesamos

Salida1

8

75

3

11

13

1

6

9

Seguimos el hilo a la derecha, procesamos el nodo.

Salida13

Ejemplo

8

75

3

11

13

1

6

9

Seguimos el vinculo a la derecha, nos movemos al nodo más a la izquierda y lo procesamos.

Salida135

Ejemplo

8

75

3

11

13

1

6

9

Salida1356

Ejemplo

Seguimos el hilo a la derecha, procesamos el nodo.

8

75

3

11

13

1

6

9

Salida13567

Ejemplo

Seguimos el vinculo a la derecha, nos movemos al nodo más a la izquierda y lo procesamos.

8

75

3

11

13

1

6

9

Salida135678

Ejemplo

Seguimos el hilo a la derecha, procesamos el nodo.

8

75

3

11

13

1

6

9

Salida1356789

Ejemplo

Seguimos el vinculo a la derecha, nos movemos al nodo más a la izquierda y lo procesamos.

8

75

3

11

13

1

6

9

Salida135678911

Ejemplo

Seguimos el hilo a la derecha, procesamos el nodo.

8

75

3

11

13

1

6

9

Salida13567891113

Ejemplo

Seguimos el vinculo a la derecha, nos movemos al nodo más a la izquierda y lo procesamos.

Node leftMost(Node n) {Node ans = n;if (ans == null) {

return null;}while (ans.left != null) {

ans = ans.left;}return ans;

}

void inOrder(Node n) {Node cur = leftmost(n);while (cur != null) {

print(cur);if (cur. rthread == 1){

cur = cur.right;} else {

cur = leftmost(cur.right);}

}}

Que modificación le podemos hacer a

este árbol??

• Todavía estamos desperdiciando punteros, la mitad de nuestros punteros hoja siguen siendo nulos.

• Podemos agregar hilos a los nodos previos en un recorrido entreorden, lo cual nos va a permitir hacer recorridos hacia atras o incluso hacer recorridos en postorden.

8

75

3

11

13

1

6

9

Arbol Hilvanado a la derecha y a la izquierda.

Ventajas

• Mejorar el aprovechamiento de la memoria.

• Los hilos evitan el uso de recursividad y de pilas.

• Recorrido entreorden más rápido.

• Determinación del predecesor y sucesor entreorden muy simple y eficiente.

• Mediante otro tipo de hilvanado se pueden conseguir los mismos resultados para otros recorridos.

Desventajas

• Espacio extra en memoria para identificar los hilos.

• Inserciones y eliminaciones menos eficientes y un poco más complejas.