Anda di halaman 1dari 12

UNIVERSIDADE FEDERAL DO PARÁ

INSTITUTO DE CIÊNCIAS EXATAS E NATURAIS

CURSO DE BACHARELADO EM CIÊNCIAS DA COMPUTAÇÃO

Projetos de Algoritmos II

UFPA

Belém,18 de Dezembro de 2013


Introdução

Um Heap de Fibonacci é uma estrutura de dados de proposta dual:


. Suporta um grupo de operações que constituem uma estrutura chamada de Heap
mesclável.
. Algumas operações do Heap de Fibonacci são executadas em tempo amortizado
constante, o que o torna adequado para aplicações que invocam estas operações
constantemente.
Aplica-se bem, do ponto de vista teórico, em aplicações onde o número de EXTRACT-MIN e
DELETE é pequeno em Relação às outras operações.

Aplicações: cálculo de árvores geradoras mínimas e busca por menores caminhos dada uma
origem.
É um bom exemplo de estrutura de dados projetada com análise amortizada em mente.
Não foi projetada para dar um suporte eficiente a operação SEARCH.

Um Heap Mesclável é qualquer estrutura de dados que suporta as cinco seguintes operações,
nas quais cada elemento tem uma chave:

Heap Mesclável
1. MAKE-HEAP(), cria e retorno um heap vazio.
2. INSERT(H,X), insere o elemento x, cuja chave já tenha sido definida, no heap H.
3. MINIMUN(H), retorna um ponteiro para o elemento no heap H cuja chave é mínima.
4. EXTRACT-MIN(H), deleta o elemento do heap H cujoa chave é mínima, retornando um
ponteiro para o elemento.
5. UNION(H1,H2), cria e retorno um heap que contem todos os elementos dos heaps H1 e H2.
Os heaps h1 e H2 são destruídos nesta operação.

Um heap de Fibonacci é um heap mesclável que também suporta as duas operações:


1. DECREASE-KEY(H, x, k), assinala a um elemento x do heap H um nova valor k para sua chave,
o qual ´e assumindo ser um valor não maior que o valor atual.1
2. DELETE(H, x), deleta o elemento x do heap H.

1Aqui será adotado o padrão como heap m´mínimo, sendo as operações de


MINUMUM, EXTRACT-MIN e DECREASE-KEY aplicáveis. Contudo também
seria possível definir um heap m´máximo, onde existiriam as funções MAXIMUM,
EXTRACT-MAX e INCREASE-KEY.
Prof. Tiago A. E. Ferreira Disciplina
Prof. Tiago A. E. Ferreira Disciplina de Projetos

Heap de Fibonacci

 Os Heaps de Fibonacci, em teoria, são desejados quando a quantidade de


chamadas das funções de EXTRACT-MIN e DELETE são mito menores que a
quantidade de chamada das demais funções.

 Na prática, os fatores constantes e a complexidade de implementação faz os heaps de


Fibonacci serem menos desejáveis do que os heaps binários para a maior parte das
aplicações, exceto as aplicações com grandes montantes de dados.

 De forma geral, o interesse nos Heaps de Fibonacci são basicamente teóricos.

Estrutura
Um Heap de Fibonacci é um conjunto de árvores que são heaps mínimos. Cada árvore
obedece a propriedade do heap mínimo:
 A chave de um dado nodo é maior ou igual da chave do seu pai.
 Cada nodo x do heap de Fibonacci tem um ponteiro x.p para seu pai e um ponteiro x.child
para cada um de seus filhos.
 Todos os filhos do nodo x são unidos por meio de uma lista.
 Circular e duplamente encadeada. Esta lista é uma chamada de lista de filhos de x.
 Cada filho y tem os ponteiros y.left e y.right que apontam para os seus irmãos da esquerda
e direita respectivamente.
 Se o nodo y não tiver irmãos, então y.left = y.right = y.
 Os irmãos podem aparecer na lista de filhos em qualquer ordem.
 As listas circulares têm duas vantagens:

1. É armazenado o número de filhos da lista de filhos do nodo x em x.degree.


2. O Atributo de valor booleano x.mark indica se x tem perdido um filho desde
da última vez que este tem sido filho de outro nodo.
 Os nodos criados são unmarked, e um nodo x se torna unmarked se este é
feito filho de outro nodo.

 Um Heap de Fibonacci H é acessado por um ponteiro H.min para a raiz de uma árvore
contendo a menor chave.
 Este nodo é chamado de nodo mínimo do Heap de Fibonacci.

 As raízes de todas as árvores são unidas por ponteiros left e right em um lista
circular e duplamente encadeada, chamada lista de raízes do Heap de Fibonacci.
 Existe ainda o atributo H.n que armazena o número de nodos correntes no Heap H.

Método do Potencial – Análise Amortizada


Em linhas gerais, a análise de custo amortizada é uma análise media, onde se garante o
desempenho médio de cada operação para o pior caso. Em particular, há o método do
potencial:

 Neste método, o trabalho a ser realizar é considerado como energia potencial,


ou simplesmente potencial, o qual pode ser liberado para pagar as operações
futuras.
 O potencial é associado á estrutura como um todo.

Para um Heap de Fibonacci H, indica-se por t(H) o número de árvores na lista de Raízes
de H e m(H) o número de nodos marcados em H.

É possível definir a função potencial (H) para o Heap H como,

Φ(H) = t(H) + 2m(H)


 A função potencial para um conjunto de Heaps é a soma dos potenciais.
 É assumido que uma aplicação de um Heap de Fibonacci começa com um
Heap vazio (sem heaps).
 Desta forma, a função potencial é zero.
 O potencial é sempre não negativo para todo tempo subsequente.
 Assuma que seja conhecido o limite superior D(n) sobre o grau máximo de
qualquer nodo em um Heap de Fibonacci com n nodos.
 Quando apenas operações de mesclarem são suportadas, tem-se.

 E quando s ao suportadas as funções DECREASE-KEY e DELETE,

Operações de Heap Mesclável


Várias operações em um Heap de Fibonacci desempenham um
“trade-off ”. Por exemplo,
 Inserção de um nodo adicionando-o a lista de raiz, o que toma um tempo
constante.
 Começando com um heap vazio, e adicionando k nodos, tem-se uma
lista de raiz com k nodos.
 O “trade-off ” ´e que se a função EXTRACT-MIN ´e invocada, apos a
remoção no nodo apontado por H.min, há a necessidade de realizar
uma busca pela menor chave nos k – 1 nodos restantes em H.

Criação
Para criar um Heap de Fibonacci vazio, a função MAKE-FIB-HEAP aloca e retorna um
objeto tipo Heap de Fibonacci H, onde.
 H.n = 0
 H.min = NIL
 Não existem árvores em H
 Devido ao fato de t(H) = 0 e m(H) = 0, o potencial é Φ (H) = 0.
 Assim, o custo amortizado da função MAKE-FIB-HEAP é O(1)

Inserção
Assumindo que um dado nodo x já tenha sido alocado e que x.key já tenha sido
preenchida, é possível inserir este nodo em um Heap de Fibonacci da seguinte forma,

FIB-HEAP-INSERT(H, x)
1 x.degree = 0
2 x.p = NIL
3 x.child = NIL
4 x.mark = FALSE
5 if H.min == NIL
6 create a root list for H containing just x
7 H.min = x
8 else insert x into H0s root list
9 if x.key < H.min.key
10 H.min = x
11 H.n = H.n + 1

As linhas 1-4 inicializam os atributos estruturais o nodo x.


Linha 5 teste se o Heap de Fibonacci está vazio.
 Se sim, linhas 6-7 faz com que x seja o único nodo da lista de raiz e ajusta
H.min para x.
 Se não, As linhas 8-10 inserem x na lista de raiz e atualiza, se necessário,
H.min.
Na linha 11 o valor de H.n é atualizado devido a inserção de um novo nodo.

Seja H o Heap de Fibonacci de entrada e H0 o Heap de Fibonacci de saída.


Então,
t(H0) = t(H) + 1
m(H0) = m(H)
e o aumento no potencial é

((t(H) + 1) + 2m(H)) − (t(H) + 2m(H)) = 1

Uma vez que o custo atual é O(1), o custo amortizado é O(1) + 1 = O(1).

Mínimo
O nodo mínimo de um Heap de Fibonacci é sempre dado pelo ponteiro H.min.
 Assim, é possível encontrar o nodo mínimo em tempo constante O(1).

Devido ao fato que o potencial de H não se alterar, o custo amortizado desta operação
também é O(1).
União

Na união de dois Heap de Fibonacci H1 e H2, um terceiro Heap de Fibonacci, H, é


criado e H1 e H2 são destruídos.
A ideia é muito simples, concatena-se as duas listas de raízes de H1 e H2, e então
determina-se um novo nodo mínimo.

FIB-HEAP-UNION(H1,H2)
1 H =MAKE-FIB-HEAP()
2 H.min = H1
3 concatenate the root list of H2 with the root list of H
4 if (H1.min == NIL) or (H2.min 6= NIL and H2.min.key < H1.min.key)
5 H.min = H2.min
6 H.n = H1.n + H2.n
7 return H

Nas linhas 1-3 há a concatenação da listas de raízes de H1 e H2 em H


As linhas 2,4 e 5 ajustam o nodo mínimo de H
A linha 6 ajusta o número de nodos em H.n
A linha 7 retorno o Heap H com a única de H1 com H2.
A alteração no potencial é
Φ(H) − (Φ (H1) + Φ (H2))
= (t(H) + 2m(H)) − ((t(H1) + 2m(H1)) + (t(H2) + 2m(H2)))
=0
uma vez que t(H) = t(H1) + t((H2) e
m(H) = m(H1) + m(H2). Assim o custo amortizado é O(1).
Prof. Tiago

Extração
A extração do nodo mínimo é a operação mais complicada desta seção.
O pseudo código a seguir extrai o nodo mínimo de um Heap de Fibonacci.
 É assumido que quando um nodo é extraído de uma lista encadeada, os
ponteiros remanescentes da lista são atualizados, mas os ponteiro do
nodo extraído são deixados inalterados.
 Este pseudo código também realiza a chamada a função CONSOLIDATE,
a qual consolida as árvores presentes na lista de raiz de H.

FIB-HEAP-EXTRACT-MIN(H)
1 z = H.min
2 if z 6= NIL
3 for each child of z
4 add x to the root list of H
5 x.p = NIL
6 remove z from the root list of H
7 if z == z.right
8 H.min = NIL
9 else H.min = z.right
10 CONSOLIDATE(H)
11 H.n = H.n − 1
12 return z

Na linha 1, o ponteiro z aponta para o o nodo mínimo de H, H.min. O função retorna este
ponteiro ao termino.
 Se z = NIL então o Heap de Fibonacci ´e vazio.
 Caso contrário, deleta-se z de H fazendo todos os filhos de z raízes de H (linhas
3-5), removendo-se z da lista de raiz de H (linha 6).
 Se z é o seu próprio irmão direito apos a linha 6, então z era o único nodo na
lista de raiz e este não tinha filhos, faltando apenas fazer o Heap de Fibonacci
ser vazio (linha 8).
 Caso contrário, H.min ´e ajustado ser o irmão direito de z. Observe que não
necessariamente este ´e o nodo mínimo.
O próximo passo é reduzir o número de árvores no Heap de
Fibonacci, consolidando a lista de raiz de H – invoca-se a
função CONSOLIDATE.

Consolidar a lista de raiz ´e repetidamente executar os seguintes passos até toda raiz na lista
de raízes ter um grau distinto.
1. Encontre duas raízes x e y na lista de raiz com o mesmo grau.
Sem perda de generalidade, faça x.key ≤ y.key.
2.Una y a x: remova y da lista de raiz, e faça y ser um filho de x invocando a função
FIB-HEAP-LINK. Esta função incrementa o atributo x.degree e limpa a marca de y.
Fib-Heap-Link (H,y,x)
1 remove y da lista raiz de H
2 cria um child no x, incrementando x.degree
3 y.mark = false
Decrease-key
Aqui mostramos como a redução de uma chave de um nó em um HF pode ser realizada com
custo amortizado O(1).
Mais adiante, mostraremos que a deleção de um nó pode ser executada em tempo amortizado
O(D(n)).
Essas operações não preservam a propriedade de que todas as árvores no HF são árvores
binomiais não ordenadas.
Estas árvores são “próximas” o suficiente para se limitar o grau máximo D(n) por o(lgn).
((t(H) + c) + 2 (m(H) – c +2)) – (t(H)+2m(H))=4 – c.

Desse modo, o custo amortizado de FIB-HEAP-DECREASE-KEY é


no máximo.

O(c) + 4 - c = O(1),

Delete
Conclusão

Aplica-se bem, do ponto de vista teórico, em aplicações onde o número de FIB-HEAP-


EXTRACT-MIN e DELETE é pequeno em relação às outras operações. Exemplos de
aplicações: cálculo de árvores geradoras mínimas e busca por menores caminhos dada
uma origem.
Não foi projetada para dar um suporte eficiente a operação SEARCH.
Do ponto de vista prático, os fatores constantes e a complexidade a tornam pouco
desejável para a maioria dos problemas.
Complexidade das operações sobre Heaps de Fibonacci são provadas com análise
amortizada.
Andr

Capítulo 19 do livro do Cormen;

Anda mungkin juga menyukai