You are on page 1of 18

ESTRUCTURAS DE DATOS

ARBOLES BINARIOS y ARBOL-B.

1 DE SEPTIEMBRE DE 2017
UNIVERSIDAD NACIONAL DE PIURA.
INGENIERIA INFORMATICA
OBJETIVOS:
1) Estructurar datos en orden.
2) Conocer la terminología de un árbol.
3) Conocer los diferentes tipos de árboles binarios.
4) Saber recorrer un árbol en sus tres formas diferente.
5) Utilizar un árbol binario en una expresión algebraica.
6) Construir arboles de búsqueda.
7) Saber los procedimientos de los árbol B.
Árbol:
1. Definición:
Un árbol es una estructura (posiblemente no lineal) de datos compuesta de nodos,
vértices y aristas que es acíclica. Un árbol que no tiene ningún nodo se llama
árbol vacío o nulo. Un árbol que no está vacío consta de un nodo raíz y potencialmente
muchos niveles de nodos adicionales que forman una jerarquía.

2. Terminología:

 Raíz: El nodo superior de un árbol.

 Hijo: Un nodo conectado directamente con otro cuando se aleja de la raíz.

 Padre: La noción inversa de hijo.

 Hermanos: Un conjunto de nodos con el mismo padre.

 Descendiente: Un nodo accesible por descenso repetido de padre a hijo.

 Ascendiente: Un nodo accesible por ascenso repetido de hijo a padre.

 Hoja (llamado menos comúnmente nodo externo): Un nodo sin hijos.

 Nodo interno: Un nodo con al menos un hijo.

 Grado: Número de subárboles de un nodo.

 Brazo: La conexión entre un nodo y otro.

 Camino: Una secuencia de nodos y brazos conectados con un nodo descendiente.

 Nivel: El nivel de un nodo se define por 1 + (el número de conexiones entre el nodo y
la raíz).

 Altura de un nodo: La altura de un nodo es el número de aristas en el camino más


largo entre ese nodo y una hoja.

 Altura de un árbol: La altura de un árbol es la altura de su nodo raíz.

 Profundidad: La profundidad de un nodo es el número de aristas desde la raíz del


árbol hasta un nodo.
ARBOLES BINARIOS
1. Definición:
Un árbol binario es un árbol cuyos nodos no pueden tener más de dos subárboles. En un
árbol
binario, cada nodo puede tener cero, uno o dos hijos (subárboles). Se conoce el nodo de
la izquierda
como hijo izquierdo y el nodo de la derecha como hijo derecho.
Un árbol binario es una estructura recursiva. Cada nodo es la raíz de su propio subárbol y
tiene hijos, que son raíces de árboles, llamados subárboles derecho e izquierdo del nodo,
respectivamente.
Un árbol binario se divide en tres subconjuntos disjuntos:
{R} Nodo raíz.
{I1, I2, ...In} Subárbol izquierdo de R.
{D1, D2, ...Dn} Subárbol derecho de R.

2. Árboles binarios completos:


Un árbol binario completo de profundidad n es un árbol en el que para cada nivel, del 0
al nivel n-1, tiene un conjunto lleno de nodos, y todos los nodos hoja a nivel n ocupan las
posiciones más a la izquierda del árbol.
Un árbol binario completo que contiene 2n nodos a nivel n es un árbol lleno. Un árbol lleno
es un árbol binario que tiene el máximo número de entradas para su altura. Esto sucede
cuando el último nivel está lleno.
Árbol completo con profundidad 5
fklnvwbcdbvuewb

Ejemplo:
Suponiendo que se tiene n = 10.000 elementos que van a ser los nodos de un árbol binario
completo. Determinar la profundidad del árbol.
En el árbol binario completo con n nodos, la profundidad del árbol es el valor entero de
log2 n + 1, que es a su vez la distancia del camino más largo desde la raíz a un nodo más
uno.
Profundidad = int (log2 10000) + 1 = int (13.28) + 1 = 14
3. TAD Árbol binario:
La estructura de árbol binario constituye un tipo abstracto de datos; las operaciones
básicas que
definen el TAD árbol binario son las siguientes:
Tipo de dato: Dato que se almacena en los nodos del árbol.
Operaciones
Crear Árbol: Inicia el árbol como vacío.
Construir: Crea un árbol con un elemento raíz y dos ramas, izquierda y derecha
que son a su vez árboles.
Es Vacío: Comprueba si el árbol no tiene nodos.
Raíz: Devuelve el nodo raíz.
Izquierdo: Obtiene la rama o subárbol izquierdo de un árbol dado.
Derecho: Obtiene la rama o subárbol derecho de un árbol dado.
Borrar: Elimina del árbol el nodo con un elemento determinado.
Pertenece Determina si un elemento se encuentra en el árbol.
4. ESTRUCTURA DE UN ARBOL BINARIO:
Un árbol binario se construye con nodos. Cada nodo debe contener el campo dato
(datos a almacenar) y dos campos de enlace (apuntador), uno al subárbol izquierdo
(izquierdo, izdo) y otro al subárbol derecho (derecho, dcho). El valor null indica un árbol o
un subárbol vacío.
La Figura muestra la representación enlazada de dos árboles binarios de raíz A. El primero
es un árbol degenerado a la izquierda; el segundo es un árbol binario completo de
profundidad 4.
5. Creación de un árbol binario:
A partir del nodo raíz de un árbol se puede acceder a los demás nodos del árbol, por ello
se mantiene la referencia a la raíz del árbol. Las ramas izquierda y derecha son, a su vez,
árboles binarios que tienen su raíz, y así recursivamente hasta llegar a las hojas del árbol.
La clase ArbolBinario tiene el campo raíz, un constructor que inicializa raíz y métodos para
implementar las operaciones:
1) package arbolBinario;
2) public class ArbolBinario
3) {
4) protected Nodo raiz;
5) public ArbolBinario()
6) {
7) raiz = null;
8) }
9) public ArbolBinario(Nodo raiz)
10) {
11) this.raiz = raiz;
12) }
13) public Nodo raizArbol()
14) {
15) return raiz;
16) }
17) // Comprueba el estatus del árbol
18) boolean esVacio()
19) {
20) return raiz == null;
21) }
22) // ...
El método nuevoArbol() crea un árbol de raíz un nodo con el campo dato, rama izquierda
y derecha pasadas en los argumentos.
1) public static Nodo nuevoArbol(
2) Nodo ramaIzqda, Object dato, Nodo ramaDrcha)
3) {
4) return new Nodo(ramaIzqda, dato, ramaDrcha);
5) }
Así, para crear el árbol binario de la Figura, se utiliza un esquema secuencial y con una
Pila que guarda, en cada paso, los subárboles:
1) import TipoPila.PilaVector;
2) ArbolBinario arbol;
3) Nodo a1, a2, a;
4) PilaVector pila = new PilaVector();
5) a1 = ArbolBinario.nuevoArbol(null,"Maria",null);
6) a2 = ArbolBinario.nuevoArbol(null,"Rodrigo",null);
7) a = ArbolBinario.nuevoArbol(a1,"Esperanza",a2);
8) pila.insertar(a);
9) a1 = ArbolBinario.nuevoArbol(null,"Anyora",null);
10) a2 = ArbolBinario.nuevoArbol(null,"Abel",null);
11) a = ArbolBinario.nuevoArbol(a1,"M Jesus",a2);
12) pila.insertar(a);
13) a2 = (Nodo) pila.quitar();
14) a1 = (Nodo) pila.quitar();
15) a = ArbolBinario.nuevoArbol(a1,"Esperanza",a2);
16) arbol = new ArbolBinario(a);

6.ÁRBOL DE EXPRESIÓN:
Una aplicación muy importante de los árboles binarios son los árboles de expresiones. Una
expresión es una secuencia de tokens (componentes de léxicos que siguen unas reglas
establecidas). Un token puede ser un operando o bien un operador.

Una expresión infija y su árbol de expresión

La Figura representa la expresión infija a * (b + c) + d junto a su árbol de expresión.


El nombre de infija es debido a que los operadores se sitúan entre los operandos.
Un árbol de expresión es un árbol binario con las siguientes propiedades:
1. Cada hoja es un operando.
2. Los nodos raíz y los nodos internos son operadores.
3. Los subárboles son subexpresiones cuyo nodo raíz es un operador.
7.RECORRIDOS DE ARBOLES BINARIOS:
Recorrido en Preorden:
En este tipo de recorrido se realiza cierta acción (quizás simplemente imprimir por pantalla
el valor de la clave de ese nodo) sobre el nodo actual y posteriormente se trata el
subárbol izquierdo y cuando se haya concluido, el subárbol derecho. Otra forma para
entender el recorrido con este método seria seguir el orden: nodo raíz, nodo izquierdo,
nodo derecha.
En el árbol de la figura el recorrido en preorden sería: 2, 7, 2, 6, 5, 11, 5, 9 y 4.

1) void preorden(tArbol *a)


2) {
3) if (a != NULL) {
4) tratar(a); //Realiza una operación en nodo
5) preorden(a->hIzquierdo);
6) preorden(a->hDerecho);
7) }
8) }
Implementación en pseudocódigo de forma iterativa:

1) push(s,NULL); //insertamos en una pila (stack) el valor NULL, para asegurarnos de que esté vacía
2) push(s,raíz); //insertamos el nodo raíz
3) MIENTRAS (s <> NULL) HACER
4) p = pop(s); //sacamos un elemento de la pila
5) tratar(p); //realizamos operaciones sobre el nodo p
6) SI (D(p) <> NULL) //preguntamos si p tiene árbol derecho
7) ENTONCES push(s,D(p));
8) FIN-SI
9) SI (I(p) <> NULL) //preguntamos si p tiene árbol izquierdo
10) ENTONCES push(s,I(p));
11) FIN-SI
12) FIN-MIENTRAS

Recorrido en postorden:
En este caso se trata primero el subárbol izquierdo, después el derecho y por último el
nodo actual. Otra forma para entender el recorrido con este método seria seguir el orden:
nodo izquierdo, nodo derecha, nodo raíz. En el árbol de la figura el recorrido en postorden
sería: 2, 5, 11, 6, 7, 4, 9, 5 y 2.

1) void postorden(tArbol *a)


2) {
3) if (a != NULL) {
4) postorden(a->hIzquiedo);
5) postorden(a->hDerecho);
6) tratar(a); //Realiza una operación en nodo
7) }
8) }

D-E-B-F-G-C-A.

Recorrido en inorden:
En este caso se trata primero el subárbol izquierdo, después el nodo actual y por último el
subárbol derecho. En un ABB este recorrido daría los valores de clave ordenados de
menor a mayor. Otra forma para entender el recorrido con este método seria seguir el
orden: nodo izquierdo, nodo raíz, nodo derecha. En el árbol de la figura el recorrido en
inorden sería: 2, 7, 5, 6, 11, 2, 5, 4, 9.
Esquema de implementación:

1) void inorden(tArbol *a)


2) {
3) if (a != NULL) {
4) inorden(a->hIzquierdo);
5) tratar(a); //Realiza una operación en nodo
6) inorden(a->hDerecho);
7) }
8) }

8.ÁRBOL BINARIO DE BUSQUEDA:


Los árboles estudiados hasta ahora no tienen un orden definido; sin embargo, los árboles
binarios ordenados tienen sentido. Estos árboles se denominan árboles binarios de
búsqueda, debido a que se puede buscar en ellos un término utilizando un algoritmo de
búsqueda binaria similar al empleado en arrays.
Un árbol binario de búsqueda es aquel en que, dado un nodo, todos los datos del
subárbol izquierdo son menores que los datos de ese nodo, mientras que todos los datos
del subárbol derecho son mayores que sus propios datos. El árbol binario del Ejemplo 13.8
es de búsqueda.
Ejemplo:
Árbol binario de búsqueda para nodos con el campo de datos de tipo int.

OPERACIONES EN ÁRBOLES BINARIOS DE BUSQUEDA:


Estas operaciones son:
• Búsqueda de un nodo. Devuelve la referencia al nodo del árbol o null.
• Inserción de un nodo. Crea un nodo con su dato asociado y lo añade, en orden, al
árbol.
• Borrado de un nodo. Busca el nodo del árbol que contiene un dato y lo quita. El árbol
debe seguir siendo de búsqueda.
• Recorrido de un árbol. Los mismos recorridos de un árbol binario preorden, inorden y
postorden.
La clase ArbolBinarioBusqueda implementa estas operaciones. Se considera que es una
extensión (herencia) de ArbolBinario.
1) package arbolBinarioOrdenado;
2) import arbolBinario.*;
3) public class ArbolBinarioBusqueda extends ArbolBinario
4) {
5) public ArbolBinarioBusqueda()
6) {
7) super();
8) }
9) //....
Búsqueda:
La búsqueda de un nodo comienza en el nodo raíz y sigue estos pasos:
1. La clave buscada se compara con la clave del nodo raíz.
2. Si las claves son iguales, la búsqueda se detiene.
3. Si la clave buscada es mayor que la clave raíz, la búsqueda se reanuda en el subárbol
derecho. Si la clave buscada es menor que la clave raíz, la búsqueda se reanuda con el
subárbol izquierdo.
1) public Nodo buscar(Object buscado)
2) {
3) Comparador dato;
4) dato = (Comparador) buscado;
5) if (raiz == null)
6) return null;
7) else
8) return localizar(raizArbol(), dato);
9) }
10) protected Nodo localizar(Nodo raizSub, Comparador buscado)
11) {
12) if (raizSub == null)
13) return null;
14) else if (buscado.igualQue(raizSub.valorNodo()))
15) return raiz;
16) else if (buscado.menorQue(raizSub.valorNodo()))
17) return localizar(raizSub.subarbolIzdo(), buscado);
18) else
19) return localizar (raizSub.subarbolDcho(), buscado);
20) }

21) public Nodo buscarIterativo (Object buscado)


22) {
23) Comparador dato;
24) boolean encontrado = false;
25) Nodo raizSub = raiz;
26) dato = (Comparador) buscado;
27) while (!encontrado && raizSub != null)
28) {
29) if (dato.igualQue(raizSub.valorNodo()))
30) encontrado = true;
31) else if (dato.menorQue(raizSub.valorNodo()))
32) raizSub = raizSub.subarbolIzdo();
33) else
34) raizSub = raizSub.subarbolDcho();
35) }
36) return raizSub;
37) }
Insertar un nodo:
Para añadir un nodo al árbol, se sigue el camino de búsqueda y, al final del camino, se
enlaza el nuevo nodo; por consiguiente, siempre se inserta como hoja del árbol. El árbol
que resulta después de insertar el nodo sigue siendo de búsqueda.
En esencia, el algoritmo de inserción se apoya en la búsqueda de un elemento, de modo
que si se encuentra el elemento buscado, no es necesario hacer nada; en caso contrario,
se inserta el nuevo elemento justo en el lugar donde ha acabado la búsqueda (es decir,
en el lugar donde habría estado en el caso de existir).
Inserción en un árbol binario de búsqueda
Por ejemplo, al árbol de la Figura se le inserta el nodo 8. El proceso describe un camino de
búsqueda que comienza en la raíz 25; el nodo 8 debe estar en el subárbol izquierdo de 25
(8< 25). El nodo 10 es la raíz del subárbol actual, el nodo 8 debe estar en el subárbol
izquierdo (8< 10), que está actualmente vacío y, por tanto, ha terminado el camino de
búsqueda. El nodo 8 se enlaza como hijo izquierdo del nodo 10.
Implementación
El método insertar() es la interfaz de la operación, llama al método recursivo que realiza la
operación y devuelve la raiz del nuevo árbol. A este método interno se le pasa la raíz
actual, a partir de la cual describe el camino de búsqueda, y, al final, se enlaza. En un
árbol binario de búsqueda no hay nodos duplicados; por ello, si se encuentra un nodo
igual que el que se desea insertar, se lanza un excepción.
1) public void insertar (Object valor )throws Exception
2) {
3) Comparador dato;
4) dato = (Comparador) valor;
5) raiz = insertar(raiz, dato);
6) }
7) //método interno para realizar la operación
8) protected Nodo
9) insertar(Nodo raizSub, Comparador dato) throws Exception
10) {
11) if (raizSub == null)
12) raizSub = new Nodo(dato);
13) else if (dato.menorQue(raizSub.valorNodo()))
14) {
15) Nodo iz;
16) iz = insertar(raizSub.subarbolIzdo(), dato);
17) raizSub.ramaIzdo(iz);
18) }
19) else if (dato.mayorQue(raizSub.valorNodo()))
20) {
21) Nodo dr;
22) dr = insertar(raizSub.subarbolDcho(), dato);
23) raizSub.ramaDcho(dr);
24) }
25) else
26) throw new Exception("Nodo duplicado");
27) return raizSub;
28) }
Eliminar un nodo:
La operación de eliminación de un nodo es también una extensión de la operación de
búsqueda,si bien más compleja que la inserción, debido a que el nodo a suprimir puede
ser cualquiera y la operación debe mantener la estructura de árbol binario de búsqueda
después de quitar el nodo.
Los pasos a seguir son:
1. Buscar en el árbol para encontrar la posición del nodo a eliminar.
2. Si el nodo a suprimir tiene menos de dos hijos, reajustar los enlaces de su antecesor.
3. Si el nodo tiene dos hijos (rama izquierda y derecha), es necesario subir a la posición
que
éste ocupa el dato más próximo de sus subárboles (el inmediatamente superior o el
inmediatamente
inferior) con el fin de mantener la estructura de árbol binario de búsqueda.
1) public void eliminar (Object valor) throws Exception
2) {
3) Comparador dato;
4) dato = (Comparador) valor;
5) raiz = eliminar(raiz, dato);
6) }
7) //método interno para realizar la operación
8) protected Nodo
9) eliminar (Nodo raizSub, Comparador dato) throws Exception
10) {
11) if (raizSub == null)
12) throw new Exception ("No encontrado el nodo con la clave");
13) else if (dato.menorQue(raizSub.valorNodo()))
14) {
15) Nodo iz;
16) iz = eliminar(raizSub.subarbolIzdo(), dato);
17) raizSub.ramaIzdo(iz);
18) }
19) else if (dato.mayorQue(raizSub.valorNodo()))
20) {
21) Nodo dr;
22) dr = eliminar(raizSub.subarbolDcho(), dato);
23) raizSub.ramaDcho(dr);
24) }
25) else // Nodo encontrado
26) {
27) Nodo q;
28) q = raizSub; // nodo a quitar del árbol
29) if (q.subarbolIzdo() == null)
30) raizSub = q.subarbolDcho();
31) else if (q.subarbolDcho() == null)
32) raizSub = q.subarbolIzdo();
33) else
34) { // tiene rama izquierda y derecha
35) q = reemplazar(q);
36) }
37) q = null;
38) }
39) return raizSub;
40) }
41) // método interno para susutituir por el mayor de los menores
42) private Nodo reemplazar(Nodo act)
43) {
44) Nodo a, p;
45) p = act;
46) a = act.subarbolIzdo(); // rama de nodos menores
47) while (a.subarbolDcho() != null)
48) {
49) p = a;
50) a = a.subarbolDcho();
51) }
52) act.nuevoValor(a.valorNodo());
53) if (p == act)
54) p.ramaIzdo(a.subarbolIzdo());
55) else
56) p.ramaDcho(a.subarbolIzdo());
57) return a;
58) }

ARBOL B:
B-árbol es un árbol de búsqueda que puede estar vacío o aquel cuyos nodos pueden
tener varios hijos, existiendo una relación de orden entre ellos, tal como muestra el dibujo.
Un árbol-B de orden M (el máximo número de hijos que puede tener cada nodo) es un
árbol que satisface las siguientes propiedades:

1. Cada nodo tiene como máximo M hijos.


2. Cada nodo (excepto raíz) tiene como mínimo (M)/2 claves.
3. La raíz tiene al menos 2 hijos si no es un nodo hoja. (según M)
4. Todos los nodos hoja aparecen al mismo nivel.
5. Un nodo no hoja con k hijos contiene k-1 elementos almacenados.
6. Los hijos que cuelgan de la raíz (r1, ···, rm) tienen que cumplir ciertas condiciones:
1. El primero tiene valor menor que r1.
2. El segundo tiene valor mayor que r1 y menor que r2, etc.
3. El último hijo tiene valor mayor que rm.

La idea tras los árboles-B es que los nodos internos deben tener un número variable de
nodos hijo dentro de un rango predefinido. Cuando se inserta o se elimina un dato de la
estructura, la cantidad de nodos hijo varía dentro de un nodo. Para que siga
manteniéndose el número de nodos dentro del rango predefinido, los nodos internos se
juntan o se parten. Dado que se permite un rango variable de nodos hijo, los árboles-B no
necesitan rebalancearse tan frecuentemente como los árboles binarios de búsqueda
auto-balanceables. Pero, por otro lado, pueden desperdiciar memoria, porque los nodos
no permanecen totalmente ocupados. Los límites (uno superior y otro inferior) en el
número de nodos hijo son definidos para cada implementación en particular. Por ejemplo,
en un árbol-B 2-3 (A menudo simplemente llamado árbol 2-3 ), cada nodo sólo puede
tener 2 ó 3 nodos hijo.
Un árbol-B se mantiene balanceado porque requiere que todos los nodos hoja se
encuentren a la misma altura.
Los árboles B tienen ventajas sustanciales sobre otras implementaciones cuando el tiempo
de acceso a los nodos excede al tiempo de acceso entre nodos. Este caso se da
usualmente cuando los nodos se encuentran en dispositivos de almacenamiento
secundario como los discos rígidos. Al maximizar el número de nodos hijo de cada nodo
interno, la altura del árbol decrece, las operaciones para balancearlo se reducen, y
aumenta la eficiencia. Usualmente este valor se coloca de forma tal que cada nodo
ocupe un bloque de disco, o un tamaño análogo en el dispositivo. Mientras que los
árboles B 2-3 pueden ser útiles en la memoria principal, y además más fáciles de explicar,
si el tamaño de los nodos se ajustan para caber en un bloque de disco, el resultado
puede ser un árbol B 129-513.
ESTRUCTURA:
#define TAMANO 1000

1) struct stclave {
2) int valor;
3) long registro;
4) };

5) class bnodo {
6) public:
7) bnodo (int nClaves); // Constructor
8) ~bnodo (); // Destructor

9) private:
10) int clavesUsadas;
11) stclave *clave;
12) bnodo **puntero;
13) bnodo *padre;
14) friend class btree;
15) };

Búsqueda:
La búsqueda es similar a la de los árboles binarios. Se empieza en la raíz, y se recorre el
árbol hacia abajo, escogiendo el sub-nodo de acuerdo a la posición relativa del valor
buscado respecto a los valores de cada nodo. Típicamente se utiliza la búsqueda
binaria para determinar esta posición relativa.
Procedimiento

1. Situarse en el nodo raíz.


2. (*) Comprobar si contiene la clave a buscar.
1. Encontrado fin de procedimiento.
2. No encontrada:
1. Si es hoja no existe la clave.
2. En otro caso el nodo actual es el hijo que corresponde:
1.La clave a buscar k < k1: hijo izquierdo.
2.La clave a buscar k > ki y k < ki+1 hijo iésimo.
3.Volver a paso 2(*).
3. AB Crear0(int ne)
4. {
5. AB raiz;
6.
7. raiz = (AB)malloc(sizeof(struct AB));
8. if (raiz == NULL)
9. error("Memoria Insuficiente.");
10. raiz->n_etiquetas = ne;
11. for (int i=1; i<=(ne+1); i++) {
12. raiz->hijos[i] = NULO;
13. }
14. return(raiz);
15. }
16.
17. AB Crear(int ne, int eti[])
18. {
19. AB raiz;
20.
21. raiz = (AB)malloc(sizeof(struct AB));
22. if (raiz == NULL)
23. error("Memoria Insuficiente.");
24. raiz->n_etiquetas = ne;
25. for (int i=1; i<=(ne+1); i++) {
26. raiz->hijos[i] = NULO;
27. }
28. for (int i=1; i<=lenght(eti[]); i++) {
29. raiz->etiquetas[i] = eti[i];
30. }
31. return(raiz);
32. }
33.
34. int Buscar(int eti, int *nod, int *pos)
35. {
36. int i,l;
37.
38. l = lenght(nod->etiquetas[]);
39. for(i=0;inod->etiquetas[i];i++)
40. ;
41. *pos = i;
42. if(*posetiquetas[*pos])
43. return 1;
44. else;
45. return 0;
46. }
47.
48. int BuscarNodo(int eti, int *nod, int *pos)
49. {
50. int i=0, enc;
51.
52. enc = Buscar(eti,&nod,&pos);
53. if (enc == 1)
54. return 1;
55. do {
56. if (etietiquetas[i] && nod->hijos[i]!=NULO)
57. enc = BuscarNodo(eti,&nod->hijos[i],&pos);
58. else
59. if ((etietiquetas[i+1]||nod->etiquetas[i+1]==-1)&&nod->hijos[i+1]!=-1)
60. enc = BuscarNodo(eti,&nod->hijos[i+1],&pos);
61. i++;
62. } while (ietiquetas[]) && enc==0);
63. return (enc);
64. }

Inserción:
Las inserciones se hacen en los nodos hoja.

1. Realizando una búsqueda en el árbol, se halla el nodo hoja en el cual debería


ubicarse el nuevo elemento.
2. Si el nodo hoja tiene menos elementos que el máximo número de elementos
legales, entonces hay lugar para uno más. Inserte el nuevo elemento en el nodo,
respetando el orden de los elementos.
3. De otra forma, el nodo debe ser dividido en dos nodos. La división se realiza de la
siguiente manera:
1. Se escoge el valor medio entre los elementos del nodo y el nuevo
elemento.
2. Los valores menores que el valor medio se colocan en el nuevo nodo
izquierdo, y los valores mayores que el valor medio se colocan en el nuevo
nodo derecho; el valor medio actúa como valor separador.
3. El valor separador se debe colocar en el nodo padre, lo que puede
provocar que el padre sea dividido en dos, y así sucesivamente.
Eliminación:
La eliminación de un elemento es directa si no se requiere corrección para garantizar sus
propiedades. Hay dos estrategias populares para eliminar un nodo de un árbol B.

 localizar y eliminar el elemento, y luego corregir, o


 hacer una única pasada de arriba a abajo por el árbol, pero cada vez que se visita
un nodo, reestructurar el árbol para que cuando se encuentre el elemento a ser
borrado, pueda eliminarse sin necesidad de continuar reestructurando
Se pueden dar dos problemas al eliminar elementos. Primero, el elemento puede ser un
separador de un nodo interno. Segundo, puede suceder que al borrar el elemento
número de elementos del nodo quede debajo de la cota mínima. Estos problemas se
tratan a continuación en orden.

Eliminación en un nodo hoja:

 Busque el valor a eliminar.


 Si el valor se encuentra en un nodo hoja, se elimina directamente la clave,
posiblemente dejándolo con muy pocos elementos; por lo que se requerirán cambios
adicionales en el árbol.
Eliminación en un nodo interno:
En el segundo caso, uno de los dos nodos hijos tienen un número de elementos mayor que
el mínimo. Entonces izquierdo o el menor elemento del nuevo separador.
 Como se ha eliminado un elemento de un nodo hoja, se trata este caso de manera
equivalente
CONCLUCIONES:
En este capítulo se introdujo y se desarrolló la estructura de datos de un árbol.
Es muy importante su aprendizaje ya que se puede utilizar en una gran variedad
de aplicaciones de programación. Un árbol binario es árbol en el que cada nodo
tiene como máximo dos hijos, llamados subárbol izquierdo y subárbol derecho. En
un árbol binario, cada elemento tiene cero, uno o dos hijos. El nodo raíz no tiene
un padre, pero cada elemento restante sí tiene un padre.
La altura de un árbol binario es el número de ramas entre la raíz y la hoja más
lejana, más 1. Si el árbol A es vacío, la altura es 0.
Los árboles binarios presentan dos tipos característicos: árboles binarios de
búsqueda y árboles binarios de expresiones.
Los árboles binarios de búsqueda se utilizan, fundamentalmente,
para mantener una colección ordenada de datos, y los árboles binarios de
expresiones, para almacenar expresiones.