algoritmo pior

Propaganda
1.6 Filas de Prioridade Implementadas
por Heaps Binários
Motivação: Vimos que as soluções anteriores para
implementar filas de prioridade têm limitações que
podem levar a uma degradação de performance em
alguns casos (algoritmos lineares O(n)). Então
devemos procurar por soluções mais eficientes!!!
 Heap é um tipo especial de árvore binária utilizado
para implementar eficientemente filas de
prioridade.
 Características do Heap Binário:
- Simplicidade: implementado num array
- Eficiente: inserção e remoção no pior caso é
O(logN)
inserção: tempo médio constante
findMin: O(1) no pior caso
 Heap Binário apresenta duas propriedades:
1. Propriedade de Estrutura
2. Propriedade de Ordem
1.6.1 Propriedade de Estrutura
 Um heap é uma árvore binária completa cujos
valores estão armazenados em seus nós de tal
forma que nenhum filho possui valor maior do que
seu pai.
 Revisando: Uma árvore binária completa é uma
árvore que é completamente preenchida, com
exceção dos nós folhas, que são preenchidos da
esquerda para direita.
Ex.1: Árvore Binária Completa
1
B
2
4
H
8
A
D
5
E
I J
9
1
10
6
3
C
F
7
G
Ex.2: Uma árvore binária incompleta
1
2
4
H
8
D
A
B
5
3
E
6
C
F
J
10
Exercício: Crie uma árvore binária completa de
pesquisa para os seguinte conjunto { 10, 30, 40, 20,
55, 24, 76, 63, 98, 87, 25, 12, 9, 3}
Propriedades de uma árvore binária completa:
 A altura de uma árvore de N nós é no máximo
log N, pois uma árvore completa de altura H
tem entre 2H e 2H + 1 – 1 nós.
 As referências esquerda e direita não são
necessárias, pois podemos implementar a
árvore com caminhamento por níveis
(esquerda-direita) num array.
Ex.3. A árvore do Ex.1. pode ser representada pelo
seguinte array:
A B C D E F
0 1 2 3 4 5 6
G H I J
7 8 9 10 11 12 13
Algoritmo para representação de uma árvore binária
completa num array:
1. Coloca-se a raiz na posição 1 (para simplificar a
operação de achar o pai de um elemento)
2. Manter uma variável que contém quantos nós
existem na árvore
3. Para cada elemento i no array
- o filho a esquerda está na posição 2i
- o filho à direita está na posição 2i + 1
Obs.: (se esta posição (2i ou 2i+1) ultrapassa o
número de nós => este filho não existe)
- o pai está na posição i/2
Esta representação de árvore binária completa num
array é chamada de representação implícita e otimiza
a performance de caminhamento na árvore uma vez
que apenas uma operação matemática é necessária
para acessar um filho ou pai (facilita o
caminhamento).
1.6.2 Propriedade de Ordem de um Heap
 Propriedade que permite a execução rápida de
operações sobre heaps
 Uma vez que a operação de remoção é efetuada
sempre sobre o elemento de maior chave, é
interessante que ele se encontre sempre na raiz
 Definição da Propriedade de Ordem:
Em um heap, para todo nó X, a chave do pai de X é
menor ou igual à chave de X, com a exceção óbvia da
raiz (não tem pai).
Ex. 4. Uma árvore binária completa que é um heap
1
4
2
30
36
5
42
10
3
65
78
7
6
45 55 80
8
9
1
10
97
2
Ex. 5. Uma árvore binária completa que não é um
heap
1
4
2
30
16
5
42
10
3
65
76
7
90
6
45 55 80
8
9
10
1
Exercício: Desenhe um heap para o seguinte conjunto
de inteiros {10,25,30,35, 40, 45, 50, 55, 60, 65}
1.6.3 Operações básicas sobre Heaps
No nosso caso, queremos usar heap para implementar
filas de prioridade, portanto, o heap deve
implementar as operções do TAD FilaPrioridade que
estudamos anteriormente:





inserir(x)
removerMin()
encontrarMin()
ehVazio()
tamanho()
Vamos enfatizar os métodos insert(x) e removeMin()
que são os mais importantes, deixamos os outros
métodos como exercicio.
Inserção
O algoritmo de inserção contém os seguintes passos:
1. Criar um espaço na próxima posição disponivel
2. Se x puder ser colocado nesse espaço novo sem
violar as propriedades do heap, inserimos x
naquela posição
3. Senão, deslocamos o pai desse novo nó criado
para ocupá-lo e o espaço que era do pai fica
disponível para a inserção de x
4. Repetir o processo de deslocamento até que o
elemento x possa ser inserido no espaço disponível
sem burlar as propriedades de heaps.
Ex.6. Inserir o elemento de chave 15 no heap abaixo
1
4
2
30
35
5
42
10
3
65
76
7
90
6
45 55 80
9
8
10
1
i.
Criar um novo espaço no heap
1
4
2
30
35
5
42
10
3
65
76
7
6
45 55 80
8
9
1
10
11
90
ii. Tenta inserir “15” no novo espaço criado, caso
não possa baixa o pai para a nova posição
1
4
10
2
30
3
65
35
5
76
7
90
6
45 55 80 42
9
8
10
11
1
1
2
4
35
5
30
10
3
65
76
7
6
45 55 80 42
8
9
1
10
11
90
1
4
2
15
35
5
30
10
3
65
76
7
90
6
45 55 80 42
8
9
10
11
1
Algoritmo de Inserção:
Remoção em Heaps
 Remoção é tratada da mesma forma que inserção
 Achar a menor chave é simples devido à
propriedade de ordem
 A parte mais difícil é tratar o espaço deixado na
raiz após remoção do elemento, de modo a não
violar as propriedades do heap
Algoritmo de remoção:
1. Remover o elemento da raiz criando um espaco na
raiz
2. Mover o último elemento x do heap para algum
lugar
3. Se x puder ser colocado no espaço criado, fim
4. Senão, mover o menor dos filhos do nodo com
espaço disponível para o espaço disponível. O
espaço disponível desce um nível
5. Repetir o passo 4 até que x ocupe o espaço
disponível
Ex7. Remoção de um heap binário
1
4
2
30
35
5
10
42
3
65
76
7
90
6
45 55 80
9
8
10
1
i-
Remove a raiz
1
4
2
30
35
5
42
3
65
76
7
6
45 55 80
8
9
1
10
90
ii- Elege o menor dos filhos para ser raiz
30
1
2
35
4
5
42
3
65
76
7
90
6
45 55 80
9
8
10
1
iii – Tenta inserir o ultimo elemento (80) no espaço
criado, como não pode, escolhe o menor dos filhos
para subir para o espaço livre (35)
1
35
2
4
5
42
30
3
65
76
7
6
45 55 80
8
9
1
10
90
iv- Tenta inserir o último elemento (80) no novo
espaço criado, como não consegue, escolhe o
menor dos filhos do espaço livre (45).
1
4
2
35
45
5
42
30
3
65
76
7
6
55 80
8
9
1
10
90
v – Finalmente, consegue inserir o último elemento
(80) no espaço livre e o algoritmo termina.
1
4
2
35
45
5
42
30
3
65
76
7
6
80 55
8
9
1
90
Exemplo de implementação da interface de Fila de
Prioridade usando Heap Binário representado em
Array.
public class HeapBinario implements FilaPrioridade
{
private int tamanho;
private boolean ordemOK; // True se ordem do heap esta OK
private Comparador [] heap;
private static final int CAPACIDADE_DEFAULT = 11;
public HeapBinario (Comparador negInf ) {
tamanho = 0;
ordemOK = true;
heap = new Comparador [CAPACIDADE_DEFAULT + 1];
heap[0] = negInf; // sentinela que contem um valor menor que todos
do heap
}
public void inserir (Comparador x)
{
checkTamanho();
int lugar = ++ tamanho;
for (; x.ehMenorQue( heap[lugar/2] ); lugar /= 2)
heap [lugar] = heap[lugar/2];
heap[lugar] = x;
}
public Object encontrarMin() throws Exception
{
if ( ehVazio() )
throw new Exception("ERRO: Heap Vazio");
return heap[1];
}
public Object removerMin() throws Exception
{
Comparador minItem = (Comparador) encontrarMin();
int filho;
int lugar = 1;
heap[1] = heap[tamanho--];
Comparador tmp = heap[1];
for (; lugar * 2 <= tamanho; lugar = filho) {
filho = lugar * 2;
if
(filho
!=
tamanho
&&
1].ehMenorQue(heap[filho]))
filho++;
if (heap[filho].ehMenorQue(tmp))
heap[lugar] = heap[filho];
else
break;
}
heap[lugar] = tmp;
return minItem;
}
public boolean ehVazio() {
return tamanho == 0;
}
heap[filho
+
private void checkTamanho()
{
if ( tamanho == heap.length - 1 )
{
Comparador [] heapAnterior = heap;
heap = new Comparador[tamanho*2];
for (int i=0; i < heapAnterior.length; i++)
heap[i] = heapAnterior[i];
}
}
public int tamanho () {
return tamanho;
}
}
public class TesteHB
{
public static void main (String[] args)
{
HeapBinario fp = new HeapBinario(new MeuInteger(0));
fp.inserir(new MeuInteger(10));
fp.inserir(new MeuInteger(20));
fp.inserir(new MeuInteger(5));
fp.inserir(new MeuInteger(40));
fp.inserir(new MeuInteger(50));
fp.inserir(new MeuInteger(15));
try {
MeuInteger v = (MeuInteger) fp.removerMin();
System.out.println(" v= " + v.getX());
v = (MeuInteger) fp.encontrarMin();
System.out.println(" EncontrarMin v= " + v.getX());
v = (MeuInteger) fp.removerMin();
System.out.println(" v= " + v.getX());
v = (MeuInteger) fp.encontrarMin();
System.out.println("Encontrar Min = " + v.getX());
v = (MeuInteger) fp.removerMin();
System.out.println(" v= " + v.getX());
v = (MeuInteger)fp.removerMin();
System.out.println(" v= " + v.getX());
v = (MeuInteger)fp.removerMin();
System.out.println(" v= " + v.getX());
v = (MeuInteger)fp.removerMin();
System.out.println(" v= " + v.getX());
v = (MeuInteger)fp.removerMin();
System.out.println(" v= " + v.getX());
v = (MeuInteger)fp.removerMin();
System.out.println(" v= " + v.getX());
} catch (Exception e) {System.err.println(e.toString());}
}
}
Resultado da execução anterior:
C:\EstruturaDados\Programas>java TesteHB
v= 5
EncontrarMin v= 10
v= 10
EncontarMin = 15
v= 15
v= 20
v= 40
v= 50
java.lang.Exception: ERRO: Heap Vazio
Download