Estructura de Datos En C++ Dr. Romeo Sánchez Nigenda. E-mail: [email protected] romeo/...

52
Estructura de Datos En C++ Dr. Romeo Sánchez Nigenda. E-mail: [email protected] http: //yalma.fime.uanl.mx/~ romeo / Oficina: 1er. Piso del CIDET. Oficina con Dr. Oscar Chacón Horas de Tutoría: 10am-11am Martes y Jueves, 3:30pm-4:30pm Miércoles, 2:00pm-4:00pm Viernes. Website: http://yalma.fime.uanl.mx/~romeo/ED/2011/ Sesiones: 48

Transcript of Estructura de Datos En C++ Dr. Romeo Sánchez Nigenda. E-mail: [email protected] romeo/...

Page 1: Estructura de Datos En C++ Dr. Romeo Sánchez Nigenda. E-mail: romeo.sanchez@gmail.com romeo/ Oficina: 1er. Piso del CIDET. Oficina.

Estructura de Datos En C++

Dr. Romeo Sánchez Nigenda.E-mail: [email protected]://yalma.fime.uanl.mx/~romeo/Oficina: 1er. Piso del CIDET. Oficina con Dr. Oscar ChacónHoras de Tutoría: 10am-11am Martes y Jueves, 3:30pm-4:30pm Miércoles, 2:00pm-4:00pm Viernes.

Website: http://yalma.fime.uanl.mx/~romeo/ED/2011/Sesiones: 48

Page 2: Estructura de Datos En C++ Dr. Romeo Sánchez Nigenda. E-mail: romeo.sanchez@gmail.com romeo/ Oficina: 1er. Piso del CIDET. Oficina.

Material de apoyo:Estructura de Datos con C y C++. Yedidyah Langsam, Moshe J. Augenstein, Aaron M. Tenenbaum, Brooklyn CollegeSegunda Edición, Prentice-Hall.

Algorithms. Third Edition.Parts 1-4, Fundamentals Data Structures Sorting SearchingRobert Sedgewick.

Estructura de Datos. Román Martínez, Elda Quiroga.Thomson Learning.

Cualquier libro de Estructura de Datos!

Software:Compiladores GCC (GNU Compiler Collection)

IDEs (Integrated Development Environment):http://www.eclipse.org/downloads/http://kdevelop.org/ http://www.bloodshed.net/devcpp.html

Page 3: Estructura de Datos En C++ Dr. Romeo Sánchez Nigenda. E-mail: romeo.sanchez@gmail.com romeo/ Oficina: 1er. Piso del CIDET. Oficina.

6. Árboles

Objetivo: El alumno entenderá y aprenderá las estructuras de datos no lineales y dinámicas más importantes en computación.

Temario: ◦ Árboles en general◦ Árboles binarios◦ Árboles balanceados◦ Árboles multicaminos

Page 4: Estructura de Datos En C++ Dr. Romeo Sánchez Nigenda. E-mail: romeo.sanchez@gmail.com romeo/ Oficina: 1er. Piso del CIDET. Oficina.

Árboles En Informática, los árboles son abstracciones matemáticas

que juegan un rol central en el diseño y análisis de algoritmos, porque: ◦ Los usamos para describir propiedades dinámicas de los algoritmos◦ Construimos estructuras de datos que son realizaciones concretas de

árboles.

Podemos concluir que un árbol es entonces una estructura de datos que mantiene un conjunto de nodos conectados (imitando la forma de un árbol).

Encontramos muchos ejemplos de árboles en nuestra vida diaria:◦ Organización de torneos deportivos◦ Árboles familiares (ascendientes y descendientes)◦ Organigramas de corporaciones ◦ Procesamiento de lenguaje natural◦ Organización de sistemas de archivos (directorios y archivos)

Page 5: Estructura de Datos En C++ Dr. Romeo Sánchez Nigenda. E-mail: romeo.sanchez@gmail.com romeo/ Oficina: 1er. Piso del CIDET. Oficina.

ÁrbolesExisten diferentes tipos de árboles:

◦ Árboles en general

◦ Árboles binarios (AVL, Rojo-Negro, AA)

◦ Árboles balanceados

◦ Árboles multi-caminos (B, B+, B*)

En general un árbol es un conjunto de vértices y aristas que satisfacen ciertos requisitos. ◦ Un vértice es un objeto simple, también denominado nodo, que

contiene información.

◦ Una arista (o arco) es una conexión entre dos vértices

◦ Un camino (o ruta) en un árbol es una lista de vértices distintos, en los que cada uno de ellos se encuentran conectados sucesivamente por aristas en el árbol.

La propiedad definitoria de un árbol es que existe solamente un camino o ruta conectando un par de nodos. Si hay más de un camino entre dos nodos, o si no hay un camino entre un par de nodos, entonces lo que tenemos es un Grafo.

Page 6: Estructura de Datos En C++ Dr. Romeo Sánchez Nigenda. E-mail: romeo.sanchez@gmail.com romeo/ Oficina: 1er. Piso del CIDET. Oficina.

Árboles: Terminología Un nodo por lo tanto, es la unidad sobre la que se

construye el árbol, y puede tener cero o más nodos hijos conectados a él (por medio de aristas) esta propiedad se le denomina grado.

Se dice que un nodo a es padre de un nodo b (o b es hijo de a) si existe un enlace desde a hasta b.

Un árbol solo puede tener un único nodo sin padres, al cual se le denomina raíz. En un árbol con raíz, cualquier nodo es la raíz de un subárbol, el cual consiste de sí mismo y de los nodos descendientes de él

Un nodo que no tiene hijos se le denomina hoja o terminal.

El resto de los nodos se les conoce como rama, ya que tienen padre y uno o varios hijos.

Page 7: Estructura de Datos En C++ Dr. Romeo Sánchez Nigenda. E-mail: romeo.sanchez@gmail.com romeo/ Oficina: 1er. Piso del CIDET. Oficina.

Árboles En computación, usualmente se usa el término árbol para

referirse a un árbol con raíz. Mientras que se asume el término árbol libre para referirse a la estructura más general.

Las aristas en un árbol no tienen dirección, usualmente se menciona que se encuentran apuntando hacia la raíz o fuera de ella. Y usualmente se coloca a la raíz en la cima del árbol.

Un árbol ordenado es un árbol con raíz en el cual el orden de los nodos descendientes (hijos) sigue un patrón determinado

Si cada nodo debe tener un número determinado de hijos en un orden específico, entonces tenemos un árbol de M-aristas. El árbol de M-aristas más simple es el árbol binario.

Page 8: Estructura de Datos En C++ Dr. Romeo Sánchez Nigenda. E-mail: romeo.sanchez@gmail.com romeo/ Oficina: 1er. Piso del CIDET. Oficina.

Árboles: Definición General Caso base: Un árbol con un solo nodo, el cual es a la vez la

raíz del árbol y una hoja.

Un árbol a partir de un nodo raíz R y k árboles A1, A2, A3,…, Ak con raíces n1, n2, n3, …, nk respectivamente, y N1, N2, N3,…, Nk nodos cada uno.

El árbol resultante de N = 1 + N1 + N2 + N3 +…+Nk nodos tiene como raíz al nodo R, por lo que los nodos n1, n2, n3, …, nk son los hijos de R.

A cada uno de los árboles Ai se les denota como subárboles de la raíz.

Un recorrido es una sucesión de nodos del árbol de tal forma que entre cada dos nodos consecutivos de la sucesión hay una relación de parentesco.

Page 9: Estructura de Datos En C++ Dr. Romeo Sánchez Nigenda. E-mail: romeo.sanchez@gmail.com romeo/ Oficina: 1er. Piso del CIDET. Oficina.

Árboles: Definición General Existen dos recorridos típicos para listar los nodos de un

árbol: en profundidad y en anchura.

En profundidad (depth-first) listamos los nodos expandiendo primero el hijo actual de cada nodo hasta llegar a una hoja, al llegar a una hoja regresamos al nodo anterior probando el siguiente hijo, y así sucesivamente.

En anchura (breadth-first), antes de recorrer los nodos del nivel d+1 (profundidad de d+1 aristas desde la raíz), se listan todos los nodos del nivel d.

Page 10: Estructura de Datos En C++ Dr. Romeo Sánchez Nigenda. E-mail: romeo.sanchez@gmail.com romeo/ Oficina: 1er. Piso del CIDET. Oficina.

Árboles: Ejemplos

Page 11: Estructura de Datos En C++ Dr. Romeo Sánchez Nigenda. E-mail: romeo.sanchez@gmail.com romeo/ Oficina: 1er. Piso del CIDET. Oficina.

Árboles Binarios Un árbol binario es un conjunto finito de elementos que

está vacío o dividido en tres subconjuntos:1. El primer subconjunto contiene un elemento único, la raíz del árbol,

2. Un subárbol binario izquierdo que puede o no estar vacío

3. Un subárbol binario derecho equivalente al izquierdo

En otras palabras, un árbol binario es un nodo externo, o un nodo interno conectado a un par de árboles binarios, los subárboles izquierdo y derecho.

izq der

hoja

descendiente

ancestro

hermanos

raíz

Page 12: Estructura de Datos En C++ Dr. Romeo Sánchez Nigenda. E-mail: romeo.sanchez@gmail.com romeo/ Oficina: 1er. Piso del CIDET. Oficina.

Árboles Binarios Nivel de un árbol binario: La raíz del árbol tiene el nivel 0,

y el nivel de cualquier otro nodo en el árbol es uno más el nivel de su padre. Nivel = 0

Nivel = 1

Nivel = 2

Nivel = 3Profundidad

Nivel = 0

Nivel = 1

Nivel = 2

Árbol binario completo: Es un árbol binario que tiene todos sus nodos completos en cada subárbol a una profundidad d.

Si un árbol binario contiene m nodos en el nivel l, entonces contiene un máximo de 2m nodos en el nivel l+1.

4

2

1

nodos

2l nodos por nivel, por lo tanto la Cantidad de nodos en un árbol de Profundidad d es igual a la suma de Los nodos por nivel:N = 20 + 21 + … + 2d = ∑d 2j = 2d+1 - 1

j=0

d

Page 13: Estructura de Datos En C++ Dr. Romeo Sánchez Nigenda. E-mail: romeo.sanchez@gmail.com romeo/ Oficina: 1er. Piso del CIDET. Oficina.

Árboles Binarios: Operaciones Entre las aplicaciones más comunes tenemos:

◦ Dado un apuntador p a un nodo en un árbol binario

a

b c

fed g

p

info(p) : Retorna el contenido del nodo, en este ejemplo es a

right(p) : Retorna un apuntadoral hijo derecho del nodo

left(p) : Retorna un apuntadoral hijo izquierdo del nodo

father(p) : Retorna un apuntador al padre del nodo

Null

brother(p) : Retorna un apuntador al hermano del nodo.

Note que si no existe un nodo que satisfaga cualquiera de las funciones anteriores, se retorna un nulo (null) entonces.

Las funciones lógicas isLeft(p) y isRight(p) retornan true si p se encuentra en el lado izquierdo o derecho de algún otro nodo respectivamente, false sino es el caso.

isLeft(d) = trueisLeft(e) = falseisRight(g) = true

Page 14: Estructura de Datos En C++ Dr. Romeo Sánchez Nigenda. E-mail: romeo.sanchez@gmail.com romeo/ Oficina: 1er. Piso del CIDET. Oficina.

Las funciones isLeft(p), isRight(p), y brother(p), se implementan usando la funcionalidad de left(p), right(p), y father(p). Ejemplo:

Bool isLeft(p)q = father(p)if(q == null)

return false;if(left(q) == p)

return true;return false;

Árboles Binarios: Operaciones

a

b c

fed g

isLeft(a) ?

isLeft(b) ? isLeft(c) ?

Implementa isRight(p)!

Page 15: Estructura de Datos En C++ Dr. Romeo Sánchez Nigenda. E-mail: romeo.sanchez@gmail.com romeo/ Oficina: 1er. Piso del CIDET. Oficina.

brother(p)if(father(p) == null)

return null;if(isLeft(p))

return right(father(p)) return left(father(p))

Árboles Binarios: Operaciones

a

b c

fed g

brother(c) ?

father

Operaciones adicionales:-makeTree(p) : Crea un árbol binario con un nodo único (raíz)- setLeft(p, x) : Establece un nodo x como hijo izquierdo de otro nodo p, siempre y cuando p no tenga un hijo del lado izquierdo ya establecido. - setRight(p, x) : Similar a la función anterior.

Page 16: Estructura de Datos En C++ Dr. Romeo Sánchez Nigenda. E-mail: romeo.sanchez@gmail.com romeo/ Oficina: 1er. Piso del CIDET. Oficina.

Los árboles binarios son útiles cuando se toman decisiones en dos sentidos en cada punto del proceso.

Ejemplo: Encontrar todos los duplicados en una lista de números: {15,4,8, 7, 4, 3, 19, 5, 7, 9, 16, 5,17}

Algoritmo: Primer elemento es la raíz, subsecuentes elementos se colocan a la izquierda si son menores o a la derecha si son mayores. Si son duplicados no se insertan pero se reportan.

Árboles Binarios: Aplicación de Ejemplo

15

15

4

15

4

8

15

4

8

7

4

15

4

8

7

3

Page 17: Estructura de Datos En C++ Dr. Romeo Sánchez Nigenda. E-mail: romeo.sanchez@gmail.com romeo/ Oficina: 1er. Piso del CIDET. Oficina.

Árboles Binarios: Aplicación de Ejemplo{15,4,8, 7, 4, 3, 19, 5, 7, 9, 16, 5,17}

15

4

8

7

3

19

15

4

8

7

3

19

5

15

4

8

7

3

19

5

9

16

17

Page 18: Estructura de Datos En C++ Dr. Romeo Sánchez Nigenda. E-mail: romeo.sanchez@gmail.com romeo/ Oficina: 1er. Piso del CIDET. Oficina.

Árboles Binarios: Aplicación de Ejemplo

15

4

8

7

3

19

5

9

16

17

Pseudocódigo:

int numbers[13] = {15,4,8, 7, 4, 3, 19, 5, 7, 9, 16, 5,17};tree = makeTree(numbers[0]);for(int i=1;i<length(numbers);i++){ p = q = tree; while(numbers[i] !=info(p) && q!=NULL){

p = q;if(numbers[i]<info(p)) q = left(p);else q = right(p);

} if(numbers[i] == info(p))

cout<<“Numero repetido”; else if(numbers[i] < info(p))

setleft(p,numbers[i]); else setright(p, numbers[i]);}

Page 19: Estructura de Datos En C++ Dr. Romeo Sánchez Nigenda. E-mail: romeo.sanchez@gmail.com romeo/ Oficina: 1er. Piso del CIDET. Oficina.

Ejemplo 2: Expresiones La raíz del árbol binario contiene un operador que se

aplicará a la evaluación de las expresiones representadas por sus subárboles izquierdo y derecho.

Los operandos son únicamente hojas en el árbol

+

A

C

*

BA+B*C

*

C

B

+

A (A+B)*C

$

+

*

B

A

*

C

+

A B

C

(A+B*C)$((A+B)*C)

Page 20: Estructura de Datos En C++ Dr. Romeo Sánchez Nigenda. E-mail: romeo.sanchez@gmail.com romeo/ Oficina: 1er. Piso del CIDET. Oficina.

Representación básica de un árbol binariostruct tnode {int info;struct tnode * father; //No necesariostruct tnode * left;struct tnode * right;};

typedef struct tnode * TNODEPTR;

TNODEPTR createNode() {TNODEPTR p = (TNODEPTR)

malloc(sizeof(struct tnode));return p;

}

void freeNode(TNODEPTR P) {free( p);}

Info

L F R

p

Page 21: Estructura de Datos En C++ Dr. Romeo Sánchez Nigenda. E-mail: romeo.sanchez@gmail.com romeo/ Oficina: 1er. Piso del CIDET. Oficina.

Representación básica de un árbol binario

TNODEPTR makeTree(int x) {TNODEPTR root = createNode();root->info = x;root->father = NULL;root->left = NULL;root->right = NULL;return root;

}

X NULL NULL NULL

TNODEPTR father(TNODEPTR pNode) {return pNode->father;

}

TNODEPTR leftChild(TNODEPTR pNode) {

return pNode->left;}

TNODEPTR rightChild(TNODEPTR pNode) {

return pNode->right;}

Page 22: Estructura de Datos En C++ Dr. Romeo Sánchez Nigenda. E-mail: romeo.sanchez@gmail.com romeo/ Oficina: 1er. Piso del CIDET. Oficina.

Representación básica de un árbol binario

void setLeftChild(TNODEPTR pNode, int x) {if (pNode == NULL)

cout << "Error, padre es nulo!" << endl; else if (leftChild(pNode) != NULL)

cout << "Error, hijo izquierdo presente!“; else {

pNode ->left = makeTree(x);pNode ->left ->father = pNode;

}}

pNode

X N N NY N N N

makeTree(x);

pNode->left=…

Y N N

X N N N

pNode

Y N N

X N N

pNode

pNode ->left ->father = pNode;

void setRightChild(TNODEPTR pNode, int x){…} //Es similar

Page 23: Estructura de Datos En C++ Dr. Romeo Sánchez Nigenda. E-mail: romeo.sanchez@gmail.com romeo/ Oficina: 1er. Piso del CIDET. Oficina.

Representación básica de un árbol binario

bool isLeft(TNODEPTR pNode) {if (pNode == NULL)

return false;else if (father(pNode) == NULL)

return false;else

return (leftChild(father(pNode)) == pNode);}

bool isRight(TNODEPTR pNode) {if (pNode == NULL)

return false;else if (father(pNode) == NULL)

return false;return (rightChild(father(pNode)) == pNode);

}

Page 24: Estructura de Datos En C++ Dr. Romeo Sánchez Nigenda. E-mail: romeo.sanchez@gmail.com romeo/ Oficina: 1er. Piso del CIDET. Oficina.

Representación básica de un árbol binario

TNODEPTR sibling(TNODEPTR pNode) {if (pNode == NULL)

return NULL;if (father(pNode) == NULL)

return NULL;if (isLeft(pNode))

return rightChild(father(pNode));else

return leftChild(father(pNode));}

a

b c

fed g

sibling(c) ?

father

Page 25: Estructura de Datos En C++ Dr. Romeo Sánchez Nigenda. E-mail: romeo.sanchez@gmail.com romeo/ Oficina: 1er. Piso del CIDET. Oficina.

Árbol binario de búsqueda u ordenadoEl ejemplo anterior introdujo el árbol binario de

búsqueda o árbol binario ordenado

Este tipo de árbol tiene todos sus nodos en orden, para cada nodo X:◦ Todos los elementos de su árbol izquierdo son menores

o iguales a X,◦ Mientras los nodos en su árbol derecho son mayores a

X.

En promedio, un árbol binario ordenado puede localizar un nodo en un árbol de N nodos en tiempo log(N).

Page 26: Estructura de Datos En C++ Dr. Romeo Sánchez Nigenda. E-mail: romeo.sanchez@gmail.com romeo/ Oficina: 1er. Piso del CIDET. Oficina.

Búsqueda en un árbol binario ordenado 15

4

8

7

3

19

5

9

16

17

//Dado un árbol binario, retorna//verdadero si el dato buscado se //encuentra en el árbol, o falso si nobool find(TNODEPTR pNode, int data){

//Caso base:arbol vacioif(pNode==NULL){ return false;} else{ //Dato es encontrado if(pNode->info==data){

return true; }else{

if(data<pNode->info){ //Recursa a la izq si es menor return find(pNode->left,data);} else{ //Recursa a la derecha si es mayor return find(pNode->right,data);}

}}

}

Page 27: Estructura de Datos En C++ Dr. Romeo Sánchez Nigenda. E-mail: romeo.sanchez@gmail.com romeo/ Oficina: 1er. Piso del CIDET. Oficina.

Inserción en un árbol binario ordenado 15

4

8

7

3

19

5

9

16

17

//Dado un árbol binario, inserta un //nuevo nodo en el lugar correcto del arbol. TNODEPTR insert(TNODEPTR pNode, int data){

//1: Si el arbol esta vacio retorna//un nodo unicoif(pNode==NULL){ return makeTree(data);} else{ //Recursa hacia abajo del arbol //Para encontrar el lugar correcto if(data<=pNode->info){

pNode->left = insert(pNode->left, data); }else{

pNode->right = insert(pNode->right, data); } //Retorna el nodo original sin cambiar return(pNode);}

}

1

Page 28: Estructura de Datos En C++ Dr. Romeo Sánchez Nigenda. E-mail: romeo.sanchez@gmail.com romeo/ Oficina: 1er. Piso del CIDET. Oficina.

Árbol binarios: Ejercicio simpleEscribe código que implemente el siguiente árbol binario:

2

1 3

a) Llamando a makeTree tres veces

y usando tres variables puntero.

b) Llamando a makeTree tres veces

y usando una variable puntero.

b) Llamando a insert tres veces,

pasándole la raíz del árbol.

TNODEPTR build123(){ TNODEPTR two; two = makeTree(2); two->left = makeTree(1); two->right = makeTree(3); return two}

TNODEPTR build123(){ TNODEPTR one, two three; one = makeTree(1); two = makeTree(2); three = makeTree(3); two->left = one; two->right = three; return two}

TNODEPTR build123(){ TNODEPTR root=NULL; root = insert(root,2); root = insert(root,1); root = insert(root,3); return root;}

Page 29: Estructura de Datos En C++ Dr. Romeo Sánchez Nigenda. E-mail: romeo.sanchez@gmail.com romeo/ Oficina: 1er. Piso del CIDET. Oficina.

Implementa la función size que calcula el número de nodos en un árbol binario.

Árbol binarios: Ejercicio simple

int size(TNODEPTR pNode){ if(pNode==NULL){

return 0; }else{

return (size(pNode->left)+ 1 + size(pNode->right)); }}

Dado un árbol binario ordenado no nulo, implementa una función que retorne el valor mínimo en el árbol

int minimum(TNODEPTR pNode){ TNODEPTR current = pNode; while(current->left!=NULL) current = current->left } return current->info;}

Page 30: Estructura de Datos En C++ Dr. Romeo Sánchez Nigenda. E-mail: romeo.sanchez@gmail.com romeo/ Oficina: 1er. Piso del CIDET. Oficina.

Recorrido de árboles binarios Recorrer un árbol binario significa visitar la raíz y recorrer

sus subárboles izquierdo y derecho de forma recursiva. Orden previo:

1. Visitar la raíz2. Recorrer el subárbol izquierdo en orden previo3. Recorrer el subárbol derecho en orden previo

A

B

G

D

C

H

E

I

F ABDGCEHIF

1

2

3

4

5

6

7 8

9

void recorridoPreorden(TNODEPTR pNode){if(pNode!=NULL){cout<<"Node: "<<pNode->info;recorridoPreorden(pNode->left);recorridoPreorden(pNode->right);}

}

Page 31: Estructura de Datos En C++ Dr. Romeo Sánchez Nigenda. E-mail: romeo.sanchez@gmail.com romeo/ Oficina: 1er. Piso del CIDET. Oficina.

Recorrido de árboles binarios Orden Simétrico/Inorden:

1. Recorrer el subárbol izquierdo en orden simétrico2. Recorrer la raíz3. Recorrer el subárbol derecho en orden simétrico

A

B

G

D

C

H

E

I

F DGBAHEICF

4

3

1

2

8

6

5 7

9

void recorridoInorden(TNODEPTR pNode){if(pNode!=NULL){recorridoPreorden(pNode->left);cout<<"Node: "<<pNode->info;recorridoPreorden(pNode->right);}

}

Page 32: Estructura de Datos En C++ Dr. Romeo Sánchez Nigenda. E-mail: romeo.sanchez@gmail.com romeo/ Oficina: 1er. Piso del CIDET. Oficina.

Recorrido de árboles binarios Orden Posterior:

1. Recorrer el subárbol izquierdo en orden posterior2. Recorrer el subárbol derecho en orden posterior3. Recorrer la raíz

A

B

G

D

C

H

E

I

F GDBHIEFCA

9

3

2

1

8

6

4 5

7

void recorridoPostorden(TNODEPTR pNode){if(pNode!=NULL){recorridoPreorden(pNode->left);recorridoPreorden(pNode->right);cout<<"Node: "<<pNode->info;}

}

Page 33: Estructura de Datos En C++ Dr. Romeo Sánchez Nigenda. E-mail: romeo.sanchez@gmail.com romeo/ Oficina: 1er. Piso del CIDET. Oficina.

Remoción en un árbol binario ordenado15

4

83

19

16

Se presentan tres casos:◦ El nodo a suprimir no tiene hijos: Se

elimina el nodo del árbol sin mayores ajustes

◦ Si el nodo a suprimir sólo tiene un subárbol: Su único hijo se mueve hacia arriba y ocupa su lugar

◦ El nodo a suprimir tiene dos subárboles: Su sucesor de orden intermedio S (o antecesor) debe ocupar su lugar. El sucesor intermedio es el nodo hijo más a la izquierda en su árbol derecho. Dicho nodo no puede tener un subárbol izquierdo. El antecesor sería el nodo hijo más a la derecha de su árbol izquierdo.

15

4

8

19

16

15

4

8

19

16

15

819

16

15

4

83

19

16

25

18

23

24

23

24

Page 34: Estructura de Datos En C++ Dr. Romeo Sánchez Nigenda. E-mail: romeo.sanchez@gmail.com romeo/ Oficina: 1er. Piso del CIDET. Oficina.

Remoción en un árbol binario ordenado15

4

83

19

16

15

4

8

19

16

15

4

8

19

16

15

819

16

15

4

83

19

16

25

18

23

24

23

24

void deleteNode(TNODEPTR tree, int x) {

TNODEPTR p = tree, q = NULL, rp;

while (p != NULL && p->info != x) {

q = p;

p = (x < p->info) ? p->left : p-> right;

}

if (p == NULL) return;

if (p->left == NULL)

rp = p-> right;

else if (p-> right == NULL)

rp = p->left;

else {

TNODEPTR f = p;

rp = p-> right;

TNODEPTR s = rp->left;

while (s != NULL) {

f = rp;

rp = s;

s = rp->left;

}

if (f != p) {

f->left = rp->right;

rp->right = p->right;

}

rp->left = p->left;

}

if (q == NULL) tree = rp;

else

(p == q->left) ? q->left = rp : q->right = rp;

freeNode(p);

}

Page 35: Estructura de Datos En C++ Dr. Romeo Sánchez Nigenda. E-mail: romeo.sanchez@gmail.com romeo/ Oficina: 1er. Piso del CIDET. Oficina.

Árboles BalanceadosLa altura (profundidad) de un árbol binario es el

nivel máximo de sus hojas

Un árbol binario balanceado o árbol AVL es aquel en el que las alturas de los dos subárboles de cada nodo nunca difieren en más de 1.

El balance de un nodo en un árbol binario se define como la altura de su subárbol izquierdo menos la altura de su subárbol derecho.

Por lo tanto, cada nodo en un árbol AVL tiene un balance de 1, -1 o 0, dependiendo de si la altura de su subárbol izquierdo es mayor que, menor que o igual a la altura del derecho.

Page 36: Estructura de Datos En C++ Dr. Romeo Sánchez Nigenda. E-mail: romeo.sanchez@gmail.com romeo/ Oficina: 1er. Piso del CIDET. Oficina.

Árboles Balanceados-1

1

0

0

1 -1

00 0

0

00 0

0000

Factor de Equilibrio (FE): Cada nodo en un árbol AVL tiene un balance de 1, -1 o 0, dependiendo de si la altura de su subárbol izquierdo es mayor que, menor que o igual a la altura del derecho.

Si el FE>=2, es necesario reequilibrar el árbol.

Page 37: Estructura de Datos En C++ Dr. Romeo Sánchez Nigenda. E-mail: romeo.sanchez@gmail.com romeo/ Oficina: 1er. Piso del CIDET. Oficina.

Árbol AVLDebido a que los árboles están balanceados, la

complejidad de búsqueda de un elemento es del orden O(log n).

Las operaciones en un árbol AVL balanceado son las mismas que en un árbol binario de búsqueda desequilibrado, pero si al insertar o borrar elementos el árbol pierde su balance entonces se rotan los nodos para equilibrar de nuevo el árbol.

El propósito de la rotación es que el recorrido de orden intermedio del árbol rotado sea el mismo que para el árbol original (es decir, el árbol rotado sigue siendo un árbol de búsqueda binaria).

Page 38: Estructura de Datos En C++ Dr. Romeo Sánchez Nigenda. E-mail: romeo.sanchez@gmail.com romeo/ Oficina: 1er. Piso del CIDET. Oficina.

Árbol AVL: RepresentaciónCada nodo debe contener, además de los datos, su factor de equilibrio y los punteros hacia sus hijos.

Por ejemplo:P = {data=10, left=7, right=15, FE=2}

5

2

15

8

7

6

10

p

Page 39: Estructura de Datos En C++ Dr. Romeo Sánchez Nigenda. E-mail: romeo.sanchez@gmail.com romeo/ Oficina: 1er. Piso del CIDET. Oficina.

Árbol AVL: Rotaciones7

5

62

10

8 15

5

2

158

7

6 10

5

2

15

8

7

6

10

Rotación derecha Rotación izquierda

2,5,6,7,8,10,15

Recorrido Inorder

2,5,6,7,8,10,15

Page 40: Estructura de Datos En C++ Dr. Romeo Sánchez Nigenda. E-mail: romeo.sanchez@gmail.com romeo/ Oficina: 1er. Piso del CIDET. Oficina.

Algoritmo de Rotación Izquierda

Rotación izquierda

q = right(p);temp = left(q);left(q) = p;right(p) = temp

p

Dado un árbol de raíz p, y de hijo izquierdo l y derecho r, se forma un nuevo árbol cuya raíz sea la raíz del hijo del lado derecho (es decir r), y como su hijo derecho le colocamos el hijo derecho que tenía anteriormente (es decir r’).

Del lado izquierdo de la nueva raíz r, colocamos a la raíz anterior p, teniendocomo raíz de su subárbol derecho el hijo izquierdo lr’ de la nueva raíz r’.

7

5

62

10

8 15

5

2

15

8

7

6

10

l r

r

r’

r’p

l

lr’

lr’

Page 41: Estructura de Datos En C++ Dr. Romeo Sánchez Nigenda. E-mail: romeo.sanchez@gmail.com romeo/ Oficina: 1er. Piso del CIDET. Oficina.

Rotaciones DoblesSi la inserción se produce en el hijo derecho (lr’) del hijo izquierdo (p) del nodo desequilibrado (r) o viceversa , se realizará una doble rotación.

Rotación Doble a la Derecha: Primero es una rotación simple a la izquierda, y luego rotación simple a la derecha.

5

2

15

9

7

6

12

r

r’p

l lr’

10

5

2

15

9

7

6

12

10

8

5

2

15

9

7

6

12

10

88

Rotación ala izquierda

Rotación ala derecha

Page 42: Estructura de Datos En C++ Dr. Romeo Sánchez Nigenda. E-mail: romeo.sanchez@gmail.com romeo/ Oficina: 1er. Piso del CIDET. Oficina.

Casos de InserciónLa inserción funciona como si fuera un árbol de

búsqueda binario desequilibrado, retrocediendo hacia la raíz y rotando sobre cualquier nodo no balanceado.

Caso 1: Izquierda Solución: Rotación Derecha

Nuevo nodo

* Imágenes tomadas de Wikimedia bajo licencia de documentación libre GNU

Page 43: Estructura de Datos En C++ Dr. Romeo Sánchez Nigenda. E-mail: romeo.sanchez@gmail.com romeo/ Oficina: 1er. Piso del CIDET. Oficina.

Casos de InserciónCaso 2: Derecha

Solución: Rotación Izquierda

* Imágenes tomadas de Wikimedia bajo licencia de documentación libre GNU

Nuevo nodo

Page 44: Estructura de Datos En C++ Dr. Romeo Sánchez Nigenda. E-mail: romeo.sanchez@gmail.com romeo/ Oficina: 1er. Piso del CIDET. Oficina.

Casos de InserciónCaso 3: Izquierda-Derecha Solución:

Rotación doble

Rotación Izquierda

* Imágenes tomadas de Wikimedia bajo licencia de documentación libre GNU

Rotación Derecha

Page 45: Estructura de Datos En C++ Dr. Romeo Sánchez Nigenda. E-mail: romeo.sanchez@gmail.com romeo/ Oficina: 1er. Piso del CIDET. Oficina.

Casos de InserciónCaso 4: Derecha-Izquierda Solución:

Rotación doble

Rotación Izquierda

* Imágenes tomadas de Wikimedia bajo licencia de documentación libre GNU

Rotación Derecha

Page 46: Estructura de Datos En C++ Dr. Romeo Sánchez Nigenda. E-mail: romeo.sanchez@gmail.com romeo/ Oficina: 1er. Piso del CIDET. Oficina.

Árboles MulticaminosUn árbol multi-camino o multi-direccional de

orden n, es un árbol general en el cual cada nodo tiene n o menos subárboles, y contiene una llave (key) menos que subárboles.

Sea A un árbol de n-caminos si y solo si:I. A está vacíoII. A puede tener hasta n subárboles S0, S1, S2, …, Sn-

1 en cada nodoIII. Dado n subárboles para un nodo p de A; p tiene Kn-

2 llaves en orden. Es decir, cada nodo contiene una llave menos que subárboles

IV. Todas las llaves en el subárbol S0 son menores que o iguales a K0, mientras todas las llaves en los subárboles Sj (1<j<n-2) son mayores que Kj-1.

V. Todas las llaves en el subárbol Sn-1 son mayores que las llaves kn-2.

Page 47: Estructura de Datos En C++ Dr. Romeo Sánchez Nigenda. E-mail: romeo.sanchez@gmail.com romeo/ Oficina: 1er. Piso del CIDET. Oficina.

Árboles Multicaminos: Nodos

S0 K0 … Kj-1 Sj Kj … Kn-2

Sn-1

Nodo A

X X X

X < K0 Kj-1 < X < Kj X > Kn-2

Cantidad variable de apuntadores Cantidad variable de llaves

Page 48: Estructura de Datos En C++ Dr. Romeo Sánchez Nigenda. E-mail: romeo.sanchez@gmail.com romeo/ Oficina: 1er. Piso del CIDET. Oficina.

Árboles Multicaminos: Ejemplos

12 50 85

6 10 3760 70

80100 120

150

2562 65

69110

A

B C D E

F G H

Árbol multicamino de orden 4. Máxima cantidad de llaves es 3

Page 49: Estructura de Datos En C++ Dr. Romeo Sánchez Nigenda. E-mail: romeo.sanchez@gmail.com romeo/ Oficina: 1er. Piso del CIDET. Oficina.

numTrees(p): Dado un nodo multicamino p, retorna el número de hijos (subárboles) de p (0<=numTrees(p)<=n). Donde n es el orden o grado del árbol.

child(p,i): Retorna el i_ésimo hijo del nodo p. Donde 0<=i<numTrees(p)-1.

key(p,j): Retorna la j_ésima llave del nodo p. Donde 0<=j<numTrees(p)-2 son las llaves en orden ascendente

Árboles Multicaminos: Operaciones Básicas

12 50 85

6 10 3760 70

80100 120

150

A

B C D E

numTrees(A) => 4

child(A,0) child(A,3)

key(A,2)key(A,0)

Page 50: Estructura de Datos En C++ Dr. Romeo Sánchez Nigenda. E-mail: romeo.sanchez@gmail.com romeo/ Oficina: 1er. Piso del CIDET. Oficina.

Árboles Multicaminos: Operaciones Básicas

child(p,0) apunta a un subárbol cuyas llaves son todas menores que la llave key(p,0).

12 50 85

6 10

37

60 70 80

100 120 150

A

B C D E

child(A,0): Las llaves de este nodo {6,10} < 12

key(A,0)child(p, numTrees(p)-1) apunta a un subárbol que contiene únicamente llaves mayores a key(p, numTrees(p)-2).

child(p,i) para 1<=i<=numTrees(p)-2, contiene todas las llaves en el árbol entre key(p, i-1) y key(p,i).

child(A,3): Las llaves de este nodo: {100,120, 150} > 85

key(A,2)

Page 51: Estructura de Datos En C++ Dr. Romeo Sánchez Nigenda. E-mail: romeo.sanchez@gmail.com romeo/ Oficina: 1er. Piso del CIDET. Oficina.

Recorrido: Impresión de llaves en orden ascendente.

traverse(T node){

if(node != NULL){

nt = numTrees(node);

for(i = 0; i<nt-1; i++){

traverse(son(node,i));

cout<<key(node, i);

}

traverse(son(node,nt-1));

}

}

Árboles Multicaminos: Operaciones Básicas

12 50 85

6 10

37

60 70 80

100 120 150

A

B C D E

nt = 40<=i<3

key(A,0), Key(A,1), Key(A,2)

son(A,0) son(A,1) son(A,2) son(A,3)

Page 52: Estructura de Datos En C++ Dr. Romeo Sánchez Nigenda. E-mail: romeo.sanchez@gmail.com romeo/ Oficina: 1er. Piso del CIDET. Oficina.

Árboles Multicaminos: Operaciones Básicas Acceso secuencial directo: Accede a la siguiente llave partiendo

de otra que se le conoce su posición en el árbol. Asumimos que la llave que conocemos se encuentra en Key(node, index)

next(T node, int index){ p = son(node, index+1); q = null; while(p != NULL){

q = p;p = son(p,0);

} if (q!=NULL)

return key(q,0); if(index < numTrees(node)-2)

return key(node, index+1); return (NULL);}

succesor(T node, int index){ p = son(node, index+1); if(p!=NULL && index<numTrees(node)-2)

return (next(p,index)); f = father(node); i = index(node); while(f != NULL&& i==numTrees(f) -1){ i = index(f);

f = father(f); } if (f==NULL)

return (NULL); return (key(f,i));}