Está en la página 1de 26

ESTRUCTURAS DE DATOS Y

ALGORITMOS I.

Conceptos de Árboles
y
Árboles Binarios.

Estructuras de Datos y Algoritmos I Hash Tables Página 0 de 27


Árboles.

• Un Árbol (tree) es una estructura de datos abstracta consistente de nodos


(nodes) conectados por aristas (edges) con un solo nodo superior llamado
nodo raíz y una (y sólo una) trayectoria del nodo raíz a cualquier otro nodo.
Tiene características que lo hacen una de las estructuras de datos más
interesantes:
• Los árboles combinan las ventajas de otras estructuras como los arreglos
ordenados y las listas ligadas sin sus desventajas.

Estructuras de Datos y Algoritmos I Hash Tables Página 1 de 27


Árboles (2).
• El algoritmo de búsqueda es rápido en los arreglos ordenados
(búsqueda binaria) del orden de O(logN). Sin embargo los procesos
de inserción y borrado son lentos, O(N), porque se tienen que
recorrer elementos para “hacer lugar” al elemento que se quiere
insertar.

• Los algoritmos de inserción y borrado son muy rápidos en las listas


ligadas, (implican solamente cambiar algunas referencias) del orden
de O(1). Sin embargo los algoritmos de búsqueda requieren visitar
todos los nodos antes del buscado lo cual los hace del orden O(N).

• Los árboles realizan estas operaciones, búsquedas, inserciones y


borrados, en forma muy rápida siempre y cuando el árbol esté bien
balanceado

Estructuras de Datos y Algoritmos I Hash Tables Página 2 de 27


Árboles Binarios.
• Los Árboles Binarios son los más simples.

• En este tipo de árboles cada nodo está conectado a


cero, uno o dos nodos inferiores llamados hijos.

• Existen otros tipos de árboles que son estructuras


mucho más complejas.

• Entre los más conocidos están:


– Árboles Rojinegros (Red-Black Trees)
– Árboles 2-3-4 (2-3-4 Trees)
– Árboles 2-3 (2-3 Trees)
– Árboles B (B-trees)

Estructuras de Datos y Algoritmos I Hash Tables Página 3 de 27


Terminología.

Estructuras de Datos y Algoritmos I Hash Tables Página 4 de 27


Terminología (2).
Node (node) Elemento del árbol que contiene los datos y normalmente la
llave. En C se representa mediante una struct.
Llave (key) Un dato de un nodo utilizado para identificarlo o visitarlo.
Arista o borde Elemento del árbol que define la relación de un nodo a otro.
(edge) Generalmente se representa mediante apuntadores.
Trayectoria o La secuencia de nodos y aristas resultante de viajar de un
Rama (path) nodo a otro a través de las aristas.
Nodo raíz Nodo superior del árbol, de donde inician todas las aristas.
(root) Un árbol contiene sólo un nodo raíz. Debe haber una y sólo
una trayectoria del nodo raíz a cualquier otro nodo.
Padre (parent) Nodo que tiene aristas hacia abajo.
Hijo(s) Nodo o nodos por debajo de un nodo dado.
(child<ren>
Hoja (leaf) Nodo que no tiene hijos

Estructuras de Datos y Algoritmos I Hash Tables Página 5 de 27


Terminología (3).
Árbol Binario Árbol en el que cada nodo tiene cuando más dos hijos.
(binary tree)
Hijo Izquierdo En un árbol binario, uno de los dos hijos de un nodo.
(left child)
Hijo Derecho En un árbol binario, el otro de los dos hijos de un nodo
(right child)
Subárbol Estructura consistente de cualquier nodo de un árbol,
(subtree) sus hijos y todos los hijos de sus hijos, i.e. todos sus
descendientes, junto con sus respectivas aristas.
Árbol balanceado Árbol que tiene (aproximadamente) el mismo número de
(balanced tree) nodos a ambos lado del nodo raíz.
Árbol desbalanceado Árbol en el cual el nodo raíz o algún otro tiene muchos
(unbalanced tree) más hijos derechos que izquierdos o viceversa.
Visitar Asignar el control del programa a un nodo determinado
(visiting) con objeto de realizar cualquier operación sobre él,
como examinarlo, desplegarlo, cambiar sus valores, etc.
Estructuras de Datos y Algoritmos I Hash Tables Página 6 de 27
Terminología (4).
Recorrer Visitar todos los nodos de un árbol en un orden
(traversing) determinado.
Nivel Número de generaciones de un nodo determinado a
(level) partir del nodo raíz, el cual se considera de nivel 0.
Árbol Binario de Árbol binario en el cual el hijo izquierdo de un nodo
Búsqueda debe tener un valor de llave menor al de su padre y el
(binary search tree) hijo derecho un valor de llave mayor o igual al de su
padre.

Estructuras de Datos y Algoritmos I Hash Tables Página 7 de 27


Demostración

Estructuras de Datos y Algoritmos I Hash Tables Página 8 de 27


Número de Nodos y Niveles.

Número de Nodos N Número de Niveles L


1 1
3 2
7 3
15 4
31 5
1,023 10
32,767 15
1,048,575 20
33.554.432 25
1,073,741,824 30

Estructuras de Datos y Algoritmos I Hash Tables Página 9 de 27


Eficiencia de los Árboles Binarios.

• La mayoría de las operaciones involucran descender de nivel en


nivel a un nodo en particular.
• Si el árbol está lleno, aproximadamente la mitad de los nodos
están en el nivel más bajo.
• Aproximadamente la mitad de las búsquedas, inserciones o
borrados requieren encontrar un nodo del nivel más bajo.
• Si N es el número de nodos y L es el número de niveles, N = 2L-1
(similar al caso de la búsqueda binaria) lo cual es equivalente a
L = log2(N+1).
• Entonces en notación de O mayúscula el tiempo para las
operaciones comunes es O(log(N))

Estructuras de Datos y Algoritmos I Hash Tables Página 10 de 27


Implementación de los Árboles Binarios.
• Normalmente en lenguaje C los árboles binarios se implementan
mediante structs.

• Cada nodo del árbol se implementa con una struct que contiene
dos struct interiores que representan el hijo izquierdo y el hijo
derechos

• Por ejemplo:

struct node {
int data;
struct node* right;
struct node* left;
};
Estructuras de Datos y Algoritmos I Hash Tables Página 11 de 27
Estructura Básica de un Árbol Binario.

// Ejemplo de un Árbol Binario


#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <locale.h>
// Definición de variables globales
struct node{
int data;
struct node* right;
struct node* left;
};
typedef struct node node;
node *root;
node *tmp;

Estructuras de Datos y Algoritmos I Hash Tables Página 12 de 27


Funciones Principales de un Árbol Binario.

// Definición de funciones

void insert(node ** tree, int val); // Inserta un nodo en el árbol


node* find(node ** tree, int val); // Buscar un nodo
void traverseInOrder(node * tree); // Recorre el árbol en orden
void traversePreOrder(); // Recorre el árbol en pre-orden
void traversePostOrder(); // Recorre el árbol en post-orden
void delTree(node * tree); // Borra todo el árbol

Nota. La función de borrar un nodo determinado del árbol es bastante


compleja puesto que depende de la posición del nodo que se
quiere borrar.

Estructuras de Datos y Algoritmos I Hash Tables Página 13 de 27


Función insert.

void insert(node ** tree, int val){


node *temp = NULL;
if(!(*tree)) { // primera vez
temp = (node *)malloc(sizeof(node));
temp->left = temp->right = NULL;
temp->data = val;
*tree = temp;
return;
}

if(val < (*tree)->data) {


insert(&(*tree)->left, val);
} else if(val > (*tree)->data) {
insert(&(*tree)->right, val);
}
}

Estructuras de Datos y Algoritmos I Hash Tables Página 14 de 27


Función find.

node* find(node ** tree, int val){


if(!(*tree)) {
return NULL;
}
if(val < (*tree)->data) {
find(&((*tree)->left), val);
} else if(val > (*tree)->data) {
find(&((*tree)->right), val);
} else if(val == (*tree)->data) {
return *tree;
}
}

Estructuras de Datos y Algoritmos I Hash Tables Página 15 de 27


Función traverseInOrder.

void traverseInorder(node * tree) {


if (tree) {
traverseInorder(tree->left);
printf("%d\n",tree->data);
traverseInorder(tree->right);
}
}

En esta forma de recorrido el


subárbol izquierdo se visita
primero, después el nodo raíz y
después el subárbol derecho. El
resultado es una lista de las
llaves en orden ascendente. En
el ejemplo, la salida sería:

D→B→E→A→F→C→G

Estructuras de Datos y Algoritmos I Hash Tables Página 16 de 27


Función traversePreOrder.

void traversePreorder(node * tree){


if (tree) {
printf("%d\n",tree->data);
traversePreorder(tree->left);
traversePreorder(tree->right);
}
}

En esta forma de recorrido el


nodo raíz se visita primero,
después el subárbol izquierdo y
finalmente el subárbol derecho.
En el ejemplo, la salida sería:

A→B→D→E→C→F→G

Estructuras de Datos y Algoritmos I Hash Tables Página 17 de 27


Función traversePostOrder.

void traversePostorder(node * tree){


if (tree){
traversePostorder(tree->left);
traversePostorder(tree->right);
printf("%d\n",tree->data);
}
}

En esta forma de recorrido el


nodo raíz es el último visitado.
Primero se recorre el subárbol
izquierdo, después el derecho y
finalmente el raíz. En el ejemplo,
la salida sería:

D→E→B→F→G→C→A

Estructuras de Datos y Algoritmos I Hash Tables Página 18 de 27


Función delTree.

void delTree(node * tree){


if (tree){
deltree(tree->left);
deltree(tree->right);
free(tree);
}
}

Estructuras de Datos y Algoritmos I Hash Tables Página 19 de 27


Función delTree.

void delTree(node * tree){


if (tree){
deltree(tree->left);
deltree(tree->right);
free(tree);
}
}

Estructuras de Datos y Algoritmos I Hash Tables Página 20 de 27


Diagrama de Actvidades para Función Delete.

Estructuras de Datos y Algoritmos I Hash Tables Página 21 de 27


Diagrama de Actvidades para Función Delete (2).

Estructuras de Datos y Algoritmos I Hash Tables Página 22 de 27


Diagrama de Actvidades para Función Delete (3).

Estructuras de Datos y Algoritmos I Hash Tables Página 23 de 27


Implementación Como Arreglo.

• También es posible implementar un Árbol Binario como


un arreglo.

• Esto no es recommendable porque los arreglos tienen


algunas limitaciones:

• Son de tamaño fijo, no pueden expandirse.


• Las funciones son siempre más lentas.
• Las funciones de borrado son muy complejas y
necesitan prácticamente reconstruir todo el arreglo.

Estructuras de Datos y Algoritmos I Hash Tables Página 24 de 27


Árbol Binario Representado Como Arreglo.

• El nodo raíz ocupa el índice 0


• Su hijo izquierdo el índice 1
• Su hijo derecho el índice 2 y así sucesivamente
• Si el índice de un Nodo es N:
• su hijo izquierdo es 2N+1
• su hijo izquierdo es 2N+2
Estructuras de Datos y Algoritmos I Hash Tables Página 25 de 27

También podría gustarte