Post on 18-Nov-2018
Definição
Uma arvore B tem as seguintes propriedades
1. Cada nó tem os seguintes campos:
a) n[x], o numero de chaves correntemente armazenadas em nó x;
b) As n[x] chaves são armazenadas em ordem não
decrescentes, i.e., key1[x] key2[x] ... keyn[x][x];
c) leaf[x], o valor booleano é verdadeiro se x é uma folha e falso se x é um nó interno.
2. Cada nó interno também tem n[x]+1 ponteiros
c1[x], c2[x], ..., cn[x]+1[x] para seus filhos. Nós folhas
não tem filho. Portanto, seus respectivos ponteiros
ci são não definidos.
Definição
3. As chaves keyi[x] separam as regiões de chaves
armazenadas em cada sub-arvore: se ki é qualquer
chave armazenada em sub-arvore ci[x], então
k1 key1[x] k2 key2[x] ... keyn[x][x] ...kn[x]+1;
4. Todas folhas tem a mesma profundidade h (altura da
arvore);
Definição
5. Existem um limite máximo e mínimo de numero de
chaves para cada nó:
a) Cada nó exceto o nó raiz tem que tem peno
menos t-1 chaves. Então, cada nó interno exceto a
raiz tem pelo menos t filhos. Se arvore não for
vazia, a raiz tem que tem pelo menos 1 chave;
b) Cada nó pode ter no máximo 2t-1 chaves. Então,
um nó interno pode ter no máximo 2t filhos. Um nó
é dito cheio se tem exatamente 2t-1 chaves.
Um nó interno contém n[x] chaves e n[x]+1 filhos. Todas as folhas têm a mesma profundidade. Os nós pintados são visitados na busca pela letra R.
Árvore B
M
D H Q T X
B C J K L N P R S V W Y ZF G
raiz[T]
1000
1000 1000
1000 1000 1000
raiz[T]
1000
1001
1001
1001
. . .
. . .
1001
Uma árvore B com altura 2 contendo mais de um bilhão de chaves. Cada nó interno e cada folha contém 1000 chaves. Há 1001 nós com profundidade 1 e mais de um milhão de folhas com profundidade 2.
1
t - 1
t - 1t - 1 t...
t - 1
t
t - 1
t - 1t - 1 t...
. . . t - 1
t - 1t - 1 t...
t - 1
t
t - 1
t - 1t - 1 t...
. . .
Número de nós
1
2
2t
2(t^2)
Uma árvore B de altura 3 contendo o número mínimo possível de chaves.
Teorema: Se n 1, então, para qualquer arvore B de n nós, de altura h e grau mínimo t 2,
2
1log
nh t
Prova:
12
1
1121
2111
1
h
h
h
i
i
t
t
tt
ttnProfundidade 1: 1Profundidade 2: 2Profundidade 3: 2tProfundidade 4: 2t2
...
Busca em Árvores B
B-Tree-Search
i ← 1
while i <= n[x] and k > keyi[x]
do i ← i + 1
if i<= n[x] and k == keyi[x]
then return(x, i)
if leaf[x]
then return NIL
else DISK-READ(ci[x])
return B-Tree-Search(ci[x], k)
ntth tlogO tempo total de CPU:
Criação de uma Árvore B Vazia
B-Tree-Create
x ← Allocate-Node()
leaf[x] ← TRUE
n[x] ← 0
Disk-Write(x)
root[T] ← x
B-Tree-Create requer O(1) de operações de disco e O(1) no tempo da CPU.
... N W ...
x keyi
-1
[x] ke
yi [
x]
keyi
+1
[x]
... N S W ...
x keyi
-1
[x] ke
yi [
x]
P Q R S T U V
T1 T2 T3 T4 T5 T6 T7 T8
P Q R
T1 T2 T3 T4
T U V
T5 T6 T7 T8
y = ci [X] z = ci+1 [x]
Dividindo um nó com t = 4. O nó y é dividido em 2 nós, y e z, e a chave média S de y é movida para os pais de y.
DIVISÃO DE NÓS
y = ci [X]
z ← Allocate-Node()
leaf[z] ← leaf[y]
n[z] ← t – 1
for j ← 1 to t – 1
do keyj[z] ← keyj+t[y]
if not leaf[y]
then for j ← 1 to t
do cj[z] ← cj+t[y]
n[y] ← t – 1
for j ← n[x] + 1 downto i + 1
do cj+1[x] ← cj[x]
ci+1 [x] ← z
for j ← n[x] downto i
do keyj+1[x] ← keyj[x]
keyi[x] ← keyt[y]
n[x] ← n[x] + 1
Disk-Write(y)
Disk-Write(z)
Disk-Write(x)
B-Tree-Split-Child(x, i, y):
tO
O tempo total de CPU:
B-Tree-Insert(T, k)
r ← root[T]
if n[r] = 2t – 1
then s ← Allocate-Node()
root[T] ← s
leaf[s] ← FALSE
n[s] ← 0
c1[s] ← r
B-Tree-Split-Child(s, 1, r)
B-Tree-Insert-Nonfull(s, k)
else B-Tree-InsertNonfull(r, k)
ntth tlogO tempo total de CPU:
A D F H L N P
T1 T2 T3 T4 T5 T6 T7 T8
root[T]
rA D F
T1 T2 T3 T4
L N P
T5 T6 T7 T8
H
root[T]
s
Dividindo a raiz com t = 4. O nó raiz r é dividido em 2, e um novo nó raiz s é criado. O novo nó raiz contém a chave do meio de r e duas metades de r como filhos. A árvore B cresce 1 em altura quando uma raiz é dividida.
i ← n[x]
if leaf[x]
then while i >= 1 and k < keyi [x]
do keyi+1[x] ← keyi [x]
i ← i – 1
keyi+1[x] ← k
n[x] ← n[x] + 1
Disk-Write(x)
else while i >= 1 and k < keyi [x]
do i ← i – 1
i ← i + 1
Disk-Read(ci [x])
if n[ci [x]] == 2t – 1
then B-Tree-Split-Child(x, i, ci
[x])
if k > keyi [x]
then i ← i + 1
B-Tree-Insert-Nonfull(ci [x], k)
B-Tree-Insert-Nonfull(x, k):
G M P X
A C D E J K R S T U VN O Y Z
a) árvore inicial
G M P X
A B C D E J K R S T U VN O Y Z
b) B inserido
: nó alterado no processo. O grau mínimo t para esta árvore é 3, então um nó pode ter no máximo 5 chaves. a) A árvore inicial; b) Inserção simples em um nó folha.
G M P T X
A B C D E J K N O Y Z
c) Q inserido
Q R S U V
G M
A B C D E J K L N O Y Z
d) L inserido
Q R S U V
T X
P
c) Ao inserir a chave Q o nó RSTUV é dividido em dois, a chave T sobe e Q é inserido no nó mais a esquerda (UV); d) A raiz é dividida, pois está cheia, e a árvore cresce mais 1, então L é inserido na folha JK.
C G M
A B J K L N O Y Z
e) F inserido
Q R S U V
T X
P
D E F
e) O nó que contém ABCDE é dividido antes de F ser inserido no nó mais à direita (DE).
Eliminação de uma chave de uma arvore B
1. Se a chave k está no nó x e x é uma folha, elimine a chave k de x;2. Se a chave k está no nó x e x é um nó interno, faça a seguinte: a. Se o filho y que precede k no nó x tem pelo menos t chaves, então encontre o predecessor k´de k na subarvore com raiz em y. Elimine recursivamente k´ , e substitua k por k´em x (encontrar k´e eliminá-lo pode ser uma operação executada em uma única passagem descendente); b. Se o filho z que segue k no nó x tem pelo menos t chaves, então encontre o sucessor k´de k na subarvore com raiz em z. Elimine recursivamente k´ , e substitua k por k´em x (encontrar k´e eliminá-lo pode ser uma operação executada em uma única passagem descendente); c. Caso contrario, se tanto y quanto z tem apenas t-1 chaves, faça a intercalação de k e todos os itens z em y, de modo que x perca tanto k quanto o ponteiro para z, e y contenha 2t-1 chaves. Em seguida, libere z e elimine recursivamente k de y.
Eliminação de uma chave de uma arvore B
3. Se a chave k não estive no nó interno x, determine a raiz ci[x] da subarvore apropriada que deve conter k, se k estiver absolutamente na arvore. Se ci[x] tiver somente t-1 chaves, execute o passo 3a ou 3b conforme necessário para garantir que desceremos até um nó contendo pelo menos t chaves. Em seguida, encerre efetuando uma recursão sobre o filho apropriado de x. a. Se ci[x] tiver somente t-1 chaves, mas tiver um irmão com t chaves, forneça a ci[x] uma chave extra, movendo uma chave de x para baixo até ci[x], movendo uma chave do irmão esquerdo ou direito imediato de ci[x] para dentro de x, e movendo o ponteiro do filho apropriado do irmão para ci[x]; b. Se ci[x] e todos os irmãos têm t-1 chaves, faça a intercalação de ci[x] com um irmão, o que envolve mover uma chave de x para baixo até o novo nó intercalado, a fim de se tornar a chave mediana para esse nó.
C G M
A B J K L N O Y ZQ R S U V
T X
P
D E F
Arvore inicial
Eliminação de uma chave de uma arvore B
t = 3
C G M
A B J K L N O Y ZQ R S U V
T X
P
D E
F eliminado, caso 1
Eliminação de uma chave de uma arvore B
C G L
A B J K N O Y ZQ R S U V
T X
P
D E
M eliminado, caso 2a
Eliminação de uma chave de uma arvore B
C L P T X
A B E J K N O Y ZQ R S U V
D eliminado, caso 3b
A arvore escolhe no sentido da altura
Eliminação de uma chave de uma arvore B
Exercícios
• Mostre os resultados da inserção das chaves F S Q K C L H T V W M R N P A B X Y D Z E nesse ordem em uma arvore B vazia com t = 2.• Explique como encontrar a chave mínima armazenada em uma arvore B e como encontrar o predecessor de uma dada chave. • Mostre os resultados da eliminação de C, P e V, nessa ordem, da arvore do último exemplo.