Documente Academic
Documente Profesional
Documente Cultură
de Busqueda y Balanceado
Joseph L. Kahn Casapa
Facultad de Ciencias, Universidad Nacional de Ingeniera, Lima, Per
u
Escuela Profesional de Matem
atica
juiskahn@gmail.com
20 de diciembre de 2014
Resumen
1.
Introducci
on
2.
Arbol
binario
Figura 1: Arbol
Binario
Se define los siguientes terminos para el manejo de
arboles binarios, utilizaremos A y B dos elementos del
arbol:
Hijo: A es hijo de B, si y solo si el nodo A es descendiente directo de B.
Las implementaciones se realizaran en python un lenguaje muy sencillo y legible para cualquier usuario, utilizando la versi
on estable 2.7. Se utilizara la noci
on basica
de arreglos como almacenamiento de la informacion en
memoria est
atica, haciendo la observaci
on que las implementaciones tambien se pueden realizar en memoria
din
amica, donde la posici
on en el arreglo le determina
un lugar especifico en el
arbol.
Nivel: Es el n
umero de arcos que deben ser recorridos para llegar a un determinado nodo.
Altura: Es el m
aximo n
umero de niveles de todos
los nodos del
arbol.
2.1.
Propiedades
h = log2 (n + 1) 1
.
2. Si conocemos h la altura del
arbol, entonces la cantidad de nodos N m
axima es
N = 2h+1 1
Implementaci
on
2.2.
Arbol
de B
usqueda
Un
arbol binario de b
usqueda(figura 2) es un tipo
particular de
arbol binario muy importante ya que
buscar alg
un dato dentro del
arbol se realiza en un
tiempo menor. Se define de la siguiente manera:
Un
arbol binario no vaco, de raz A, es un arbol
binario de b
usqueda si cumple los siguientes enunciados:
En caso de tener sub
arbol izquierdo, la raz A debe
ser mayor que el valor m
aximo almacenado en el
sub
arbol izquierdo, y que el sub
arbol izquierdo sea
un
arbol binario de b
usqueda.
usqueda.
1
2
3
4
5
def crear():
print Cuanto espacio desea que tenga
inicialmente la cola
maxi = int(raw_input(?:))
arbol = []*maxi
return arbol
Figura 2: Arbol
binario de b
usqueda
2
3
4
5
def padre(arbol,i):
if arbol[i] != :
return i/2
else:
#EL ELEMENTO EN LA POSICION i, NO
EXISTE
return False
La posici
on del hijo a izquierda de un nodo, sera
el doble de la posici
on, aumentado en 1.
1
2
3
4
5
6
7
8
9
10
def izq(arbol,i):
if 2*i+1 < len(arbol):
if arbol[2*i+1] != :
return 2*i+1
else:
#EL ELEMENTO EN LA POSICION i, NO
TIENE HIJO A IZQUIERDA
return False
else:
#EL ELEMENTO EN LA POSICION i, NO
TIENE HIJO A IZQUIERDA
return False
1
2
3
4
5
La posici
on del hijo a derecha de un nodo, sera el
doble de la posici
on aumentado en 1.
1
2
1
2
3
4
5
6
7
8
9
10
def der(arbol,i):
if 2*(i+1) < len(arbol):
if arbol[2*(i+1)] != :
return 2*(i+1)
else:
#EL ELEMENTO EN LA POSICION i, NO
TIENE HIJO A DERECHA
return False
else:
#EL ELEMENTO EN LA POSICION i, NO
TIENE HIJO A DERECHA
return False
4
5
6
7
8
9
10
11
12
13
14
15
16
17
La altura de un
arbol, considerando el dato en la
mayor posici
on en el array con el cual calculamos
la altura mediante h = log2 (n) + 1.
18
19
20
21
1
2
3
4
5
6
7
def altura(arbol):
for i in range(len(arbol)-1,0,-1):
if arbol[i] != :
n = i
break
alt = int(m.log(n,2))+1
return alt
22
23
24
25
26
2
3
4
5
6
7
def agregar(arbol,x):
if elemen(arbol) == 0:
arbol[0] = x
else:
i = 0
bolean = True
while bolean:
if x <= arbol[i]:
if izq(arbol,i) == False:
if 2*i+1 >= len(arbol):
m = 2*(i+1)-len(arbol)
arbol += []*m
arbol[2*i+1] = x
bolean = False
else:
i = izq(arbol,i)
elif x > arbol[i]:
if der(arbol,i) == False:
if 2*(i+1) >= len(arbol):
m = 2*i+3-len(arbol)
arbol += []*m
arbol[2*(i+1)] = x
bolean = False
else:
i = der(arbol,i)
return arbol
B
usqueda del elemento bus en el arbol, analiza si
la raz es igual a bus si no son iguales entonces al
igual que el programa anterior se puede analizar si
es mayor o menor que la raz y asi poder seguir su
b
usqueda solo en un subarbol.
Cantidad de elementos en el
arbol, realiza un recorrido en el
arbol para verificar cuantos datos contiene el
arbol.
1
def vacio(arbol):
bolean = True
if arbol[0] != :
bolean = False
return bolean
def elemen(arbol):
n =len(arbol)
cant = 0
for i in range(n):
if arbol[i] != :
cant += 1
return cant
1
2
3
4
5
6
7
def busqueda(arbol,bus):
i = 0
bolean = True
while bolean:
if bus == arbol[i]:
bolean = False
print El elemento %d se encuentra
en la posicion %d %(bus,i)
else:
if bus < arbol[i]:
if izq(arbol,i) == False:
bolean = False
print El elemento %d no se
cuentra en el arbol %bus
else:
i = izq(arbol,i)
if bus > arbol[i]:
if der(arbol,i) == False:
bolean = False
print El elemento %d no se
cuentra en el arbol %bus
else:
i = der(arbol,i)
8
9
10
11
12
13
14
15
16
17
18
19
20
2.3.
Arbol
Balanceado
Un
arbol balanceado(figura 3), al igual que el arbol
binario de b
usqueda, es un tipo particular de arbol
binario que se define de la siguiente manera:
Un
arbol binario T no vaco con Ti y Td sus
sub
arboles izquierdo y derecho respectivamente, es un
arbol balanceado si cumple los siguientes enunciados:
Ti es un
arbol balanceado
Td es un
arbol balanceado
Figura 4: Arbol
balanceado
Figura 3: Arbol
binario balanceado
Figura A: Caso 1
Se utiliza una notaci
on muy sencilla para verificar
que es un
arbol binario balanceado, para cada nodo
se le asigna el valor h igual a la altura del subarbol
derecho menos la altura del sub
arbol izquierdo, si
para cualquier nodo su valor asignado h es 1, 0 o 1,
entonces podemos afirmar que es un
arbol balanceado.
En principio todo arbol balanceado puede ordenar sus
elementos de cualquier manera, pero en este texto se
considera que todo
arbol balanceado tambien es de
b
usqueda.
Figura B: Caso 2
3. El sub
arbol T 2 pasa a ser parte del hijo a izquierda del nodo A.
obteniendo despues de la rotaci
on la figura 5
Implementaci
on
Figura 5: Rotaci
on a derecha
Caso 2
Al intentar solo la rotaci
on a derecha como en el
caso 1, el
arbol sigue desbalanceado solo que ahora
el valor asignado es 2. As que realizaremos una
rotaci
on a izquierda en el sub
arbol a izquierda del
nodo A de la siguiente manera
1. Consideramos al
arbol como en la figura 6
2
3
4
5
6
8
9
10
11
12
13
def balanceo(arbol):
index = indices(arbol)
vali = validar(index)
if vali[0]:
#caso mover izquierda
if deraltu(arbol,vali[1]) izqaltu(arbol,vali[1])>0:
sarbol,arbol =
subarbol(arbol,vali[1],True)
#mover derecha de ser necesario
if deraltu(sarbol,0) izqaltu(sarbol,0)<0:
auxarbol,sarbol =
subarbol(sarbol,2,True)
auxarbol = rotader(auxarbol)
sarbol =
agregarsub(sarbol,auxarbol)
sarbol = rotaizq(sarbol)
14
15
16
17
18
19
20
21
22
Figura 7: Rotaci
on a izquierda
23
24
25
26
Analogamente hacemos el an
alisis cuando agregamos
el elemento en el sub
arbol a derecha del nodo A, con
lo cual cubrimos todos los posibles casos en los que el
arbol se puede desbalancear.
27
1
2
3
4
5
6
7
8
9
10
11
12
3.
def rotaizq(sub):
T1,sub = subarbol(sub,1,True)
aux,sub = subarbol(sub,2,True)
T2,aux = subarbol(aux,1,True)
T3,aux = subarbol(aux,2,True)
rotasub = []*10
rotasub = agregar(rotasub,aux[0])
rotasub = agregar(rotasub,sub[0])
rotasub = agregarsub(rotasub,T1)
rotasub = agregarsub(rotasub,T2)
rotasub = agregarsub(rotasub,T3)
return rotasub
Realiza la rotaci
on a derecha del
arbol sub.
1
2
3
4
5
6
7
8
9
10
11
12
Gr
afica de un
arbol
def rotader(sub):
T1,sub = subarbol(sub,2,True)
aux,sub = subarbol(sub,1,True)
T2,aux = subarbol(aux,2,True)
T3,aux = subarbol(aux,1,True)
rotasub = []*10
rotasub = agregar(rotasub,aux[0])
rotasub = agregar(rotasub,sub[0])
rotasub = agregarsub(rotasub,T1)
rotasub = agregarsub(rotasub,T2)
rotasub = agregarsub(rotasub,T3)
return rotasub
Figura 9: Analisis
de grafica
Por la propiedad de un arbol completo con altura h
podemos calcular el ancho del arbol, que sera el n
umero
de elementos que tiene el arbol(figura 9). La correspondencia de los elementos con la posicion en el ancho es
de la siguiente manera:
2. izqaltu(arbol,i)::
La altura a izquierda de un sub
arbol, donde su raz
se encuentra en la posici
on i.
i0 =
3. deraltu(arbol,i):
La altura a derecha de un sub
arbol, donde su raz
se encuentra en la posici
on i.
2h 1
.
2
4. agregarsub(arbol,subarbol):
Agrega un sub
arbol al
arbol, utilizando la funcion
agregar cada elemento del sub
arbol, as se mantiene la estructura.
in =
in1 1
2
5. indices(arbol):
Asigna a cada nodo el valor de la diferencia entre
su altura a derecha menos la altura a izquierda.
6. validar(arbol):
Valida si es necesario el balanceo.
i0 =
7. subarbol(arbol,i,elim):
En el
arbol determina un sub
arbol tal que su raz
se encuentra en la posici
on i, y si elim es True se
elimina los datos del
arbol.
24 1
= 7.
2
71
=3
2
Implementaci
on
La funci
on grafica determina la altura del
arbol, el
ancho del
arbol y en cada nivel imprime el espaciado
con la correspondencia entre cada nodo.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
def graficar(arbol):
n = altura(arbol)
anc = (2**n)-1
index = []
num = 0
print \n*******GRAFICA*******
for i in range(n):
print %.2d %(i+1),
cant = 2**i
espa = (anc-2*cant+1)/(2*cant)
auxindex = []
for k in range(espa,anc,espa+1):
auxindex.append(k)
for j in range(anc):
if j not in index and j in auxindex:
if num < len(arbol):
if arbol[num] != :
print %.2d %arbol[num],
else:
print --,
else:
print --,
num += 1
else:
print --,
index = index + auxindex
print
print
5.
4.
Posibles problemas
Soluciones
Podemos solucionar el problemas considerando los casos en donde se debe rotar elementos iguales, ya que la
funcion agregar siempre mandara el elemento igual hacia el subarbol izquierdo. Si consideramos dos casos: si
es rotacion a derecha tenemos que mandar el elemento
igual hacia el subarbol a derecha, pero si es rotaci
on a
izquierda mandar el elemento igual hacia el sub
arbol a
izquierda.
Para solucionar el problema del grafico es mucho mas
complejo su solucion ya que tendremos que analizar con
mas detenimiento las variables la cantidad de nodos n
su altura y el ancho del arbol.
Referencias
[1] thomas h. cormen y charles e. leiserson, Introduction to Algorithms, tercera edicion, 2009.
7