0% encontró este documento útil (0 votos)
26 vistas35 páginas

04 Arbol Biselado

El documento describe los árboles binarios de búsqueda, su construcción, operaciones y el concepto de biselación para optimizar la búsqueda. Se explican las rotaciones simples, dobles y dobles inversoras, así como su implementación en Java. Además, se compara la eficiencia de los árboles biselados con los árboles equilibrados como AVL y Rojo-Negro.

Cargado por

Adri Ss
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PPSX, PDF, TXT o lee en línea desde Scribd
0% encontró este documento útil (0 votos)
26 vistas35 páginas

04 Arbol Biselado

El documento describe los árboles binarios de búsqueda, su construcción, operaciones y el concepto de biselación para optimizar la búsqueda. Se explican las rotaciones simples, dobles y dobles inversoras, así como su implementación en Java. Además, se compara la eficiencia de los árboles biselados con los árboles equilibrados como AVL y Rojo-Negro.

Cargado por

Adri Ss
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PPSX, PDF, TXT o lee en línea desde Scribd

Árboles binarios

• Si a partir de n claves se
construye un árbol binario de
búsqueda de altura mínima se
obtiene un árbol de log2n ñ
niveles.
• Las operaciones de búsqueda, h r
inserción y extracción
requieren un tiempo de g k o x
O(log2n).
Árboles binarios
• Si la única consideración a tener en cuenta es la de
“menores a la izquierda y mayores a la derecha”, la
altura del árbol puede degenerar hasta n.
g g

k r
x
k
r
o
o
ñ ñ
Definición del árbol biselado
 Es un árbol binario de búsqueda
 Cualquier operación requiere un esquema de
reestructuración denominado biselación
 El esquema de biselación consiste en:
Desplazar un nodo hasta la raíz del árbol biselado
 Mediante una secuencia de rotaciones

 Objetivo: reducir el tiempo de búsqueda de


cada valor de clave
 Se sitúan los nodos más frecuentemente solicitados
en torno a la raíz del árbol.
Relación con los árboles binarios equilibrados
 El objetivo de los árboles AVL y Rojo-Negro es
asegurar que el árbol nunca se desequilibre
 Garantizan que el tiempo de búsqueda de un valor de clave
individual nunca requiere más de O(lg2 n)
• Los árboles biselados pueden necesitar un tiempo de O(n)
– Aseguran que este comportamiento no se va a producir de forma
repetida
– No precisan de ningún tipo de información de equilibrio adicional
en cada nodo
Rotaciones
• En los esquemas, la biselación se realiza sobre el
nodo u, su padre -el nodo p- y su abuelo –el nodo b.
• Los tipos de rotaciones a utilizar
son:
b b

p p p
4 4
u u u
3 1 3

1 2 2 3 1 2

Rotación Simple Rotación Doble Rotación Doble Inversora


Rotación Simple
• Las rotaciones I y D son simétricas.

p p
u p p
u

u u D
u 3 p p 1 3 u
I
3 1 1

1 2 1 2 2 3 2 3 1 2 2 3
u es hijo izquierdo de p u es hijo derecho de p

• Intercambian la relación padre-hijo y sitúan el


subárbol central de forma que cumpla la condición de
árbol binario de búsqueda.
Rotación Simple en Java
protected NodoBinario rotaciónSimple(NodoBinario nodo, int rama) {
//Se intercambian los nodos
NodoBinario hijo = [Link][rama];
int otraRama = 1 - rama;
[Link][rama] = [Link][otraRama];
[Link][otraRama] = nodo;
return hijo;
}

nodo
A B

nodo| hijo B
A
I
T3

T1’ T2
T1’ T2 T3
Rotación Doble
b b
u
p p 4 b
ID
4

Modifican relaciones 1 u 1 u 2 3 4
abuelo-padre-hijo
y sitúan los dos
subárboles centrales de
2 3 2 3
u es hijo derecho de p
forma que cumplan con
la condición de b b
u
árbol binario de p
DI
búsqueda. p b 1
1
u 4 1 2 u 3 4

2 3
2 3 u es hijo izquierdo de p
Una rotación doble equivale a dos simples
• Consiste en efectuar la rotación simple D
al nivel del padre inicial...

b b

p 4 u u
4
u D p I p b
1 3

2 3 1 2 1 2 3 4
• ... y después la I a nivel del abuelo del subárbol
intermedio
nodo
A
hijo

Rotación Doble en Java


B
nieto
C nodo
protected NodoBinario rotaciónDoble(NodoBinario nodo, int rama) {
//Se intercambian los nodos
NodoBinario hijo = [Link][rama];
int otraRama = 1 - rama;
NodoBinario nieto = [Link][otraRama]; T4
[Link][rama] = [Link][otraRama];
[Link][otraRama] = [Link][rama];
T1 T2’ T3
[Link][otraRama] = nodo;
[Link][rama] = hijo;
return nieto;
}

B A

T3
T1 T2’ T4
Rotación Doble inversora
(u es hijo izquierdo
de p)
b u b

p p
4 1 4

u u
3 II 2 3 b

1 2 1 2 3 4
• Se efectúan dos rotaciones simples I consecutivas
– Se obtiene una situación inversa a la de partida
Rotación Doble inversora
(u es hijo derecho de
p)
b b u

p p
1 1 4
DD
2 u b 2 u
3

3 4 1 2 3 4

Se efectúan dos rotaciones simples D


consecutivas
nodo
A
hijo
B
Rotación DobleInversora en Java nieto
C nodo
protected NodoBinario rotaciónDobleInversora( NodoBinario nodo,
int rama) {
//Se intercambian los nodos
NodoBinario hijo = [Link][rama]; T3 T4
int otraRama = 1 - rama; T2’
NodoBinario nieto = [Link][rama];
[Link][rama] = [Link][otraRama];
[Link][rama] = [Link][otraRama];
T1
[Link][otraRama] = hijo;
[Link][otraRama] = nodo;
C
return nieto;
}
B

T1 T2

T3 T4
Proceso de biselación
• En cada paso se realiza una rotación
• La rotación simple actúa sólo cuando el nodo en el
que se desea biselar es hijo de la raíz del árbol.
• Las rotaciones doble o doble inversora se
aplican cuando existe el abuelo del nodo en el que se
que desea biselar.
• Se elige una u otra (doble o doble inversora) en función
del camino del abuelo al nodo.
Proceso de biselación
g g

k k

h x h x
DD
ñ r

T ñi o ¿Tiene o T rd

abuelo?
r ñ
T o T ri
i

¿rotación doble o
doble inversora?
T ri T ñi Toi
T rd

roceso de biselación en el nodo r


g
Proceso de biselación
k g
rotación
doble
r
h x

r DI k x

o T rd
h o T rd

ñ ñ T ri
Ti
r

T ñi Toi
T ñ
i T o
i

oceso de biselación en el nodo r


Proceso de biselación
rotación simple

g r

r g x
D
k x k T rd

h o T rd h o
ñ T ri ñ T ri

T ñi Toi
T ñi Toi
Proceso de biselación en el nodo r
Búsqueda
• El descenso por el árbol es igual que en el árbol
binario de búsqueda.
• Si se encuentra un nodo u con el valor de clave
buscado.
– El árbol se bisela en u.
• Si no
– El árbol se bisela en el último nodo visitado.

La búsqueda modifica el árbol


• El camino recorrido en la biselación es el inverso del
seguido durante el descenso por el árbol.
• El tiempo de búsqueda es proporcional al recorrido.
– ¡Ojo, puede llegar a O(n)!, aunque no de forma repetida.
Búsqueda del valor de clave x
g x
rotación
doble inversora
Tg i k k Txd
¿Tiene
abuelo?
h x g ñ
DD
Th i Th d ñ T x
d
Tg i
h m o
m o
Th i Th d T ji To i r
T ji To i r
Tr i Tr d

Tr i
Proceso de biselación en el nodo x
Tr d
Inserción
• Funciona de forma similar a un árbol binario de
búsqueda.
– Se alcanza el árbol vacío.
– Se añade el nuevo nodo al árbol.

• Se realiza la biselación sobre el nuevo


nodo.
• Si el valor de clave a insertar existe en el
árbol.
– Se bisela en el nodo que lo contiene.
Extracción
• La extracción es la operación más complicada
– Requiere dos biselaciones

• Se busca el nodo S que contiene el valor de clave a


extraer
– Si no se encuentra, se bisela en el último nodo examinado
– Si sí se encuentra, se bisela en el nodo S
s

Ti Td
– y se elimina S s
– Se obtienen dos árboles separados

Ti Td
Ti Td
Para unir de nuevo los dos árboles se reorganiza uno de ellos
O se bisela en el nodo con el máximo valor de clave del árbol
izquierdo.
• Tal nodo se sitúa en la raíz del árbol izquierdo
• es el Predecesor en orden simétrico del valor de clave del
nodo S
Predeces
or
•no tiene hijo Ti Ti’
derecho
• La unificación de los dos árboles se completa situando la raíz
del árbol derecho como hijo derecho de la nueva raíz del árbol
izquierdo
Predeces
or

Ti’ Td

O se bisela en el nodo con el mínimo valor de clave del árbol


derecho, cuando el árbol izquierdo está vacío.
Extracción del valor de clave ñ
x ñ

k Txd k x
¿Tiene
abuelo?
g ñ g m o Txd

ID
Tg i h T ji To i r
Tg i h m o

Th i Th d Tr i Tr d
T h
i
Th d T ji To i r

Tr i Tr d

Proceso de biselación en el nodo ñ


Extracción del valor de clave ñ
El árbol de la derecha se
ñ
m encadena a m como subárbol
derecho
k x

g m
T
j
i
o Txd

Eliminación
del nodo
Tg i h T ji To d r

Th i Th d Tr i Tr d

Se obtienen dos árboles separados


Se bisela en m (máximo valor de clave del árbol
izquierdo)
Árboles binarios de búsqueda equilibrados
Representan una buena solución a la degeneración de
un árbol de búsqueda.
Son árboles autoajustables con cota logarítmica de
altura.
La estructura debe reorganizarse en cuanto las
inserciones y extracciones transgredan el equilibrio.
Las operaciones de mantenimiento deben garantizar un
tiempo de O(lg2 n).
 El quid radica en introducir Árboles Biselados
binarios de
cierta holgura búsqueda
Los nodos rojos en los árboles Rojo-Negro Árboles autoajustables AVL
Los nodos con un desequilibrio de altura
Árboles equilibrados
de una unidad en los árboles AVL
Rojo-Negro
Implementación en Java de un
contenedor con un árbol biselado
Se parte de la interfaz ContenedorOrdenado y de su
implementación ÁrbolBinarioBúsqueda que se
extiende a la clase ÁrbolBinarioAjustable (que define
las rotaciones como los métodos comunes a todos los
ajustables); por último se deriva la clase
ÁrbolBiselado que implementa los métodos
apropiados sin añadir ningún campo.

El método está de ÁrbolBinarioBúsqueda define la


operación de pertenencia sin modificar el árbol, es
necesario redefinir este método para que se adapte a
las características del árbol biselado.
Esquema de clases
public class ÁrbolBinarioBúsqueda implements ContenedorOrdenado {
public interface ContenedorOrdenado { protected int numElem;
public void insertar(Comparable e); protected NodoBinario raíz;
public void extraer(Comparable e); public void insertar(Comparable valor);
public boolean está(Comparable e); public void extraer(Comparable valor);
public void vaciar(); public void vaciar();
public boolean esVacío(); public boolean está(Comparable valor);
public int tamaño(); public boolean esVacío();
} public int tamaño();
}

Interfa
z
public class ÁrbolBinarioAjustable extends ÁrbolBinarioBúsqueda {
Clase que extiende Implementa la interfaz
protected NodoBinario rotaciónSimple(NodoBinario nodo,int rama);
ÁrbolBinarioAjustable y ContenedorOrdenado
protected y
NodoBinario rotaciónDoble(NodoBinario nodo,int rama);
proporciona las proporciona la estructura de
protected NodoBinario rotaciónDobleInversora(NodoBinario nodo,int rama);
}
operaciones específicas arbol binario y sus
del árbol biselado operaciones básicas
Extensión de la Resuelve insertar, extraer,
clase vaciar y todas las operaciones
ÁrbolBinarioBúsqu observadoras
public class
eda ÁrbolBinarioAjustable {
Biselado extends
public void insertar(Comparable valor);
public void extraer(Comparable valor); Aporta los
public void está(Comparable valor); mecanismos de
} rotación para los
árboles binarios
autoajustables
Clase ÁrbolBiselado
public class ÁrbolBiselado extends ÁrbolBinarioAjustable implements ContenedorOrdenado {

private class EnteroMutable { ... } Clase auxiliar


private NodoBinario raíz; Realiza un paso de biselación

public ÁrbolBiselado() {
Constructor
super();
Bisela el nodo con el mayor o el menor valor de
raíz = null;
} clave de un árbol dependiendo del valor de rama

private NodoBinario bisela( NodoBinario nodo, int rama, Comparable valor, EnteroMutable niveles) {...}
private NodoBinario biselaSubárbol( NodoBinario nodo, int rama, EnteroMutable niveles) { ... }
private NodoBinario insertar( NodoBinario nodo, Comparable valor, EnteroMutable niveles) { ... }
Métodos
privados

Añade el elemento al contenedor, si no está.


En cualquier caso, se bisela en él.

private NodoBinario está( NodoBinario nodo, Comparable valor, EnteroMutable niveles) { ... }

Método está específico: modifica el árbol.


public void insertar(Comparable valor) { ... }
Devuelve la referencia del nodo encontrado
Métodos
públicos

public void extraer(Comparable valor) { ... }

public boolean está(Comparable valor) { ... }


Extrae el valor del contenedor. Si está, realiza sus dos biselaciones
propias; si no está, bisela en el último nodo accedido.
}
Clase ÁrbolBiselado: clase auxiliar EnteroMutable
private class EnteroMutable {
Permite tener un entero como parámetro de entrada/salida
int entero;

public EnteroMutable() {
entero = 0;
}
public void incrementar(){
entero++;
}
public void decrementar(){
entero--;
}
public int valor(){
return entero;
}
public void ponerValor(int n){
entero = n;
}
}
Clase ÁrbolBiselado: está (privado)
Devuelve la referencia del nodo que contiene el valor de clave buscado, nulo si no
existe
private NodoBinario está(NodoBinario nodo, Comparable valor, EnteroMutable niveles) {
int rama;
O alcanza
if (nodo == null) { Indica al llamador el número de niveles que se tiene que
un nulo
niveles = ponerValor(2); ascender para aplicar una rotación doble o
} dobleInversora
else { O encuentra el valor buscado
if ([Link]([Link]) == 0) {
niveles = ponerValor(1);
} La búsqueda continúa en abuelo abuelo
else { el subárbol adecuado
if ([Link]([Link]) < 0)

niveles = 1

niveles = 2
rama = 0;
else En caso de no cumplirse ninguna de las
dos condiciones, se llama de manera
rama = 1;
recursiva en el subárbol apropiado
[Link][rama] = nodo nodo
está([Link][rama], valor, niveles);
// El nodo actual se bisela un paso
nodo = bisela(nodo, rama, valor, niveles); Nodo a biselar
}
}
return nodo; valor
} Nulo
Nodo a biselar
Clase ÁrbolBiselado: insertar (privado)
Devuelve la referencia del nodo resultante de insertar el valor de clave, si ya se encuentra bisela el último accedido
private NodoBinario insertar(NodoBinario nodo, Comparable valor, EnteroMutable niveles) {
int rama;
if (nodo == null) { O alcanza un nulo y valor se inserta como
nodo = new NodoBinario(valor); hoja
numElem++;
niveles = ponerValor(1);
} O encuentra el valor buscado y valor no se inserta
else {
if ([Link]([Link]) == 0) {
niveles = ponerValor(1); En caso de no cumplirse abuel
} ninguna de las dos o
else { condiciones, se llama de
if ([Link]([Link]) < 0)
rama = 0;
manera recursiva en el

niveles = 1
else subárbol apropiado
rama = 1;
[Link][rama] = insertar([Link][rama], valor, niveles);
// El nodo actual se bisela un paso
nodo = bisela(nodo, rama, valor, niveles);
}
}
return nodo; nodo
}

valor
Nulo
Nodo a
biselar
Clase ÁrbolBiselado: bisela (privado)
niveles indica el número de ascensos necesario para realizar una rotación doble o doble inversora sobre nodo,
según el hijo que indica rama y el nieto deducido de valor. Si se llega antes a la raíz se hace una rotación simple
sobre nodo, según el hijo que indica rama

private NodoBinario bisela(NodoBinario nodo, int rama, Comparable valor, EnteroMutable niveles){
int ramaDos;
NodoBinario hijo; Nivel de la raíz y no existe abuelo: Rotación simple
if ((nodo == raíz) && ([Link]() > 0))
if ([Link][rama] != null) nodo = rotaciónSimple(nodo, rama);
else { Se asciende un nivel por no
if ([Link]() > 0) [Link](); haber alcanzado el abuelo
else {
hijo = [Link][rama]; Es el abuelo porque niveles=0
if ([Link]([Link]) < 0)
ramaDos = 0;
else La posición valor respecto de nodo y de hijo (abuelo
ramaDos = 1; y padre) condiciona el tipo de rotación
if (rama == ramaDos)
nodo = rotaciónDobleInversora(nodo, rama);
else
nodo = rotaciónDoble(nodo, rama);
[Link](1);
}
}
return nodo;
}
Clase ÁrbolBiselado: extraer (público)
Extrae el valor del contenedor: Si está, realiza sus dos biselaciones propias.
Si no está, bisela en el último nodo accedido.

public void extraer(Comparable valor) { está localiza valor y lo bisela,


EnteroMutable niveles = new EnteroMutable(); si no lo encuentra bisela el
NodoBinario hijo, otroHijo; último nodo accedido
raíz = está(raíz, valor, niveles);
if ((raíz != null) && ([Link](raí[Link]) == 0)) {
hijo = raí[Link][0];
otroHijo = raí[Link][1]; Si se encontró, se biseló a la raíz, entonces
numElem--; se elimina la raíz y se tratan sus
if (otroHijo != null) { subárboles
raíz = otroHijo;
Se bisela el sucesor en orden simétrico
raíz = biselaSubárbol(otroHijo, 0, niveles);
raí[Link][0] = hijo; del valor de clave extraído
}
else { Como no existe el sucesor, se bisela el
raíz = hijo; predecesor
raíz = biselaSubárbol(hijo, 1, niveles);
}
}
}
Clase ÁrbolBiselado: biselaSubárbol (privada)
Bisela en el nodo con menor valor de clave, rama=0, o en el nodo con mayor valor de
clave, rama=1, del árbol de raíz nodo

private NodoBinario biselaSubárbol( NodoBinario nodo, int rama, EnteroMutable niveles ) {


if (nodo == null)
[Link](2); Descenso por la misma rama
else {
[Link][rama] = biselaSubárbol([Link][rama], rama, niveles);
if (nodo == raíz && [Link]() > 0)
if ([Link][rama] != null) Nivel de la raíz y no existe abuelo: Rotación simple
nodo = rotaciónSimple(nodo, rama);
else Asciende otro nivel
if ([Link]() > 0) [Link]();
else {
nodo = rotaciónDobleInversora(nodo, rama); Existe abuelo porque niveles=0
[Link](1);
}
}
return nodo; Se aplica rotación doble inversora porque se
} ha descendido siempre por la misma rama
Clase ÁrbolBiselado: insertar, está y vaciar (públicos)
public void insertar(Comparable valor) { Invoca a insertar (privado) con niveles a 0
EnteroMutable niveles = new EnteroMutable();
raíz = insertar(raíz, valor, niveles);
}
Invoca a está (privado) con niveles a
public boolean está(Comparable valor) {
0
EnteroMutable niveles = new EnteroMutable();
raíz = está(raíz, valor, niveles);
if ((raíz != null) && ([Link](raí[Link]) == 0))
return true;
else
return false;
}

También podría gustarte