El documento describe los árboles binarios. Define un árbol binario como un conjunto finito de nodos donde cada nodo tiene como máximo dos ramas o subárboles izquierdo y derecho. Explica propiedades como el número máximo de nodos por nivel y en total, y la relación entre nodos de grado 2 (internos) y hojas. También introduce árboles binarios completos y su altura en función del número de nodos. Finalmente, propone una primera aproximación a la clase árbol binario con operaciones básicas.
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)
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)))
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 i1 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 i1, 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
n1
å 2 2 2 =2
i −1 n n n1
= −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;
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.
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.
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.
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
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;
}
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, 23, 234,
red/black y Btrees
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;
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
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
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