ARBOLES B



ARBOLES B
Constituyen una categoría muy importante de estructuras de datos, que permiten una implementación eficiente de conjuntos y diccionarios, para operaciones de consulta y acceso secuencial. Existe una gran variedad de ´arboles B: los ´arboles B, B+ y B*; pero todas ellas están basadas en la misma idea, la utilización de ´arboles de búsqueda no binarios y con condición de balanceo.

CARACTERÍSTICAS
  • 1. Surgieron en 1972 por R. Bayer y E. Mc creight.
  • 2. Manejan índices en almacenamiento externo para acceso a D.D.
  • 3. Los arboles b son una categoría muy importante en la E.D.
  • 4. Están pensados para administrar la cantidad de accesos al disco y la posibilidad de mantener en memoria la parte que se está utilizando en el resto conservándolo en el disco.
  • 5.El árbol b es un árbol de búsqueda que puede estar vacío o puede tener varios hijos.
  • 6.Los nodos del árbol b son denominados páginas.
  • 7. Las páginas tienen apuntadores a la izquierda, derecha y a los datos.    
  • 8.Cada página tiene como máximos 4n claves.
  • 9.Cada página contiene mínimo n claves excepto la raíz.
  • 10.Cada página o es una página hoja o tiene más descendientes siendo m el número de claves en esta.
  • 11.Todas las paginas hojas están al mismo nivel.
  • 12.Un árbol b no puede tener claves repetidas.    


Operaciones:

Dentro dela operaciones que podemos hacer con estos árboles están las siguientes:
  • Búsqueda
  • Inserción
  • Eliminación  

Búsqueda

La operación búsqueda consiste en buscar un elemento en árbol y encontrarlo.


 Inserción 

Para la inserción nos guiaremos del siguiente ejemplo.

Insertar las siguientes claves: 30, 60, 45, 8, 22

recordemos que para la creación de un árbol debemos iniciar de abajo a arriba.

Como nuestro árbol va a hacer de orden 2 lo que quiere decir que podemos insertar máximo 4 claves al inicio (2n=2(2)=4), por lo que iniciaremos nuestro árbol de la siguiente manera.

El primer paso sería ir insertando las 4 primeras claves en orden de la siguiente manera.  



 Ahora al ingresar el 22 tendría que quedar en la mitad del 30 y 45 pero como es de orden 2 no pueden haber más de 5 claves por página porque su máximo son 4 entonces lo que hacemos es partir el árbol y nos quedaría de la siguiente manera:


Lo que paso fue que al insertar una clave a una página llena ocurren un desbordamiento, lo que se hace en estos casos es dividir las pagina en 2 subir el que quedó en medio para que quede como raíz .


Eliminación

Para la eliminación debemos tener en cuenta las siguientes reglas:

  1. Si el elemento a borrar está en un nodo hoja se borra y se termina la operación de eliminación.
  2. Si el elemento no se encuentra en la hoja se busca el sustituto así:  
  • El último elemento de la hoja más derecha del subárbol izquierdo del nodo actual (el mayor de los menores)
  • El primer elemento de la hoja más izquierda del subárbol derecho del nodo actual (el menor de los mayores)










/* En este programa se encuentran las rutinas que insertan y */
/* retiran llaves de un arbol b de cualquier orden. */

#include "stdio.h"
//#include "alloc.h"
#include "stdlib.h"
#include "conio.h"
#define N 2
#define M 4
#define M1 5
#define MAXIMO 10
#define localizar (pagina *) malloc (sizeof (pagina))

typedef struct z pagina;
typedef struct LIFO LIFO;
typedef struct componente componente;
typedef struct LIFO1 LIFO1;
struct z {
int cont;
int info [M];
pagina *apunt [M1];
};
struct LIFO {
int t;
pagina *a [MAXIMO];
};
struct componente  {
pagina  *s;
int v;
};

struct LIFO1 {
int t;
componente a [MAXIMO];
};



int main()
{
pagina *raiz=NULL;
int x,min,s;
int lea();
void ins_b (pagina **raiz,int x,int *s);
void listar1_b (pagina *p,int l);
void retira_b (pagina **raiz, int x, int *s);
printf ("Comienzo..\n");
printf ("De llave\n");
min = lea();
while (min != 9999) {
ins_b (&raiz, min, &s);
if (s == 1)
printf ("La llave ya existe\n");
printf ("De llave\n");
min = lea();
}
printf ("\n");
listar1_b (raiz,0);
getch();

printf ("\nRetiros\n");
printf ("De llave a retirar\n");
x = lea();
while (x != 9999) {
retira_b (&raiz, x, &s);
if (s == 0)
printf ("La llave no existe\n");
printf ("De llave a retirar\n");
x = lea();
}
printf ("\n");
listar1_b (raiz,0);
getch();
return 0;

}
void init_pila (struct LIFO *p)
{
p->t = 0;
}

int pila_vacia (struct LIFO *p)
{
return (!p->t);
}



void ins_pila (struct LIFO *p,pagina *s)
{
if (p->t == MAXIMO) {
printf ("la pila no soporta mas elementos\n");
exit (1);
}
else  {
 p->t++;
 p->a [p->t - 1] = s;
}
}

void retira_pila (struct LIFO *p,pagina **s)
{
if (pila_vacia (p) )  {
printf ("la pila esta vacia\n");
exit (1);
}
else  {
 *s = p->a [p->t - 1];
 p->t--;
}
}

void init1_pila (struct LIFO1 *p)
{
p->t = 0;
}

int pila1_vacia (struct LIFO1 *p)
{
return (!p->t);
}

void ins1_pila (struct LIFO1 *p,pagina *s,int i)
{
if (p->t == MAXIMO) {
printf ("la pila no soporta mas elementos\n");
exit (1);
}
else  {
p->t++;
p->a[p->t - 1].s = s;
p->a[p->t - 1].v = i;
}
}

void retira1_pila (struct LIFO1 *p,pagina **s,int *i)
{
if (pila1_vacia (p) )  {
printf ("la pila esta vacia\n");
exit (1);
}
else  {
*s = p->a [p->t -1].s;
*i = p->a [p->t - 1].v;
p->t--;
}
}

void inicializar (pagina *p)
{
int i;

i=0;
p->cont = 0;
while (i < M1)
p->apunt [i++] = NULL;
}

void crear_pagina (pagina **p,int x)
{
*p = localizar;
inicializar (*p);
(*p)->cont = 1;
(*p)->info [0] = x;
}

void buscar (pagina *p,int x,int *posicion,LIFO *pila)
{
int i,encontro = 0;
void init_pila (struct LIFO *p);
int pila_vacia (struct LIFO *p);
void ins_pila (struct LIFO *p,pagina *s);
void retira_pila (struct LIFO *p,pagina **s);
*posicion = -1;
while (p && !encontro) {
ins_pila (pila, p);
i = 0;
while (x > p->info [i] && i < p->cont - 1)
i++;
if (x < p->info [i])
p = p->apunt [i];
else if (x > p->info [i])
p = p->apunt [i+1];
else encontro = 1;
}
if (!encontro)
*posicion = i;
}

void insertar (pagina *p,int x,int *i)
{
int j;

if (p->cont)
if (x > p->info [*i])
(*i)++;
else {
j = p->cont - 1;
while (j >= *i) {
p->info [j+1] = p->info [j];
j--;
}
}
p->cont++;
p->info [*i] = x;
}

int donde (pagina *p, int x)
{
int i;

i= 0;
while (x > p->info [i] && i < p->cont - 1)
i++;
return (i);
}

void romper (pagina *p,pagina *t,pagina **q,int x,int *subir)
{
int a [M1], i = 0, s = 0;
pagina *b[M1+1];

while (i < M && !s)
if (p->info[i] < x) {
a[i] =p->info [i];
b[i] = p->apunt [i];
p->apunt [i++] = NULL;
}
else s = 1;
a[i] = x;
b[i] = p->apunt [i];
p->apunt [i] = NULL;
b[++i] = t;
while (i <= M) {
a[i] =p->info [i-1];
b[i+1] = p->apunt [i];
p->apunt [i++] = NULL;
}
*q = localizar;
inicializar (*q);
p->cont = (*q)->cont = N;
i = 0;
while (i < N) {
p->info [i] = a[i];
p->apunt [i] = b [i];
(*q)->info [i] = a[i+N+1];
(*q)->apunt [i] = b[i+N+1];
i++;
}
p->apunt [N] = b [N];
(*q)->apunt [N] = b [M1];
*subir = a [N];
}

void cderecha_apunt (pagina *p,int i)
{
int j;

j = p->cont;
while (j > i) {
p->apunt [j] = p->apunt [j - 1];
j--;
}
}

void listar_b (pagina *p)
{
int i;
LIFO1 pila;
void init1_pila (struct LIFO1 *p);
int pila1_vacia (struct LIFO1 *p);
void ins1_pila (struct LIFO1 *p,pagina *s,int i);
void retira1_pila (struct LIFO1 *p,pagina **s,int *i);
init1_pila (&pila);
while (p) {
ins1_pila (&pila,p,0);
p = p->apunt [0];
}
while (!pila1_vacia (&pila) ) {
retira1_pila (&pila,&p,&i);
if (i < p->cont) {
printf ("%d ",p->info [i]);
ins1_pila (&pila,p,i+1);
p = p->apunt [i+1];
while (p) {
ins1_pila (&pila,p,0);
p = p->apunt [0];
}
}
}
}

void listar1_b (pagina *p,int l)
{
int i;

if (p) {
for (i = 0; i < l; i++)
printf ("  ");
for (i = 0; i < p->cont; i++)
printf ("%4d",p->info [i]);
printf ("\n");
listar1_b (p->apunt [0],l+1);
for (i=1; i <= p->cont; i++)
listar1_b (p->apunt [i], l+1);
}
}



void ins_b (pagina **raiz,int x,int *s)
{
int posicion,i,subir,subir1,terminar,separar;
pagina *p,*nuevo,*nuevo1;
LIFO pila;
void init_pila (struct LIFO *p);
int  pila_vacia (struct LIFO *p);
void ins_pila (struct LIFO *p,pagina *s);
void retira_pila (struct LIFO *p,pagina **s);
init_pila (&pila);
*s = 0;
if (*raiz == NULL)
crear_pagina (raiz, x);
else {
buscar (*raiz, x, &posicion, &pila);
if (posicion == -1)
*s = 1; /* La llave esta en el arbol */
else {
terminar = separar = 0;
while (!pila_vacia (&pila) && terminar == 0) {
 retira_pila (&pila, &p);
 if (p->cont == M) {
 if (separar == 0) {
romper (p, NULL, &nuevo, x, &subir);
separar = 1;
 }
 else {
 romper (p,nuevo,&nuevo1,subir,&subir1);
 subir = subir1;
 nuevo = nuevo1;
 }
 }
 else {
 if (separar == 1) {
 separar = 0;
 i = donde (p, subir);
 insertar (p, subir, &i);
 cderecha_apunt (p, i+1);
 p->apunt [i+1] = nuevo;
 }
 else insertar (p, x,&posicion);
 terminar = 1;
 }
}
if (separar == 1 && terminar == 0) {
crear_pagina (raiz,subir);
(*raiz)->apunt [0] = p;
(*raiz)->apunt [1] = nuevo;
}
}
}
}

int lea()
{
char a[10];
gets (a);
return (atoi(a) );
}

void retirar (pagina *p,int i)
{
while (i < p->cont - 1) {
p->info [i] = p->info [i+1];
i++;
}
p->cont--;
}

void cambio (pagina *p,pagina *q,pagina *r,int i,int x)
{
int k,t;

if (x > r->info [r->cont - 1]) {
t = q->info [i];
retirar (q,i);
k = 0;
insertar (p,t,&k);
t = r->info [r->cont - 1];
retirar (r, r->cont - 1);
k = i;
if (k == -1)
k = 0;
insertar (q,t,&k);
}
else {
t = q->info [i];
retirar (q, i);
k = p->cont - 1;
if (k == -1)
k = 0;
insertar (p,t,&k);
t = r->info [0];
retirar (r, 0);
k = i;
if (q->cont != 0)
if (k > q->cont - 1)
k = q->cont -1;
insertar (q,t,&k);
}
}

int hoja (pagina *p)
{
int j = 0;

while (p->apunt [j] == NULL && j < p->cont - 1)
j++;
return (p->apunt [j] == NULL);
}

void cizquierda_apunt (pagina *p,int i,int j)
{
while (i < j) {
p->apunt [i] = p->apunt [i+1];
i++;
}
p->apunt [i] = NULL;
}

void esta (pagina *p, int x, int *posicion, LIFO1 *pila)
{
int i = 0,encontro = 0;

*posicion = -1;
while (p != NULL && !encontro) {
i = 0;
while (x > p->info [i] && i < p->cont - 1)
i++;
if (x < p->info [i]) {
ins1_pila (pila, p, i);
p = p->apunt [i];
}
else if (x > p->info [i]) {
ins1_pila (pila, p, i+1);
p = p->apunt [i+1];
}
else {
ins1_pila (pila, p, i);
encontro = 1;
}
}
if (encontro == 1)
*posicion = i;
}

void unir (pagina **raiz, pagina *q, pagina *r, pagina *p,
int i, LIFO1 pila, int x, int posicion)
{
int terminar = 0,j, k;
pagina *t;

retirar (p, posicion);
if (x < r->info [0]) {
t = p;
p = r;
r = t;
}
while (terminar == 0) {
 if (r->cont < N && p->cont > N) {
cambio (r, q, p, i, x);
r->apunt [r->cont] = p->apunt [0];
cizquierda_apunt (p, 0, p->cont + 1);
terminar = 1;
 }
 else if (p->cont < N && r->cont > N) {
cambio (p, q, r, i, x);
cderecha_apunt (p, 0);
p->apunt [0] = r->apunt [r->cont + 1];
r->apunt [r->cont + 1] = NULL;
terminar = 1;
 }
 else {
 j = r->cont;
 r->info [j++] = q->info [i];
 k = 0;
 while (k <= p->cont - 1)
r->info [j++] = p->info [k++];
 r->cont = j;
 retirar (q, i);
 k = 0;
 j = M - p->cont;
 while (p->apunt [k] != NULL)
r->apunt [j++] = p->apunt [k++];
 free (p);
 if (q->cont == 0) {
q->apunt [i+1] = NULL;
if (pila1_vacia (&pila) ) {
free (q);
q = NULL;
}
 }
 else cizquierda_apunt (q, i+1, q->cont+1);
 if (q != NULL)
if (q->cont >= N)
terminar = 1;
else {
t = q;
if (!pila1_vacia (&pila) ) {
retira1_pila (&pila, &q, &i);
if (x >= q->info [0]) {
p = t;
r = q->apunt [i-1];
i--;
}
else {
r = t;
p = q->apunt [i+1];
}
}
else terminar = 1;
}
 else {
terminar = 1;
*raiz = r;
 }
 }
}
}

void retira_b (pagina **raiz, int x, int *s)
{
int posicion, i, k;
pagina *p, *q, *r, *t;
LIFO1 pila;
void init1_pila (struct LIFO1 *p);
int pila1_vacia (struct LIFO1 *p);
void ins1_pila (struct LIFO1 *p,pagina *s,int i);
void retira1_pila (struct LIFO1 *p,pagina **s,int *i);
*s = 1;
init1_pila (&pila);
esta (*raiz, x, &posicion, &pila);
if (posicion == -1)
*s = 0;  /* La llave no existe en el arbol */
else {
retira1_pila (&pila, &p, &i);
if (!hoja (p)) {
t = p;
k = i;
ins1_pila (&pila, p, i+1);
p = p->apunt [i+1];
while ( p != NULL) {
ins1_pila (&pila, p, 0);
p = p->apunt [0];
}
retira1_pila (&pila, &p, &i);
t->info [k] = p->info [0];
x = p->info [0];
posicion = 0;
}
if (p->cont > N)
retirar (p, posicion);
else {
if (!pila1_vacia (&pila)) {
retira1_pila (&pila, &q, &i);
if (i < q->cont) {
r = q->apunt [i+1];
if (r->cont > N) {
retirar (p, posicion);
cambio (p, q, r, i, x);
}
else {
if (i != 0) {
  r = q->apunt [i-1];
  if (r->cont > N) {
retirar (p, posicion);
cambio(p,q,r,i-1,x);
  }
  else unir (raiz,q,r,p,
i-1,pila,x,posicion);
}
else unir (raiz,q,r,p,i,pila,
x,posicion);
}
}
else {
r = q->apunt [i-1];
if (r->cont > N) {
retirar (p, posicion);
cambio (p,q,r,i-1,x);
}
else unir (raiz,q,r,p,i-1,pila,
x, posicion);
}
}
else {
retirar (p, posicion);
if (p->cont == 0) {
free (*raiz);
*raiz = NULL;
}
}
}
}
}

About the author

Admin
Donec non enim in turpis pulvinar facilisis. Ut felis. Praesent dapibus, neque id cursus faucibus. Aenean fermentum, eget tincidunt.

0 comentarios:

Copyright © 2013 ESTRUCTURAS DE DATOS II and Blogger Themes.