Árboles avl cont

Post on 14-Jan-2016

35 Views

Category:

Documents

0 Downloads

Preview:

Click to see full reader

DESCRIPTION

Árboles AVL cont. Algoritmo de Inserción. En la construcción de un árbol AVL todo nodo que se inserte, se insertará como una hoja . Los pasos son: 1. Buscar donde insertar el nuevo nodo 2. Insertar el nuevo nodo 3. Recalcular factores de balance - PowerPoint PPT Presentation

TRANSCRIPT

Árboles AVLcont.

Algoritmo de Inserción

En la construcción de un árbol AVL todo nodo que se inserte, se insertará como una hojahoja. Los pasos son:

1. Buscar donde insertar el nuevo nodo2. Insertar el nuevo nodo3. Recalcular factores de balance4. Rebalancear el árbol si es necesario

Para el primer paso, el cual consiste en buscar

dónde insertar el nuevo nodo se utilizan las

siguientes variables:

– p: Para recorrer el árbol buscando donde insertar el nuevo nodo

– q: Apuntará hacia el padre de p

Inicialmente p será la raíz y q será NULL

• Cuando p se haga NULL, q apuntará hacia el nodo que será el padre del nodo que contiene el nuevo dato

• Ahora bien, como el tercer paso es rebalancear el árbol, se requiere conocer cuál será el nodo "raíz" del sub-árbol a balancear. Se llamará a este nodo PIVOTE. Es decir, PIVOTE será la raíz del árbol a balancear

• Como al rebalancear un árbol, éste siempre cambia de raíz, la nueva raíz, (que queda en Q), habrá que pegarla del nodo que era padre de PIVOTE. Esto implica que se debe conocer el padre de PIVOTE. Se llamará a este nodo pp

• Para determinar PIVOTE se debe tener en cuenta que los únicos nodos que pueden quedar desbalanceados son aquellos cuyo factor de balance es diferente de cero

• En concreto, PIVOTE es el nodo más cercano al nodo donde se hará la inserción, con factor de balance diferente de cero. Es bueno aclarar que es el nodo más cercano en la trayectoria desde la raíz hasta el nodo que será el padre del nuevo nodo

• Puede suceder que PIVOTE sea RAIZ, con factor de balance cero

• Inicialmente PIVOTE será la raíz y pp será NULL

class Nodo{ public:

int clave; Nodo *hijoIzq; //Apuntador a hijo izquierdo Nodo *hijoDer; //Apuntador a hijo derecho int FB; //Factor de Balance

public: Nodo(int dato);

};

Nodo::Nodo(int dato) //Constructor{

clave = dato;hijoIzq = NULL;hijoDer = NULL;FB=0;

}

class ArbolAVL{ public:

Nodo *raiz; //Apunta a la raíz del arbol Nodo *actual;

public:ArbolAVL(); //Constructorvoid insertar(int dato);

//Recorrido void inorden(Nodo *r);

//Rotacionesvoid Rotacion_a_la_Derecha(Nodo *P, Nodo *Q);void Rotacion_a_la_Izquierda(Nodo *P, Nodo *Q);

Nodo *Doble_Rotacion_a_la_Derecha(Nodo *P, Nodo *Q); Nodo *Doble_Rotacion_a_la_Izquierda(Nodo *P, Nodo *Q);};

//Constructor

ArbolAVL::ArbolAVL()

{

raiz=NULL;

actual=NULL;

}

//Rotaciones:void ArbolAVL::Rotacion_a_la_Derecha(Nodo *P, Nodo *Q){ P -> hijoIzq = Q -> hijoDer; Q -> hijoDer = P; P -> FB = 0; Q -> FB = 0;}

void ArbolAVL::Rotacion_a_la_Izquierda(Nodo *P, Nodo *Q){ P -> hijoDer = Q -> hijoIzq; Q -> hijoIzq = P; P -> FB = 0; Q -> FB = 0;}

Nodo *ArbolAVL::Doble_Rotacion_a_la_Derecha(Nodo *P, Nodo *Q){

Nodo *R = Q -> hijoDer; //Se obtiene R a partir de Qint factor_R = R->FB; //Se guarda el factor de balance de R

Rotacion_a_la_Izquierda(Q, R);Rotacion_a_la_Derecha(P, R);switch ( factor_R )

{ case 0: P -> FB = 0;

Q -> FB = 0; break;

case 1: P -> FB = -1;Q -> FB = 0;

break; case -1: P -> FB = 0;

Q -> FB = 1; break;

}R -> FB = 0; //Aunque sobra ya que las rotaciones ya lo han puesto en 0return R; //Se devuelve la raíz del árbol balanceado

}

Nodo *ArbolAVL::Doble_Rotacion_a_la_Izquierda(Nodo *P, Nodo *Q){

Nodo *R = Q -> hijoIzq; //Se obtiene R a partir de Qint factor_R = R->FB; //Se guarda el factor de balance de R

Rotacion_a_la_Derecha(Q, R); Rotacion_a_la_Izquierda(P, R);switch ( factor_R )

{ case 0: P -> FB = 0;

Q -> FB = 0;break;

case 1: P -> FB = 0;Q -> FB = -1;

break; case -1: P -> FB = 1;

Q -> FB = 0; break;

}R -> FB = 0; //Aunque sobra ya que las rotaciones ya lo han puesto en 0return R; //Se devuelve la raíz del árbol balanceado

}

//Algoritmo de Inserción:void ArbolAVL::insertar(int dato){

Nodo *x= new Nodo(dato); //Crea el nodo para el nuevo

Nodo *p = raiz; //Asigna valores iniciales a las variablesNodo *q = NULL; //que se utilizan para buscar el sitio dondeNodo *pivote = raiz; //se insertará el nuevo nodo y determinarNodo *pp= NULL; //pivote y su padre.

if(raiz == NULL) //Si árbol vacío{

raiz = actual = x; //El nuevo a su vez es la raíz y el actual}

else {

while (p != NULL){

if (p-> clave == dato) { //Controla repetidos delete(x);

return; } if (p->FB != 0) { //O sea que es -1 ó +1

pivote = p; //Determina el PIVOTE pp = q; //y su padre.

} q = p; //Actualiza qif ( p->clave > dato)

p = p -> hijoIzq; //Avanza con pelse

p = p -> hijoDer; //Avanza con p

}

if (q->clave > dato) q->hijoIzq = x; //Inserta x como hijo izquierdo

else // o como hijo derecho de q q->hijoDer = x;

//Recalcula factor de balance de PIVOTEif (pivote-> clave > dato)

{pivote->FB = pivote->FB +1; q = pivote-> hijoIzq;

}else{

pivote->FB = pivote->FB -1; q = pivote-> hijoDer;

}

//Recalcula factores de balance de todos los nodos en la//trayectoria desde PIVOTE hasta el nodo insertado x

p = q; while (p != x){

if (p->clave > dato) {

p->FB = 1; p = p->hijoIzq;

}else{

p->FB = -1; p = p->hijoDer;

} }

if (pivote->FB == 0 || pivote-> FB == -1 || pivote-> FB == 1)//Si el árbol siguió balanceado retorna return;

//Determina el tipo de rotaciónif (pivote->FB == 2 && q->FB == 1) Rotacion_a_la_Derecha(pivote,q);if (pivote->FB == -2 && q->FB == -1) Rotacion_a_la_Izquierda(pivote,q);if (pivote->FB == 2 && q->FB == -1) q=Doble_Rotacion_a_la_Derecha(pivote,q);if (pivote->FB == -2 && q->FB == 1) q=Doble_Rotacion_a_la_Izquierda(pivote,q);

// Si el nodo desbalanceado era la raíz lo actualiza y regresa. if (pp == NULL) {

raiz = q; return;

}

// Pega la nueva raíz del árbol rebalanceado (q) al nodo pp.if (pivote == pp->hijoIzq)

pp->hijoIzq = q; else

pp->hijoDer = q;}

}

void ArbolAVL::inorden(Nodo *r){

if(r){

inorden(r->hijoIzq);cout<<" "<<r->clave<<" ";inorden(r->hijoDer);

}}

void main(void){ //Se crea un árbol AVL

ArbolAVL miarbolAVL;

//Se insertan claves en el árbol:

miarbolAVL.insertar(9);miarbolAVL.insertar(6);miarbolAVL.insertar(1); //Desencadena rotación por la derecha

miarbolAVL.inorden(miarbolAVL.raiz);}

top related