SlideShare ist ein Scribd-Unternehmen logo
1 von 67
Downloaden Sie, um offline zu lesen
Árboles 

• Introducción
• Conjunto finito de nodos que cumple
• 1­ Existe un nodo especial llamado raíz (root)
• 2­ El resto de nodos están en n (n>= 0) particiones de 
  conjuntos disjuntos T1, T2, ……Tn donde cada uno de 
  estos conjuntos es un árbol. T1, T2, ……Tn son los 
  subárboles del nodo raíz.
• La definición es recursiva
• Disjuntos => no puede haber conexiones entre subárboles
Árboles
•   Nodo : información + ramas de conexión a otros nodos
•   El número de subárboles es el grado del nodo
•   Las hojas o nodos terminales tienen grado = 0
•   Los nodos raíz de los subárboles de un nodo X son sus 
    hijos
    – X es el nodo padre
    – Los nodos hijos son entre si hermanos (siblings)
Árboles
• El grado de un árbol es el grado máximo de sus nodos
• Los ancestros de un nodo son todos los nodos que hay en el 
  camino desde el nodo raíz hasta el nodo en cuestión
• El nivel de un nodo se define como sigue:
   – El nivel del nodo raíz es 1
   – Si un nodo está en el nivel L, sus hijos están en el nivel 
     L+1
• La altura o profundidad de un árbol es el máximo nivel
root (raiz)         Árboles                        Niveles
branch (rama)                     A                            1
                                           internal node 
                                           (nodo interno)
                B                 C            D               2

        E           F             G    H        I       J      3
                    leaf (hoja)
   K        L                          M                       4

  Lista ­­­­­  (A(B(E(K,L),F),C(G),D(H(M),I,J)))
Árboles
A


        C        D


            G             I   J


    B                 H


            F             M

        E


            K     L
Árboles

• Es deseable tener una representación específica para árboles
• El tamaño de los nodos puede ser variable o fijo
• Se suele utilizar tamaño fijo según el grado del árbol


   Info      Hijo1    Hijo2     ………. HijoN­1 HijoN



Si T es un árbol de grado k con n nodos de tamaño fijo, =>
n * ( k ­ 1 ) + 1 de los n * k campos hijo son 0, n>=1
Árboles
• Prueba:
•  El número de campos hijos distintos de cero en un árbol 
  de n nodos es n ­ 1 ( cada nodo es referenciado por una 
  conexión excepto el nodo raíz)
• El número total de campos hijo en un árbol de grado k con 
  n nodos será n * k 
• (n * k) ­ (n ­ 1) = n * ( k ­ 1) + 1 
Árboles
• Representación: Hijo Izquierdo ­ Hermano Derecho

      INFO                 A
   IZQ.  DER.

            B              C               D


       E        F          G        H          I     J


  K        L                       M
Árboles Binarios

• Cada nodo puede tener hasta dos ramas
                                                  K        K
• Se admite el concepto de árbol binario vacío
   – Cuando el número de nodos es cero
                                             L        ¹        L
• Definición:
   – Conjunto finito de nodos que; o bien está vacío o 
     consiste de un root y dos árboles binarios disjuntos 
     llamados subárbol izquierdo y subárbol derecho
Árboles Binarios
Propiedades:
(1) El número máximo de nodos en el nivel i es 2 , i³1
                                                      i−1




(2) El número máximo de nodos en un árbol de 
  profundidad k es   2 −1, k³1
                      k




(1) Demostración por inducción: si i == 1 => 2 = 2 =1
                                                1−1         0




Sea i >=1, suponemos que en el nivel i­1 el número de 
  nodos es 2
             i− 2




Como el grado máximo de cada nodo es 2, el máximo 
  número de nodos en el nivel i es dos veces el máximo 
  número de nodos en el nivel i­1,   2∗2 = 2
                                       i −2   i −1
Árboles Binarios
(2) El máximo número de nodos en un árbol binario de 
 k   profundidad k será:
å  max num kde nodos en el nivel i  =
i =1
                     å2                     2
                                i−1             k
                                        =           −1
                     i =1
                            2 = 2 −1     1−1             1

Por inducción: si i = 1 =>                      suponemos 
  validez para i = n y probaremos para i = n + 1

               n1


               å 2              2               2 =2
                     i −1           n                n       n1
                            =           −1                        −1
               i=1
Árboles Binarios

Relación entre el número de nodos de grado 2 y el 
   número de hojas: N0 = N2 + 1
N0: número de hojas, N2 número de nodos de grado 2
Sea N: número total de nodos y N1 los de grado 1
N = N0 + N1 + N2       (i)
El número de ramas B será igual al número de nodos
menos uno (root) => N = B + 1 = N1 + 2 * N2 + 1  (ii)
(i)­(ii) => 0 = N0 ­ N2 ­ 1 => N0 = N2 + 1;
Árboles Binarios
Definición: un árbol binario de profundidad k y N nodos
                            2 −1, k³0
se dice completo si tiene                     nodos y los nodos
                                   k




 están numerados desde 1 a N según la figura 
La altura H de un árbol 
                             1
binario completo de n 
nodos es: log  n1
               2




                   2                             3
                                                                   H
      4                     5           6                 7


  8        9           10       11 12       13       14       15
Árboles Binarios
•   Primera aproximación a la clase árbol binario
•   Conjunto mínimo de operaciones típicas 

template<class KeyType> class BinaryTree {
     //conjunto finito de nodos: root, left BinaryTree y rigth BinaryTree
public:
     BinaryTree(); //constructor por defecto: árbol vacío
     bool IsEmpty(); //verdadero si el árbol esta vacío
     BinaryTree( BinaryTree bt1, Element<KeyType> item, BinaryTree bt2 ); 
//Crea un árbol con root = ítem y subárboles bt1 y bt2
     BinaryTree LChild();
 //si no esta vacío retorna el subárbol izquierdo de *this 
      Element<KeyType> Data(); //retorna el root de *this
     BinaryTree RChild();
 //si no esta vacío retorna el subárbol derecho de *this
};
Árboles Binarios

• Representación mediante vectores de árboles 
  completos:
   – La posición cero del vector señala el árbol vacío
   – Para cualquier nodo i; 1 =< i =< n
   – padre( i ) estará en          si i     , i = 1 => root
                            ⌊i / 2⌋      ¹1

   – hijoizq( i ) estará en 2 * i  si 2 * i =< n
   – hijoder( i ) estará en 2 * i +1  si 2 * i +1=< n
• Si los árboles no son completos se 
  desperdicia espacio
Árboles Binarios
• Representación mediante enlaces:
    – La representación secuencial no es eficiente en 
      las inserciones y borrado de nodos intermedios
class Tree; (templates)
class TreeNode {                         Data

      friend class Tree;
                                  LeftChild RightChild
     TreeNode *LeftChild;
      char Data;                LeftChild Data RightChild
     TreeNode *RightChild;
};
Árboles Binarios

• Representación mediante enlaces:

class Tree {
public:
// operaciones
private:
      TreeNode *root;
};
Árboles Binarios
                     Representaciones
                          A                       0   ­­­
                                                  1   A
              B                       C           2   B
                                                  3   C
        D         0 E 0       0 F 0       0 G 0   4   D
                                                  5   E
                                                  6   F
0 H 0       0 I 0
                                                  7   G
                                                  8   H
                                                  9   I
Árboles Binarios
•   Recorridos ­ Iteradores
•   L: movimiento a la izquierda
•   V: “visitar” el nodo
•   R: movimiento a la derecha
•   Hay seis combinaciones posibles de recorrido
     – LVR, LRV, VLR, VRL, RVL, RLV
     – Si optamos por realizar primero el movimiento a 
       izquierda, tenemos las tres primeras posibilidades
     – LVR inorden, LRV postorden, VLR preorden
Árboles Binarios
                                            +
• Recorridos ­ Iteradores
• Los recorridos se corresponden                E
                                        *
  con las formas infija, postfija y 
  prefija.
                                    *       D
Inorden A/B*C*D+E

                            /           C
Preorden +**/ABCDE
                     A              B

Postorden AB/C*D*E+
Árboles Binarios



• Inorden
  – Descender por la izquierda hasta donde se 
    pueda, visitar el nodo, moverse un nodo a la 
    derecha y continuar. Si no se puede ir a la 
    derecha, volver un nodo hacia atrás.
Árboles Binarios
void Tree::inorder() {
inorder( root );
}
void Tree::inorder(TreeNode *CurrentNode)
{
  if(CurrentNode){
     inorder(CurrentNode­>LeftChild);
     cout << CurrentNode­>Data;
     inorder(CurrentNode­>RightChild);
  }
}
Árboles Binarios


• Preorden
  – Visitar un nodo, descender por la izquierda, así 
    hasta donde se pueda. Cuando no se pueda 
    continuar, moverse a la derecha y comenzar 
    nuevamente o volver hacia atrás hasta que se 
    pueda mover a la derecha y continuar.
Árboles Binarios
void Tree::preorder() {
preorder( root);
}
void Tree::preorder(TreeNode *CurrentNode)
{
  if(CurrentNode){
     cout << CurrentNode­>Data;
     preorder(CurrentNode­>LeftChild);
     preorder(CurrentNode­>RightChild);
  }
}
Árboles Binarios


• Postorden
  – Descender por la izquierda, así hasta donde se 
    pueda. Cuando no se pueda continuar, moverse a 
    la derecha hasta que se pueda, visitar el nodo, 
    volver hacia atrás y comenzar nuevamente.
Árboles Binarios
void Tree::postorder() {
postorder( root);
}
void Tree::postorder(TreeNode *CurrentNode)
{
  if(CurrentNode){
     postorder(CurrentNode­>LeftChild);
     postorder(CurrentNode­>RightChild);
     cout << CurrentNode­>Data;
  }
}
void Tree::NoRecInorder() {                    Árboles Binarios
   stack<TreeNode *> s;
   TreeNode *CurrentNode = root;
   while(true){
       while(CurrentNode) {
               s.push(CurrentNode);
               CurrentNode = CurrentNode­>LeftChild;
       }
       if(!s.empty()){
               CurrentNode = s.top(); s.pop();
               cout << CurrentNode­>Data<<endl;
               CurrentNode=CurrentNode­>RightChild;
       }else break;
   }
}
void Tree::Levelorder() {             Árboles Binarios
  queue<TreeNode *> q;
  TreeNode *CurrentNode = root;  q.push(CurrentNode);
  while(!q.empty()) {
         CurrentNode = q.top(); q.pop(); //q.front()
         cout << CurrentNode­>Data<<endl;
         if(CurrentNode­>LeftChild)
              q.push(CurrentNode­>LeftChild);
         if(CurrentNode­>RightChild)
              q.push(CurrentNode­>RightChild);
  }
}
Árboles Binarios


class InorderIterator {
public:
   char * Next();
    InorderIterator(Tree tree): t(tree) {CurrentNode  = t.root;}
private:
Tree t;
stack<TreeNode *> s;
TreeNode *CurrentNode;
};
char *InorderIterator::Next() {       Árboles Binarios
  while(CurrentNode) {
      s.push(CurrentNode);
    CurrentNode = CurrentNode­>LeftChild;
  }
  if(!s.empty()){
      CurrentNode = s.top(); s.pop();
      char& temp = CurrentNode­>Data;
      CurrentNode=CurrentNode­>RightChild;
      return &temp;
      }else return 0;
}
• Copia                              Árboles Binarios
Tree::Tree(const Tree& s) {
       root = copy(s.root);
}
TreeNode* Tree::copy(TreeNode* orignode) {
       if(orignode){
             TreeNode *temp = new TreeNode;
             temp­>Data = orignode­>Data;
             temp­>LeftChild = copy(orignode­>LeftChild);
             temp­>RightChild = copy(orignode­>RightChild);
             return temp;
       }else return 0;
}
• Igualdad                            Árboles Binarios
bool operator==(const Tree& s, const Tree& t){
        return equal(s.root, t.root);
}
bool equal(TreeNode *a, TreeNode *b){
    if(!a && !b) return 1;
    if(a && b && (a­>Data == b­>Data) && 
        equal(a­>LeftChild, b­>LeftChild) && 
        equal(a­>RightChild , b­>RightChild) ) 
        return 1;
return 0;
}
Árboles Binarios

• Árbol de búsqueda:
  – Cuando los nodos respetan la relación de orden:
     • El hijo izquierdo de cualquier nodo es menor que su 
       padre y 
     • El hijo derecho es mayor que su padre
• Se dice que un árbol binario es balanceado 
  cuando la diferencia de altura de todo par 
  de  subárboles es menor o igual que 1 
Árboles Binarios


• La búsqueda es de complejidad O(       )
                                      log
                                        2   n



• La inserción se realiza buscando el valor a 
  insertar y cuando se llega a una hoja (sin 
  haber hallado el valor) se inserta a la 
  izquierda o derecha de ésta.
• El borrado depende del grado del nodo a 
  eliminar.   
Árboles Binarios de Búsqueda

                20                      30        60

      15              25            5        40             70

 12        10              22   2                      65        80


                a                       b                   c
• Cada nodo tendrá tres campos: LeftChild, RightChild y data.
• data es una clase con al menos un campo key.
• La clase árbol binario de búsqueda la llamaremos BST
Árboles de Búsqueda
template<class Type>
BstNode<Type>* BST<Type>::Search(const Element<Type>& x)
{
    return Search(root, x);
}
template<class Type>
BstNode<Type>* BST<Type>::Search(BstNode<Type> *b, 
                                      const Element<Type>& x) {
if(!b) return 0;
if(x.key == b­>data.key) return b;
if(x.key < b­>data.key) return Search(b­>LeftChild, x);
return Search(b­>RightChild, x);
}
Árboles de Búsqueda

template<class Type>
BstNode<Type>* BST<Type>::IterSearch(
                                    const Element<Type>& x) 
{
   for(BstNode<Type> *t = root; t) {
       if(x.key == t­>data.key) return t;
       if(x.key < t­>data.key) t = t­>LeftChild;
       else t = t­>RightChild;
   }
   return 0;
}
January      Inserción de los meses 
                          según su orden natural

  February             March

April              June    May

  August      July             September

        December          October

                     November
template<class Type>                               Árboles de Búsqueda 
bool BST<Type>::Insert( const Element<Type>& x) { Inserción
   BstNode<Type> *p= root; BstNode<Type> *q=0;
   while(p){
                 q=p; 
                 if(x.key == p­>data.key) return false;
                 if(x.key < p­>data.key) p = p­>LeftChild;
                 else p = p­>RightChild;
        }
   p = new BstNode<Type>;
   p­>LeftChild = p­>RightChild = 0; p­>data = x;
   if(!root) root = p;
   else if(x.key < q­>data.key) q­>LeftChild = p;
          else q­>RightChild = p;
   return true;
}
January           Árboles de Búsqueda 
                                     Borrado


  February             March           Eliminado 
                                          July: 
April              June    May          grado 0

  August                        September

        December          October
                                   Se pone a 0 el enlace 
                                   correspondiente del 
                    November       nodo padre
January              Árboles de Búsqueda 
                                Borrado
                         Eliminados 
April       March      February y May: 
                           grado 1
  August June    September

      December October
                         Se reemplaza el nodo 
          November       eliminado por su subárbol 
January                    Árboles de Búsqueda 
                                            Borrado

  April              November           Eliminado 
                                     March: grado 2
      August June             September

            December October
Se debe reemplazar el nodo a eliminar por el nodo mayor de su 
subárbol izquierdo (predecesor inorden) o por el nodo menor de 
su subárbol derecho (sucesor inorden).
A continuación se elimina el nodo utilizado en el reemplazo que 
siempre será de grado < 2.
Árboles de Búsqueda 
                              Borrado

template<class Type> 
BstNode<Type>* BST<Type>::IterSearchDelete(const Element< Type > & x, 
   BstNode<Type>*& q) //retorna la dirección del nodo y la dirección del padre 
   (p)
{                        // si no esta retorna 0
   BstNode<Type> *p= root;
   while(p){
                if(x.key == p­>data.key) return p;
                q=p;
                if(x.key < p­>data.key) p = p­>LeftChild;
                else p = p­>RightChild;
   }
   return p;
}
Árboles de Búsqueda 
template<class Type>                                        Borrado
bool BST<Type>::Delete( const Element< Type > & x ) 
{
   BstNode<Type>  *parent=0;
   BstNode<Type>*  pos = IterSearchDelete(x, parent); 
   if(pos) { remove(pos, parent); delete pos; return true;} 
   else return false;
}

template<class Type>
void BST<Type>::remove(BstNode<Type>*  pos, BstNode<Type>*  parent ) 
{
   if(!pos­>LeftChild ) // no tiene subárbol izquierdo
        if(!pos­>RightChild) remove_leaf(pos, parent); // es de grado 0
        else remove_right(pos, parent); // grado 1, tiene subárbol derecho
   else if(!pos­>RightChild) remove_left(pos, parent); // grado 1, tiene subárbol 
   izq.
        else remove_both(pos, parent); // grado 2
}
Árboles de Búsqueda 
                           Borrado


template<class Type>
void BST<Type>::remove_leaf(BstNode<Type>*  pos,  BstNode<Type>* p) 
{ //el nodo a eliminar tiene grado 0 (hoja)
    if(pos == root) root = 0;
    else if (p­>LeftChild == pos) p­>LeftChild = 0;
        else p­>RightChild = 0;
}
Árboles de Búsqueda 
template<class Type>       Borrado
void BST<Type>::remove_right(BstNode<Type>*  pos, BstNode<Type>* p)
{//el nodo a eliminar tiene grado 1(subárbol derecho)
    BstNode<Type>* lr = pos­>RightChild;
    if(pos == root) root = lr;
    else if (p­>LeftChild == pos) p­>LeftChild = lr;
          else p­>RightChild = lr;
}
template<class Type>
void BST<Type>::remove_left(BstNode<Type>*  pos, BstNode<Type>* p)
{//el nodo a eliminar tiene grado 1 (subárbol izquierdo)
    BstNode<Type>* ll = pos­>LeftChild;
    if(pos == root) root = ll;
    else if (p­>LeftChild == pos) p­>LeftChild = ll;
          else p­>RightChild = ll;
}
Árboles de Búsqueda 
template<class Type>          Borrado
void BST<Type>::remove_both(BstNode<Type>*  pos, BstNode<Type>* pa)
{//el nodo a eliminar tiene grado 2
        BstNode<Type>* lr = pos­>RightChild; 
        BstNode<Type>* plr = pos­>RightChild;
        if(!lr­>LeftChild)plr = 0;
        for( ;   lr­>LeftChild; lr = lr­>LeftChild);
        if(plr) for( ; plr­>LeftChild != lr; plr = plr­>LeftChild);
        if(pa){ if (pa­>LeftChild == pos) pa­>LeftChild = lr;
                  else pa­>RightChild = lr;
        }else root = lr; //deleting root
        BstNode<key,T>* r = lr­>RightChild;
        lr­>LeftChild  = pos­>LeftChild;
        if(pos ­>RightChild != lr)   lr­>RightChild = pos­> RightChild ;
        if(plr) plr­>LeftChild = r;
}
Árboles de Búsqueda 
• Altura: si no se tiene cuidado, la altura de un árbol 
  de búsqueda de n nodos puede llegar a ser n (lista) 
   – Se pierde toda la eficiencia de búsqueda
      • O(n)
   – Si las inserciones son aleatorias => O(        )
                                               log2   n


• Los árboles con O(        ) se denominan árboles de 
                       log2   n


  búsqueda balanceados
   – Los de mayor utilidad son los AVL, 2­3, 2­3­4, 
     red/black y B­trees
Árboles Enhebrados
• En un árbol binario hay más punteros null que 
  punteros a nodos
• En un árbol binario de n nodos hay 2n punteros, de 
  los cuales n+1 son null
•  Se puede utilizar estos punteros para conseguir 
  ciertas ventajas
• Para diferenciarlos de los punteros no null le 
  llamaremos hebras
• Existen varias formas de enhebrado. Veremos el 
  inorden
Árboles Enhebrados
• La hebras se construyen de la siguiente forma:
   – Un 0 en un enlace derecho de un nodo p se 
     reemplaza por por un puntero al nodo que se 
     visitaría después de p en un recorrido en inorden 
     (sucesor inorden)
   – Un 0 en un enlace izquierdo de un nodo p se 
     reemplaza por por un puntero al nodo que se 
     visitaría antes de p en un recorrido en inorden 
     (predecesor inorden)
• Utilizaremos un nodo de cabecera. Será predecesor 
  del primer nodo y el sucesor del último nodo
Árboles Enhebrados          head
                            ­­­­­

                    root
                            A


               B                         C


          D         E               F            G


 t   H   tt    I    t           Puntero a Nodo
                                Hebra

     True LeftChild ­­­­­­ RightChild False
                   árbol 
                   vacío
class ThreadedNode {                     Árboles Enhebrados
friend class ThreadedTree;
                                        class ThreadedTree {
friend class ThreadedInorderIterator;
                                        friend class 
public:                                 ThreadedInorderIterator;
ThreadedNode(char c=‘0’) :Data(c),     public:
LeftThread(false), LeftChild(0),        ThreadedTree(){head = new 
RightChild(0),RightThread(false){}      ThreadedNode;}
private:                                bool empty();
   bool LeftThread;                     private:
    ThreadedNode *LeftChild;             ThreadedNode  *head;
   char Data;                           };
    ThreadedNode *RightChild;           bool ThreadedTree::empty(){
   bool RightThread; };                 if(!head || head­>LeftChild == 
                                        head && head­>RightChild 
                                        ==head) return true;
Árboles Enhebrados
class ThreadedInorderIterator {
public:
   char * Next();
   void Inorder();
    ThreadedInorderIterator (ThreadedTree tree): t(tree) 
   {CurrentNode  = t.head;}
private:
ThreadedTree t;
ThreadedNode *CurrentNode;
};
Árboles Enhebrados
char* ThreadedInorderIterator::Next() {
  ThreadedNode *temp = CurrentNode­>RightChild;
  if(! CurrentNode­>RightThread)
      while(!temp­>LeftThread ) temp = temp­>LeftChild;
  CurrentNode = temp;
  if( CurrentNode == t.head) return 0;
  else return  &CurrentNode­>Data;
}
void ThreadedInorderIterator::Inorder() {
  for( char *ch = Next(); ch; ch = Next() )
      cout << *ch << endl;
}
Árboles Enhebrados
• Para encontrar el sucesor, si su enlace derecho es 
  una hebra, es inmediato, si no lo es, bastará 
  recorrer, a partir de la posición que señala dicho 
  enlace, todos los nodos a su izquierda hasta 
  encontrar la primera hebra
• Para encontrar el predecesor, si su enlace izquierdo 
  es una hebra, es inmediato, si no lo es, bastará 
  recorrer, a partir de la posición que señala dicho 
  enlace, todos los nodos a su derecha hasta encontrar 
  la primera hebra
Árboles Enhebrados
ThreadedNode *ThreadedTree::InorderSucc(ThreadedNode *r) {
  ThreadedNode *temp = r­>RightChild;
  if(r­>RightThread) return temp;
  while(!temp­>LeftThread ) temp = temp­>LeftChild;
  return  temp;
}
ThreadedNode *ThreadedTree::InorderPred(ThreadedNode *r) {
  ThreadedNode *temp = r­>LeftChild;
  if(r­>LeftThread) return temp;
  while(!temp­>RightThread ) temp = temp­>RightChild;
  return  temp;
}
Árboles Enhebrados

void ThreadedTree::Inorder(ThreadedNode *head) {
ThreadedNode *temp = head;
  while(true){
      temp = InorderSucc(temp);
      if(temp == head) return;
      else  cout << temp­>Data << endl;
  }
}
Árboles Enhebrados
• La inserción es simple cuando se realiza en 
  la posición que ocupa una hebra
• Cuando no se inserta sobre una hebra, se 
  debe encontrar el predecesor ó el sucesor 
  inorden del nodo a partir del que se 
  insertará
  – El predecesor si la inserción es por la izquierda
     • se asigna una hebra con la dirección del nuevo 
       nodo, al enlace derecho del predecesor
  – El sucesor si la inserción es por la derecha
     • se asigna una hebra con la dirección del nuevo 
       nodo, al enlace izquierdo del sucesor
Árboles Enhebrados
void ThreadedTree::InsertLeft(ThreadedNode *x, char c) {
  ThreadedNode *p = new ThreadedNode(c);
  p­>LeftChild = x­>LeftChild;
  x­>LeftChild = p;
  p­>LeftThread = x­>LeftThread; x­>LeftThread = false;
  p­>RightChild = x;
  p­>RightThread = true; 
  if(!p­>LeftThread) {
      ThreadedNode *aux = InorderPred(p);
      aux­>RightChild = p;
      aux­>RightThread = true; 
  } // Falta contemplar la inserción en un árbol vacío
}
Árboles Enhebrados
void ThreadedTree::InsertRight(ThreadedNode *x, char c) {
    ThreadedNode *p = new ThreadedNode(c); 
   p­>RightChild = x­>RightChild;
   p­>RightThread = x­>RightThread; 
   p­>LeftChild = x;
   p­>LeftThread = true; 
   x­>RightChild = p;
   x­>RightThread = false; 
   if(!p­>RightThread) {
       ThreadedNode * aux = InorderSucc(p);
       aux­>LeftChild = p; //Este enlace ya era una hebra
   }if(p­>RightChild == head) head­>LeftChild = p;
}// Falta contemplar la inserción en un árbol vacío 
Árboles Enhebrados
void ThreadedTree::InsertLeftHead(char c) {
   ThreadedNode *p = new ThreadedNode(c); 
  head­>RightChild = head­>LeftChild  = p;
  p­>RightThread = p­>LeftThread = true; 
}

void ThreadedTree::InsertRightHead(char c) {
   ThreadedNode *p = new ThreadedNode(c); 
  head­>RightChild = head­>LeftChild  = p;
  p­>RightThread = p­>LeftThread = true; 
}
head                                  head


         A                                        A


    B                  D              B                   D


C
    x          E           G    C         x           E       G


                                 p
                   F                          H           F

        Inserción a la izquierda de x: 
        el subárbol izquierdo de x está vacío
head                                   head


    x         A                             x       A

                                        p
        B                   D                   I                  D


C                   E           G           B              E           G


                        F           C                          F

            Inserción a la izquierda de x: 
            el subárbol izquierdo de x es no vacío
• Ventajas
                              Árboles Enhebrados
   – Las hebras evitan el uso de recursividad o pilas
   – Recorrido inorden más rápido
   – Determinación del sucesor y el predecesor 
     inorden muy simple y eficiente.
   – Mediante otro tipo de enhebrado se pueden 
     conseguir los mismos resultados para otros 
     recorridos
• Inconvenientes
   – No se pueden compartir subárboles
   – Espacio extra para identificar las hebras
   – Inserciones y supresiones menos eficientes 
HEAP
                  20              •Árbol binario balanceado 
                                  y parcialmente ordenado
                                •Todo nodo debe ser 
     15                      10 mayor que sus hijos
                                •El root será el mayor 
                                nodo

12         10           8         •Al ser balanceados se 
                                  puede utilizar la 
                                  representación secuencial
 Se puede construir un HEAP a partir de una secuencia de 
 objetos, simplemente reorganizando. La STL provee la 
 el patrón de función make_heap
15
                           HEAP
                                                              15
                          Inserción
        9                 12                     9                     12

    5        8        4        3       11                 8        4        3

2       11                         2             5
Se realiza al final de la               15
secuencia (balance) y luego 
mediante intercambios se  11                         12
coloca en la posición 
correcta (push_heap) 9             8         4            3

                  2            5
HEAP
                                                                     12
                             Borrado
         11                 12                         11                      

    9           8       4        3            9                 8         4       3

2        5                               2             5
                                                                12
Se retira el root, se lo reemplaza
por el mayor de sus hijos                         11                      4
y se repite el proceso (pop_heap deja 
el nodo al final de la secuencia)   9                       8                 3

                                     2            5

Weitere ähnliche Inhalte

Empfohlen

2024 State of Marketing Report – by Hubspot
2024 State of Marketing Report – by Hubspot2024 State of Marketing Report – by Hubspot
2024 State of Marketing Report – by HubspotMarius Sescu
 
Everything You Need To Know About ChatGPT
Everything You Need To Know About ChatGPTEverything You Need To Know About ChatGPT
Everything You Need To Know About ChatGPTExpeed Software
 
Product Design Trends in 2024 | Teenage Engineerings
Product Design Trends in 2024 | Teenage EngineeringsProduct Design Trends in 2024 | Teenage Engineerings
Product Design Trends in 2024 | Teenage EngineeringsPixeldarts
 
How Race, Age and Gender Shape Attitudes Towards Mental Health
How Race, Age and Gender Shape Attitudes Towards Mental HealthHow Race, Age and Gender Shape Attitudes Towards Mental Health
How Race, Age and Gender Shape Attitudes Towards Mental HealthThinkNow
 
AI Trends in Creative Operations 2024 by Artwork Flow.pdf
AI Trends in Creative Operations 2024 by Artwork Flow.pdfAI Trends in Creative Operations 2024 by Artwork Flow.pdf
AI Trends in Creative Operations 2024 by Artwork Flow.pdfmarketingartwork
 
PEPSICO Presentation to CAGNY Conference Feb 2024
PEPSICO Presentation to CAGNY Conference Feb 2024PEPSICO Presentation to CAGNY Conference Feb 2024
PEPSICO Presentation to CAGNY Conference Feb 2024Neil Kimberley
 
Content Methodology: A Best Practices Report (Webinar)
Content Methodology: A Best Practices Report (Webinar)Content Methodology: A Best Practices Report (Webinar)
Content Methodology: A Best Practices Report (Webinar)contently
 
How to Prepare For a Successful Job Search for 2024
How to Prepare For a Successful Job Search for 2024How to Prepare For a Successful Job Search for 2024
How to Prepare For a Successful Job Search for 2024Albert Qian
 
Social Media Marketing Trends 2024 // The Global Indie Insights
Social Media Marketing Trends 2024 // The Global Indie InsightsSocial Media Marketing Trends 2024 // The Global Indie Insights
Social Media Marketing Trends 2024 // The Global Indie InsightsKurio // The Social Media Age(ncy)
 
Trends In Paid Search: Navigating The Digital Landscape In 2024
Trends In Paid Search: Navigating The Digital Landscape In 2024Trends In Paid Search: Navigating The Digital Landscape In 2024
Trends In Paid Search: Navigating The Digital Landscape In 2024Search Engine Journal
 
5 Public speaking tips from TED - Visualized summary
5 Public speaking tips from TED - Visualized summary5 Public speaking tips from TED - Visualized summary
5 Public speaking tips from TED - Visualized summarySpeakerHub
 
ChatGPT and the Future of Work - Clark Boyd
ChatGPT and the Future of Work - Clark Boyd ChatGPT and the Future of Work - Clark Boyd
ChatGPT and the Future of Work - Clark Boyd Clark Boyd
 
Getting into the tech field. what next
Getting into the tech field. what next Getting into the tech field. what next
Getting into the tech field. what next Tessa Mero
 
Google's Just Not That Into You: Understanding Core Updates & Search Intent
Google's Just Not That Into You: Understanding Core Updates & Search IntentGoogle's Just Not That Into You: Understanding Core Updates & Search Intent
Google's Just Not That Into You: Understanding Core Updates & Search IntentLily Ray
 
Time Management & Productivity - Best Practices
Time Management & Productivity -  Best PracticesTime Management & Productivity -  Best Practices
Time Management & Productivity - Best PracticesVit Horky
 
The six step guide to practical project management
The six step guide to practical project managementThe six step guide to practical project management
The six step guide to practical project managementMindGenius
 
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...RachelPearson36
 

Empfohlen (20)

2024 State of Marketing Report – by Hubspot
2024 State of Marketing Report – by Hubspot2024 State of Marketing Report – by Hubspot
2024 State of Marketing Report – by Hubspot
 
Everything You Need To Know About ChatGPT
Everything You Need To Know About ChatGPTEverything You Need To Know About ChatGPT
Everything You Need To Know About ChatGPT
 
Product Design Trends in 2024 | Teenage Engineerings
Product Design Trends in 2024 | Teenage EngineeringsProduct Design Trends in 2024 | Teenage Engineerings
Product Design Trends in 2024 | Teenage Engineerings
 
How Race, Age and Gender Shape Attitudes Towards Mental Health
How Race, Age and Gender Shape Attitudes Towards Mental HealthHow Race, Age and Gender Shape Attitudes Towards Mental Health
How Race, Age and Gender Shape Attitudes Towards Mental Health
 
AI Trends in Creative Operations 2024 by Artwork Flow.pdf
AI Trends in Creative Operations 2024 by Artwork Flow.pdfAI Trends in Creative Operations 2024 by Artwork Flow.pdf
AI Trends in Creative Operations 2024 by Artwork Flow.pdf
 
Skeleton Culture Code
Skeleton Culture CodeSkeleton Culture Code
Skeleton Culture Code
 
PEPSICO Presentation to CAGNY Conference Feb 2024
PEPSICO Presentation to CAGNY Conference Feb 2024PEPSICO Presentation to CAGNY Conference Feb 2024
PEPSICO Presentation to CAGNY Conference Feb 2024
 
Content Methodology: A Best Practices Report (Webinar)
Content Methodology: A Best Practices Report (Webinar)Content Methodology: A Best Practices Report (Webinar)
Content Methodology: A Best Practices Report (Webinar)
 
How to Prepare For a Successful Job Search for 2024
How to Prepare For a Successful Job Search for 2024How to Prepare For a Successful Job Search for 2024
How to Prepare For a Successful Job Search for 2024
 
Social Media Marketing Trends 2024 // The Global Indie Insights
Social Media Marketing Trends 2024 // The Global Indie InsightsSocial Media Marketing Trends 2024 // The Global Indie Insights
Social Media Marketing Trends 2024 // The Global Indie Insights
 
Trends In Paid Search: Navigating The Digital Landscape In 2024
Trends In Paid Search: Navigating The Digital Landscape In 2024Trends In Paid Search: Navigating The Digital Landscape In 2024
Trends In Paid Search: Navigating The Digital Landscape In 2024
 
5 Public speaking tips from TED - Visualized summary
5 Public speaking tips from TED - Visualized summary5 Public speaking tips from TED - Visualized summary
5 Public speaking tips from TED - Visualized summary
 
ChatGPT and the Future of Work - Clark Boyd
ChatGPT and the Future of Work - Clark Boyd ChatGPT and the Future of Work - Clark Boyd
ChatGPT and the Future of Work - Clark Boyd
 
Getting into the tech field. what next
Getting into the tech field. what next Getting into the tech field. what next
Getting into the tech field. what next
 
Google's Just Not That Into You: Understanding Core Updates & Search Intent
Google's Just Not That Into You: Understanding Core Updates & Search IntentGoogle's Just Not That Into You: Understanding Core Updates & Search Intent
Google's Just Not That Into You: Understanding Core Updates & Search Intent
 
How to have difficult conversations
How to have difficult conversations How to have difficult conversations
How to have difficult conversations
 
Introduction to Data Science
Introduction to Data ScienceIntroduction to Data Science
Introduction to Data Science
 
Time Management & Productivity - Best Practices
Time Management & Productivity -  Best PracticesTime Management & Productivity -  Best Practices
Time Management & Productivity - Best Practices
 
The six step guide to practical project management
The six step guide to practical project managementThe six step guide to practical project management
The six step guide to practical project management
 
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
 

Árboles binarios

  • 1. Árboles  • Introducción • Conjunto finito de nodos que cumple • 1­ Existe un nodo especial llamado raíz (root) • 2­ El resto de nodos están en n (n>= 0) particiones de  conjuntos disjuntos T1, T2, ……Tn donde cada uno de  estos conjuntos es un árbol. T1, T2, ……Tn son los  subárboles del nodo raíz. • La definición es recursiva • Disjuntos => no puede haber conexiones entre subárboles
  • 2. Árboles • Nodo : información + ramas de conexión a otros nodos • El número de subárboles es el grado del nodo • Las hojas o nodos terminales tienen grado = 0 • Los nodos raíz de los subárboles de un nodo X son sus  hijos – X es el nodo padre – Los nodos hijos son entre si hermanos (siblings)
  • 3. Árboles • El grado de un árbol es el grado máximo de sus nodos • Los ancestros de un nodo son todos los nodos que hay en el  camino desde el nodo raíz hasta el nodo en cuestión • El nivel de un nodo se define como sigue: – El nivel del nodo raíz es 1 – Si un nodo está en el nivel L, sus hijos están en el nivel  L+1 • La altura o profundidad de un árbol es el máximo nivel
  • 4. root (raiz) Árboles Niveles branch (rama) A 1 internal node  (nodo interno) B C D 2 E F G H I J 3 leaf (hoja) K L M 4 Lista ­­­­­  (A(B(E(K,L),F),C(G),D(H(M),I,J)))
  • 5. Árboles A C D G I J B H F M E K L
  • 6. Árboles • Es deseable tener una representación específica para árboles • El tamaño de los nodos puede ser variable o fijo • Se suele utilizar tamaño fijo según el grado del árbol Info Hijo1 Hijo2 ………. HijoN­1 HijoN Si T es un árbol de grado k con n nodos de tamaño fijo, => n * ( k ­ 1 ) + 1 de los n * k campos hijo son 0, n>=1
  • 7. Árboles • Prueba: •  El número de campos hijos distintos de cero en un árbol  de n nodos es n ­ 1 ( cada nodo es referenciado por una  conexión excepto el nodo raíz) • El número total de campos hijo en un árbol de grado k con  n nodos será n * k  • (n * k) ­ (n ­ 1) = n * ( k ­ 1) + 1 
  • 9. Árboles Binarios • Cada nodo puede tener hasta dos ramas K K • Se admite el concepto de árbol binario vacío – Cuando el número de nodos es cero L ¹ L • Definición: – Conjunto finito de nodos que; o bien está vacío o  consiste de un root y dos árboles binarios disjuntos  llamados subárbol izquierdo y subárbol derecho
  • 10. Árboles Binarios Propiedades: (1) El número máximo de nodos en el nivel i es 2 , i³1 i−1 (2) El número máximo de nodos en un árbol de  profundidad k es   2 −1, k³1 k (1) Demostración por inducción: si i == 1 => 2 = 2 =1 1−1 0 Sea i >=1, suponemos que en el nivel i­1 el número de  nodos es 2 i− 2 Como el grado máximo de cada nodo es 2, el máximo  número de nodos en el nivel i es dos veces el máximo  número de nodos en el nivel i­1,   2∗2 = 2 i −2 i −1
  • 11. Árboles Binarios (2) El máximo número de nodos en un árbol binario de  k profundidad k será: å  max num kde nodos en el nivel i  = i =1 å2 2 i−1 k = −1 i =1 2 = 2 −1 1−1 1 Por inducción: si i = 1 =>                      suponemos  validez para i = n y probaremos para i = n + 1 n1 å 2 2 2 =2 i −1 n n n1 = −1  −1 i=1
  • 12. Árboles Binarios Relación entre el número de nodos de grado 2 y el  número de hojas: N0 = N2 + 1 N0: número de hojas, N2 número de nodos de grado 2 Sea N: número total de nodos y N1 los de grado 1 N = N0 + N1 + N2       (i) El número de ramas B será igual al número de nodos menos uno (root) => N = B + 1 = N1 + 2 * N2 + 1  (ii) (i)­(ii) => 0 = N0 ­ N2 ­ 1 => N0 = N2 + 1;
  • 13. Árboles Binarios Definición: un árbol binario de profundidad k y N nodos 2 −1, k³0 se dice completo si tiene                     nodos y los nodos k  están numerados desde 1 a N según la figura  La altura H de un árbol  1 binario completo de n  nodos es: log  n1 2 2 3 H 4 5 6 7 8 9 10 11 12 13 14 15
  • 14. Árboles Binarios • Primera aproximación a la clase árbol binario • Conjunto mínimo de operaciones típicas  template<class KeyType> class BinaryTree { //conjunto finito de nodos: root, left BinaryTree y rigth BinaryTree public: BinaryTree(); //constructor por defecto: árbol vacío bool IsEmpty(); //verdadero si el árbol esta vacío BinaryTree( BinaryTree bt1, Element<KeyType> item, BinaryTree bt2 );  //Crea un árbol con root = ítem y subárboles bt1 y bt2 BinaryTree LChild();  //si no esta vacío retorna el subárbol izquierdo de *this   Element<KeyType> Data(); //retorna el root de *this BinaryTree RChild();  //si no esta vacío retorna el subárbol derecho de *this };
  • 15. Árboles Binarios • Representación mediante vectores de árboles  completos: – La posición cero del vector señala el árbol vacío – Para cualquier nodo i; 1 =< i =< n – padre( i ) estará en          si i     , i = 1 => root ⌊i / 2⌋ ¹1 – hijoizq( i ) estará en 2 * i  si 2 * i =< n – hijoder( i ) estará en 2 * i +1  si 2 * i +1=< n • Si los árboles no son completos se  desperdicia espacio
  • 16. Árboles Binarios • Representación mediante enlaces: – La representación secuencial no es eficiente en  las inserciones y borrado de nodos intermedios class Tree; (templates) class TreeNode { Data friend class Tree; LeftChild RightChild   TreeNode *LeftChild; char Data; LeftChild Data RightChild   TreeNode *RightChild; };
  • 18. Árboles Binarios Representaciones A 0 ­­­ 1 A B C 2 B 3 C D 0 E 0 0 F 0 0 G 0 4 D 5 E 6 F 0 H 0 0 I 0 7 G 8 H 9 I
  • 19. Árboles Binarios • Recorridos ­ Iteradores • L: movimiento a la izquierda • V: “visitar” el nodo • R: movimiento a la derecha • Hay seis combinaciones posibles de recorrido – LVR, LRV, VLR, VRL, RVL, RLV – Si optamos por realizar primero el movimiento a  izquierda, tenemos las tres primeras posibilidades – LVR inorden, LRV postorden, VLR preorden
  • 20. Árboles Binarios + • Recorridos ­ Iteradores • Los recorridos se corresponden  E * con las formas infija, postfija y  prefija. * D Inorden A/B*C*D+E / C Preorden +**/ABCDE A B Postorden AB/C*D*E+
  • 21. Árboles Binarios • Inorden – Descender por la izquierda hasta donde se  pueda, visitar el nodo, moverse un nodo a la  derecha y continuar. Si no se puede ir a la  derecha, volver un nodo hacia atrás.
  • 22. Árboles Binarios void Tree::inorder() { inorder( root ); } void Tree::inorder(TreeNode *CurrentNode) { if(CurrentNode){ inorder(CurrentNode­>LeftChild); cout << CurrentNode­>Data; inorder(CurrentNode­>RightChild); } }
  • 23. Árboles Binarios • Preorden – Visitar un nodo, descender por la izquierda, así  hasta donde se pueda. Cuando no se pueda  continuar, moverse a la derecha y comenzar  nuevamente o volver hacia atrás hasta que se  pueda mover a la derecha y continuar.
  • 24. Árboles Binarios void Tree::preorder() { preorder( root); } void Tree::preorder(TreeNode *CurrentNode) { if(CurrentNode){ cout << CurrentNode­>Data; preorder(CurrentNode­>LeftChild); preorder(CurrentNode­>RightChild); } }
  • 25. Árboles Binarios • Postorden – Descender por la izquierda, así hasta donde se  pueda. Cuando no se pueda continuar, moverse a  la derecha hasta que se pueda, visitar el nodo,  volver hacia atrás y comenzar nuevamente.
  • 26. Árboles Binarios void Tree::postorder() { postorder( root); } void Tree::postorder(TreeNode *CurrentNode) { if(CurrentNode){ postorder(CurrentNode­>LeftChild); postorder(CurrentNode­>RightChild); cout << CurrentNode­>Data; } }
  • 27. void Tree::NoRecInorder() { Árboles Binarios stack<TreeNode *> s; TreeNode *CurrentNode = root; while(true){ while(CurrentNode) { s.push(CurrentNode);   CurrentNode = CurrentNode­>LeftChild; } if(!s.empty()){ CurrentNode = s.top(); s.pop(); cout << CurrentNode­>Data<<endl; CurrentNode=CurrentNode­>RightChild; }else break; } }
  • 28. void Tree::Levelorder() {  Árboles Binarios queue<TreeNode *> q; TreeNode *CurrentNode = root;  q.push(CurrentNode); while(!q.empty()) {    CurrentNode = q.top(); q.pop(); //q.front()    cout << CurrentNode­>Data<<endl;    if(CurrentNode­>LeftChild)  q.push(CurrentNode­>LeftChild);    if(CurrentNode­>RightChild)  q.push(CurrentNode­>RightChild); } }
  • 29. Árboles Binarios class InorderIterator { public: char * Next();  InorderIterator(Tree tree): t(tree) {CurrentNode  = t.root;} private: Tree t; stack<TreeNode *> s; TreeNode *CurrentNode; };
  • 30. char *InorderIterator::Next() {  Árboles Binarios while(CurrentNode) { s.push(CurrentNode);   CurrentNode = CurrentNode­>LeftChild; } if(!s.empty()){ CurrentNode = s.top(); s.pop(); char& temp = CurrentNode­>Data; CurrentNode=CurrentNode­>RightChild; return &temp; }else return 0; }
  • 31. • Copia Árboles Binarios Tree::Tree(const Tree& s) { root = copy(s.root); } TreeNode* Tree::copy(TreeNode* orignode) { if(orignode){       TreeNode *temp = new TreeNode;       temp­>Data = orignode­>Data;       temp­>LeftChild = copy(orignode­>LeftChild);       temp­>RightChild = copy(orignode­>RightChild);       return temp;      }else return 0; }
  • 32. • Igualdad Árboles Binarios bool operator==(const Tree& s, const Tree& t){ return equal(s.root, t.root); } bool equal(TreeNode *a, TreeNode *b){ if(!a && !b) return 1; if(a && b && (a­>Data == b­>Data) &&      equal(a­>LeftChild, b­>LeftChild) &&          equal(a­>RightChild , b­>RightChild) )  return 1; return 0; }
  • 33. Árboles Binarios • Árbol de búsqueda: – Cuando los nodos respetan la relación de orden: • El hijo izquierdo de cualquier nodo es menor que su  padre y  • El hijo derecho es mayor que su padre • Se dice que un árbol binario es balanceado  cuando la diferencia de altura de todo par  de  subárboles es menor o igual que 1 
  • 34. Árboles Binarios • La búsqueda es de complejidad O(       ) log 2 n • La inserción se realiza buscando el valor a  insertar y cuando se llega a una hoja (sin  haber hallado el valor) se inserta a la  izquierda o derecha de ésta. • El borrado depende del grado del nodo a  eliminar.   
  • 35. Árboles Binarios de Búsqueda 20 30 60 15 25 5 40 70 12 10 22 2 65 80 a b c • Cada nodo tendrá tres campos: LeftChild, RightChild y data. • data es una clase con al menos un campo key. • La clase árbol binario de búsqueda la llamaremos BST
  • 36. Árboles de Búsqueda template<class Type> BstNode<Type>* BST<Type>::Search(const Element<Type>& x) { return Search(root, x); } template<class Type> BstNode<Type>* BST<Type>::Search(BstNode<Type> *b,   const Element<Type>& x) { if(!b) return 0; if(x.key == b­>data.key) return b; if(x.key < b­>data.key) return Search(b­>LeftChild, x); return Search(b­>RightChild, x); }
  • 37. Árboles de Búsqueda template<class Type> BstNode<Type>* BST<Type>::IterSearch(    const Element<Type>& x)  { for(BstNode<Type> *t = root; t) { if(x.key == t­>data.key) return t; if(x.key < t­>data.key) t = t­>LeftChild; else t = t­>RightChild; } return 0; }
  • 38. January Inserción de los meses  según su orden natural February March April June May August July September December October November
  • 39. template<class Type> Árboles de Búsqueda  bool BST<Type>::Insert( const Element<Type>& x) { Inserción BstNode<Type> *p= root; BstNode<Type> *q=0; while(p){ q=p;  if(x.key == p­>data.key) return false; if(x.key < p­>data.key) p = p­>LeftChild; else p = p­>RightChild; } p = new BstNode<Type>; p­>LeftChild = p­>RightChild = 0; p­>data = x; if(!root) root = p; else if(x.key < q­>data.key) q­>LeftChild = p;   else q­>RightChild = p; return true; }
  • 40. January Árboles de Búsqueda  Borrado February March Eliminado  July:  April June May grado 0 August September December October Se pone a 0 el enlace  correspondiente del  November nodo padre
  • 41. January Árboles de Búsqueda  Borrado Eliminados  April March February y May:  grado 1 August June September December October Se reemplaza el nodo  November eliminado por su subárbol 
  • 42. January Árboles de Búsqueda  Borrado April November Eliminado  March: grado 2 August June September December October Se debe reemplazar el nodo a eliminar por el nodo mayor de su  subárbol izquierdo (predecesor inorden) o por el nodo menor de  su subárbol derecho (sucesor inorden). A continuación se elimina el nodo utilizado en el reemplazo que  siempre será de grado < 2.
  • 43. Árboles de Búsqueda  Borrado template<class Type>  BstNode<Type>* BST<Type>::IterSearchDelete(const Element< Type > & x,  BstNode<Type>*& q) //retorna la dirección del nodo y la dirección del padre  (p) { // si no esta retorna 0 BstNode<Type> *p= root; while(p){ if(x.key == p­>data.key) return p; q=p; if(x.key < p­>data.key) p = p­>LeftChild; else p = p­>RightChild; } return p; }
  • 44. Árboles de Búsqueda  template<class Type> Borrado bool BST<Type>::Delete( const Element< Type > & x )  { BstNode<Type>  *parent=0; BstNode<Type>*  pos = IterSearchDelete(x, parent);  if(pos) { remove(pos, parent); delete pos; return true;}  else return false; } template<class Type> void BST<Type>::remove(BstNode<Type>*  pos, BstNode<Type>*  parent )  { if(!pos­>LeftChild ) // no tiene subárbol izquierdo if(!pos­>RightChild) remove_leaf(pos, parent); // es de grado 0 else remove_right(pos, parent); // grado 1, tiene subárbol derecho else if(!pos­>RightChild) remove_left(pos, parent); // grado 1, tiene subárbol  izq.   else remove_both(pos, parent); // grado 2 }
  • 45. Árboles de Búsqueda  Borrado template<class Type> void BST<Type>::remove_leaf(BstNode<Type>*  pos,  BstNode<Type>* p)  { //el nodo a eliminar tiene grado 0 (hoja) if(pos == root) root = 0; else if (p­>LeftChild == pos) p­>LeftChild = 0; else p­>RightChild = 0; }
  • 46. Árboles de Búsqueda  template<class Type> Borrado void BST<Type>::remove_right(BstNode<Type>*  pos, BstNode<Type>* p) {//el nodo a eliminar tiene grado 1(subárbol derecho) BstNode<Type>* lr = pos­>RightChild; if(pos == root) root = lr; else if (p­>LeftChild == pos) p­>LeftChild = lr; else p­>RightChild = lr; } template<class Type> void BST<Type>::remove_left(BstNode<Type>*  pos, BstNode<Type>* p) {//el nodo a eliminar tiene grado 1 (subárbol izquierdo) BstNode<Type>* ll = pos­>LeftChild; if(pos == root) root = ll; else if (p­>LeftChild == pos) p­>LeftChild = ll;       else p­>RightChild = ll; }
  • 47. Árboles de Búsqueda  template<class Type> Borrado void BST<Type>::remove_both(BstNode<Type>*  pos, BstNode<Type>* pa) {//el nodo a eliminar tiene grado 2 BstNode<Type>* lr = pos­>RightChild;  BstNode<Type>* plr = pos­>RightChild; if(!lr­>LeftChild)plr = 0; for( ;   lr­>LeftChild; lr = lr­>LeftChild); if(plr) for( ; plr­>LeftChild != lr; plr = plr­>LeftChild); if(pa){ if (pa­>LeftChild == pos) pa­>LeftChild = lr; else pa­>RightChild = lr; }else root = lr; //deleting root BstNode<key,T>* r = lr­>RightChild; lr­>LeftChild  = pos­>LeftChild; if(pos ­>RightChild != lr)   lr­>RightChild = pos­> RightChild ; if(plr) plr­>LeftChild = r; }
  • 48. Árboles de Búsqueda  • Altura: si no se tiene cuidado, la altura de un árbol  de búsqueda de n nodos puede llegar a ser n (lista)  – Se pierde toda la eficiencia de búsqueda • O(n) – Si las inserciones son aleatorias => O(        ) log2 n • Los árboles con O(        ) se denominan árboles de  log2 n búsqueda balanceados – Los de mayor utilidad son los AVL, 2­3, 2­3­4,  red/black y B­trees
  • 49. Árboles Enhebrados • En un árbol binario hay más punteros null que  punteros a nodos • En un árbol binario de n nodos hay 2n punteros, de  los cuales n+1 son null •  Se puede utilizar estos punteros para conseguir  ciertas ventajas • Para diferenciarlos de los punteros no null le  llamaremos hebras • Existen varias formas de enhebrado. Veremos el  inorden
  • 50. Árboles Enhebrados • La hebras se construyen de la siguiente forma: – Un 0 en un enlace derecho de un nodo p se  reemplaza por por un puntero al nodo que se  visitaría después de p en un recorrido en inorden  (sucesor inorden) – Un 0 en un enlace izquierdo de un nodo p se  reemplaza por por un puntero al nodo que se  visitaría antes de p en un recorrido en inorden  (predecesor inorden) • Utilizaremos un nodo de cabecera. Será predecesor  del primer nodo y el sucesor del último nodo
  • 51. Árboles Enhebrados head ­­­­­ root A B C D E F G t H tt I t Puntero a Nodo Hebra True LeftChild ­­­­­­ RightChild False árbol  vacío
  • 52. class ThreadedNode { Árboles Enhebrados friend class ThreadedTree; class ThreadedTree { friend class ThreadedInorderIterator; friend class  public: ThreadedInorderIterator; ThreadedNode(char c=‘0’) :Data(c), public: LeftThread(false), LeftChild(0), ThreadedTree(){head = new  RightChild(0),RightThread(false){} ThreadedNode;} private: bool empty(); bool LeftThread; private:  ThreadedNode *LeftChild;  ThreadedNode  *head; char Data; };  ThreadedNode *RightChild; bool ThreadedTree::empty(){ bool RightThread; }; if(!head || head­>LeftChild ==  head && head­>RightChild  ==head) return true;
  • 53. Árboles Enhebrados class ThreadedInorderIterator { public: char * Next(); void Inorder();  ThreadedInorderIterator (ThreadedTree tree): t(tree)  {CurrentNode  = t.head;} private: ThreadedTree t; ThreadedNode *CurrentNode; };
  • 54. Árboles Enhebrados char* ThreadedInorderIterator::Next() { ThreadedNode *temp = CurrentNode­>RightChild; if(! CurrentNode­>RightThread) while(!temp­>LeftThread ) temp = temp­>LeftChild; CurrentNode = temp; if( CurrentNode == t.head) return 0; else return  &CurrentNode­>Data; } void ThreadedInorderIterator::Inorder() { for( char *ch = Next(); ch; ch = Next() ) cout << *ch << endl; }
  • 55. Árboles Enhebrados • Para encontrar el sucesor, si su enlace derecho es  una hebra, es inmediato, si no lo es, bastará  recorrer, a partir de la posición que señala dicho  enlace, todos los nodos a su izquierda hasta  encontrar la primera hebra • Para encontrar el predecesor, si su enlace izquierdo  es una hebra, es inmediato, si no lo es, bastará  recorrer, a partir de la posición que señala dicho  enlace, todos los nodos a su derecha hasta encontrar  la primera hebra
  • 56. Árboles Enhebrados ThreadedNode *ThreadedTree::InorderSucc(ThreadedNode *r) { ThreadedNode *temp = r­>RightChild; if(r­>RightThread) return temp; while(!temp­>LeftThread ) temp = temp­>LeftChild; return  temp; } ThreadedNode *ThreadedTree::InorderPred(ThreadedNode *r) { ThreadedNode *temp = r­>LeftChild; if(r­>LeftThread) return temp; while(!temp­>RightThread ) temp = temp­>RightChild; return  temp; }
  • 57. Árboles Enhebrados void ThreadedTree::Inorder(ThreadedNode *head) { ThreadedNode *temp = head; while(true){ temp = InorderSucc(temp); if(temp == head) return; else  cout << temp­>Data << endl; } }
  • 58. Árboles Enhebrados • La inserción es simple cuando se realiza en  la posición que ocupa una hebra • Cuando no se inserta sobre una hebra, se  debe encontrar el predecesor ó el sucesor  inorden del nodo a partir del que se  insertará – El predecesor si la inserción es por la izquierda • se asigna una hebra con la dirección del nuevo  nodo, al enlace derecho del predecesor – El sucesor si la inserción es por la derecha • se asigna una hebra con la dirección del nuevo  nodo, al enlace izquierdo del sucesor
  • 59. Árboles Enhebrados void ThreadedTree::InsertLeft(ThreadedNode *x, char c) { ThreadedNode *p = new ThreadedNode(c); p­>LeftChild = x­>LeftChild; x­>LeftChild = p; p­>LeftThread = x­>LeftThread; x­>LeftThread = false; p­>RightChild = x; p­>RightThread = true;  if(!p­>LeftThread) { ThreadedNode *aux = InorderPred(p); aux­>RightChild = p; aux­>RightThread = true;  } // Falta contemplar la inserción en un árbol vacío }
  • 60. Árboles Enhebrados void ThreadedTree::InsertRight(ThreadedNode *x, char c) {  ThreadedNode *p = new ThreadedNode(c);  p­>RightChild = x­>RightChild; p­>RightThread = x­>RightThread;  p­>LeftChild = x; p­>LeftThread = true;  x­>RightChild = p; x­>RightThread = false;  if(!p­>RightThread) { ThreadedNode * aux = InorderSucc(p); aux­>LeftChild = p; //Este enlace ya era una hebra }if(p­>RightChild == head) head­>LeftChild = p; }// Falta contemplar la inserción en un árbol vacío 
  • 61. Árboles Enhebrados void ThreadedTree::InsertLeftHead(char c) {  ThreadedNode *p = new ThreadedNode(c);  head­>RightChild = head­>LeftChild  = p; p­>RightThread = p­>LeftThread = true;  } void ThreadedTree::InsertRightHead(char c) {  ThreadedNode *p = new ThreadedNode(c);  head­>RightChild = head­>LeftChild  = p; p­>RightThread = p­>LeftThread = true;  }
  • 62. head head A A B D B D C x E G C x E G p F H F Inserción a la izquierda de x:  el subárbol izquierdo de x está vacío
  • 63. head head x A x A p B D I D C E G B E G F C F Inserción a la izquierda de x:  el subárbol izquierdo de x es no vacío
  • 64. • Ventajas Árboles Enhebrados – Las hebras evitan el uso de recursividad o pilas – Recorrido inorden más rápido – Determinación del sucesor y el predecesor  inorden muy simple y eficiente. – Mediante otro tipo de enhebrado se pueden  conseguir los mismos resultados para otros  recorridos • Inconvenientes – No se pueden compartir subárboles – Espacio extra para identificar las hebras – Inserciones y supresiones menos eficientes 
  • 65. HEAP 20 •Árbol binario balanceado  y parcialmente ordenado •Todo nodo debe ser  15 10 mayor que sus hijos •El root será el mayor  nodo 12 10 8 •Al ser balanceados se  puede utilizar la  representación secuencial Se puede construir un HEAP a partir de una secuencia de  objetos, simplemente reorganizando. La STL provee la  el patrón de función make_heap
  • 66. 15 HEAP 15 Inserción 9 12 9 12 5 8 4 3 11 8 4 3 2 11 2 5 Se realiza al final de la  15 secuencia (balance) y luego  mediante intercambios se  11 12 coloca en la posición  correcta (push_heap) 9 8 4 3 2 5
  • 67. HEAP   12 Borrado 11 12 11   9 8 4 3  9 8 4 3 2 5 2 5 12 Se retira el root, se lo reemplaza por el mayor de sus hijos 11 4 y se repite el proceso (pop_heap deja  el nodo al final de la secuencia)  9 8 3 2 5