Heaps e Filas de Prioridade
Fundamentos
Filas de Prioridade
Uma fila de prioridade é uma lista de itens na qual
cada item possui uma prioridade associada.
Pode-se determinar o item que tem a maior e o que
tem a menor prioridade, por exemplo.
Itens são inseridos em filas de prioridade em
qualquer ordem. A exclusão de itens é feita em
ordem decrescente de prioridade.
3
Filas de Prioridade
Filas de prioridade são containers que possuem as
seguintes operações:

enqueue


findMin (ou findMax)


colocar objetos no container;
retornar o objeto de menor prioridade no container
dequeueMin ( ou dequeueMax)

remover o menor objeto do container.
Uma fila de prioridades é usada para armazenar
um conjunto de chaves de um conjunto ordenado
de chaves K.
4
Árvore Binária Perfeita
Definição (Árvore Binária Perfeita)
Uma árvore binária perfeita de altura h  0,
é uma árvore binária {R, TL, TR} com as
seguintes propriedades.
1. Se h=0, TL = 0 e TR = 0.
2. Para h>0 tanto TL quanto TR são árvores
binárias perfeitas de altura h-1.
5
Árvore Binária Completa
Definição (Árvore Binária Completa) Uma
árvore binária completa de altura h  0, é uma
árvore binária {R, TL, TR} com as seguintes
propriedades.
1. Se h=0, TL = 0 e TR = 0.
2. Para h>0 existem duas possibilidades
1.
2.
TL é uma árvore binária perfeita de altura h-1 e TR é
uma árvore binária completa de altura h-1; ou
TL é uma árvore binária completa de altura h-1 e TR é
uma árvore binária perfeita de altura h-2.
6
Exemplo de árvores perfeitas e completas
Raiz da sub árvore
2
3
4
5
Tipo de árvore
Completa
Perfeita
Perfeita
Completa
Altura
3
2
2
2
7
Árvore N-aria Completa
Definição (Árvore N-aria Completa) Uma
árvore N-aria completa de altura h  0, é uma
árvore N-aria {R, T0, T1, T2, ... TN-1} com as
seguintes propriedades.
1. Se h=0, T1 =  para todo i, 0  i < N.
2. Para h>0 existe um j, 0  j < N tal que
1.
2.
3.
Ti é uma árvore N-aria perfeita de altura h-1 para todo i:
0  i < j;
Tj é uma árvore N-aria completa de altura h-1;
Ti é uma árvore N-aria perfeita de altura h-2 para todo
i:j<i<N.
8
Árvore N-aria completa
Uma árvore completa é uma árvore na qual todos os
níveis estão cheios exceto o último e este nível é cheio da
esquerda para a direita.
9
Heap
As implementações de filas de prioridade são
baseadas em um tipo especial de árvore chamado de
heap
Há dois tipos de heap (min e max)
Definição ((Min) Heap) Um (Min) Heap é uma
árvore, {R, T0, T1, T2, ... TN-1} com as seguintes
propriedades:
1.
2.
Cada sub árvore de T é um heap,
A raiz de T é menor ou igual do que a raiz de cada sub
árvore de T. Ou seja, R  Ri para todo i, 0  i  n ,
aonde Ri é a raiz de Ti.
10
Heap Binário
Um heap binário é uma árvore binária
ordenada que tem a forma de árvore
completa.
Um heap binário pode ser implementado
sobre um “array”, o que dispensa o
armazenamento de ponteiros para a
montagem da árvore.
11
Incluir Itens em um Heap Binário
Como o heap resultante da inclusão deve ser uma árvore completa só existe
um local para a inclusão.
Para incluir o item de chave 2 no heap da figura verifica-se a posição da
inclusão (figura (a) ). A seguir reajusta-se o heap até chegar à posição
adequada (figuras (b) e (c)). Finalmente faz-se a inclusão (figura (d)).
12
Remover Itens de um Heap Binário
O menor dos itens está sempre na raiz de um
heap mínimo.
A última linha do heap deve ser esvaziada
da direita para a esquerda na remoção de
itens.
O dado a ser removido está na raiz mas o nó
a ser removido está em folha.
13
Exemplo de Heap
No heap da figura a operação dequeueMin remove a chave 2 do heap mas o nó contendo 6 é que
deve ser removido.
O buraco deixado pela remoção da raiz deve ser reposicionado no heap, descendo até permitir a
reinserção na árvore da chave 6 que ocupava a posição do heap a ser eliminada
Para afastar da raiz um buraco este troca de lugar com o menor de seus dois filhos.
O processo continua até o buraco atingir uma folha da árvore ou uma posição adequada à chave que
necessita ser reposicionada na árvore.
14
Implementação Java
Implementação
16
Interface PriorityQueue
//
pgm11_01.txt
public interface PriorityQueue
extends Container
{
void enqueue (Comparable object);
Comparable findMin ();
Comparable dequeueMin ();
}
17
Interface MergeablePriorityQueue
//
pgm11_02.txt
public interface
MergeablePriorityQueue
extends PriorityQueue
{
void merge
(MergeablePriorityQueue queue);
}
18
Campos de BinaryHeap
//
pgm11_03.txt
public class BinaryHeap
extends AbstractContainer
implements PriorityQueue
{
protected Comparable[] array;
// ...
}
19
Métodos Construtor e purge da classe
BinaryHeap
//
pgm11_04.txt
public class BinaryHeap
extends AbstractContainer
implements PriorityQueue
{
protected Comparable[] array;
public BinaryHeap (int length)
{ array = new Comparable[length + 1]; }
public void purge ()
{
while (count > 0)
array [count--] = null;
}
// ...
}
20
Método enqueue da classe
BinaryHeap
• Como o heap resultante da inclusão deve ser uma
árvore completa só existe um local para a inclusão
• Este local (vazio ou buraco) vai “subir” no heap
até encontrar seu ligar, deixando para baixo os
valores menores do que o objeto o incluir no heap
• A “subida” no heap é feita buscando-se a posição
do array obtida da divisão por dois da posição
corrente
• Quando o buraco parar de “subir” nele inclui-se o
objeto
21
Método enqueue da classe
BinaryHeap
//
pgm11_05.txt
public void enqueue (Comparable object)
{
if (count == array.length - 1)
throw new ContainerFullException ();
++count;
int i = count;
while (i > 1 && array [i/2].isGT (object))
{
array [i] = array [i / 2];
i /= 2;
}
array [i] = object;
}
22
Método findMin da classe
BinaryHeap
//
pgm11_06.txt
public class BinaryHeap
extends AbstractContainer
implements PriorityQueue
{
protected Comparable[] array;
public Comparable findMin ()
{
if (count == 0)
throw new ContainerEmptyException ();
return array [1];
}
// ...
}
23
Método dequeue da classe BinaryHeap
O elemento a ser removido é o da raiz do heap
O objeto que estava no último nó do heap deve
procurar seu lugar no heap pois esse nó vai
desaparecer
Inicia-se pela raiz, agora vazia, testando-se seus dois
filhos para verificar o menor
Se o objeto que estava no último nó for menor que os
filhos da raiz termina a repetição
Caso contrário a raiz (objeto que estava no último nó)
troca de lugar com o menor de seus dois filhos e
passa a ser a raiz do heap corrente a pesquisar
Quando a repetição termina a raiz no heap corrente
recebe o objeto que estava no último nó
24
Método dequeue da classe BinaryHeap
public Comparable dequeueMin ()
{
if (count == 0)
throw new ContainerEmptyException ();
Comparable result = array [1];
Comparable last = array [count];
--count;
int i = 1;
while (2 * i < count + 1)
{
int child = 2 * i;
if (child + 1 < count + 1
&& array [child + 1].isLT (array [child]))
child += 1;
if (last.isLE (array [child]))
break;
array [i] = array [child];
i = child;
}
array [i] = last;
return result;
}
25
Exemplos
Exemplos
Serão apresentados dois exemplos de uso de
Filas de Prioridade
O primeiro exemplo é absolutamente trivial
com inclusão e exclusão de objetos
manualmente, via teclado
O segundo exemplo consiste em uma
simulação de eventos discretos
27
Exemplo de uso de Fila de Prioridade em
simples entrada e saída de dados
Exemplo usando o teclado para inserir
dados inteiros em uma fila de prioridade
O usuário recebe um “prompt” para
escolher entre inserir, remover dados, listas
a fila de prioridade ou encerrar o programa
Caso escolha a inserção o usuário deve
entrar com o dado
28
Composição do código
A hierarquia de classes já foi apresentada no
estudo da classe BinaryHeap
Serão apresentadas as classes específicas
desta aplicação
Classe de Dados
 Classe da Aplicação Fila de Prioridade

29
Classe de Dados (1)
import cap5.*;
import java.io.*;
public class DataArea
extends AbstractObject
implements Serializable
{
private String numero;
private String transacao;
final private int TAMANHO_INT = 2;
public DataArea()
{
this.numero
}
= "";
public DataArea( String numero)
{
if ( numero.length() < TAMANHO_INT )
{
numero = "0"+numero;
}
this.numero
}
= numero;
30
Classe de Dados (2)
public DataArea( BufferedReader br )
throws IOException
{
int
i = 0;
String
s, line = br.readLine();
if ( line == null )
{
transacao = "err";
return;
}
transacao = line.substring(i,1);
i = 2;
if ( transacao.compareToIgnoreCase( "i" ) == 0 )
{
numero = line.substring(i,i+TAMANHO_INT);
i += TAMANHO_INT+1;
nome = line.substring(i,i+TAMANHO_NOME);
i += TAMANHO_NOME+2;
s = line.substring(i,line.length());
salario = Double.parseDouble( s );
}
}
31
Classe de Dados (3)
public String getNumero()
{
return numero;
}
public String getTransacao()
{
return transacao;
}
public void setNumero( String numero )
{
this.numero = numero;
}
}
public void imprime()
{
System.out.println ("Numero = " + numero );
}
protected int compareTo (cap5.Comparable object)
{
DataArea arg = (DataArea) object;
return numero.compareToIgnoreCase( arg.numero );
}
}
32
FilaPrioridade01 (1)
import cap5.*;
import dados.*;
import java.io.*;
import corejava.*;
public class FilaPrioridade01
{
private static void lerDados( PriorityQueue listaP )
{
DataArea data = null;
String transacao = "ok";
try
{ BufferedReader br =
new BufferedReader( new FileReader("xxxx.zzz") );
while ( transacao.compareToIgnoreCase( "err" ) != 0 )
{
data = new DataArea( br );
transacao = data.getTransacao();
if ( transacao.compareToIgnoreCase( "i" ) == 0 )
stack.push( data );
}
br.close();
}
catch(Exception e)
{
33
}
}
FilaPrioridade01 (2)
public static void main (String[] args)
{
String numero;
DataArea data;
Enumeration todos;
PriorityQueue filaP = new LeftistHeap();
lerDados( listaP );
boolean continua = true;
while (continua)
{ System.out.println('\n' + “==================");
System.out.println('\n' + "O que deseja fazer?");
System.out.println('\n' + "1. Inserir");
System.out.println("2. Remover");
System.out.println("3. Listar");
System.out.println("4. Sair");
34
FilaPrioridade01 (3)
int opcao = Console.readInt('\n' +
"Digite um número entre 1 e 4:");
switch (opcao)
{
case 1:
{ numero = Console.readLine('\n' + "Digite o numero: ");
data = new DataArea (numero);
filaP.enqueue(data);
System.out.println('\n' + "Inserido com sucesso!");
break;
}
case 2:
// Remover
{
data = (DataArea) filaP.dequeue();
System.out.println('\n' + data.getNumero()+
" removido com sucesso!");
break;
}
35
FilaPrioridade01 (4)
case 3:
// Listar tudo
{ todos = filaP.getEnumeration();
while (todos.hasMoreElements ())
{ System.out.println("");
data = (DataArea)todos.nextElement();
data.imprime();
}
break;
}
case 4:
// Sair
break;
default:
System.out.println('\n' + "Opção inválida!");
}
}
}
}
36
Exemplo de uso de Fila de Prioridade em
Simulação de Eventos Discretos
Uma simulação de eventos discretos servirá para
ilustrar um emprego das filas de prioridade
Etapas da simulação


Geração do modelo matemático
Programa para avaliação do modelo
Sistemas possuem:


Estados
Eventos (mudanças de estado)
37
Ambiente escolhido para a simulação
Atendimento a clientes em um caixa de
banco
O estado do sistema pode ser caracterizado
por:
Estado do atendente de caixa (ocupado,
desocupado)
 Número de clientes na fila

38
Modelo de fila de banco
39
Características do Modelo
Eventos

Tipo



Chegada (arrival)
Partida (departure)
Tempo
Association (utilizada para fazer comparações de
prioridade com um atributo chave em vez de com
todo o objeto)


Tempo (chave)
Tipo (valor)
40
Implementação do exemplo (1)
Simulação de sistema composto de:
Fila
 Atendente

A classe Event representa os eventos em
simulação
Uma fila de prioridade simulará o
atendimento e a prioridade será por tempo
41
Implementação do exemplo (2)
A classe Simulation contém uma fila de
prioridade eventList que armazena os
eventos
O estado do sistema é retratado pelas
variáveis:
serverBusy (atendente ocupado sim/não ?)
 numberInQueue (número de clientes
aguardando atendimento)

42
Implementação do exemplo (3)
O método run implementa a simulação e recebe
um argumento timeLimit (tempo total da
simulação)
A chegada de clientes será modelada por
instâncias da classe ExponentialRV (geradora
de pseudo aleatórios):


serviceTime (tempo de um atendimento)
interArrivalTime (intervalo entre chegaadas)
A interface RandomVariable tem o método
nextDouble que busca um novo valor que
neste exemplo teve distribuição com média 100
para ambas as variáveis
43
Implementação do exemplo (4)
Fila inicialmente vazia
Um cliente chega no tempo zero
Repetição até que a lista de eventos fique vazia
Cada iteração retira um elemento da fila de
prioridade
Quando o tempo do evento a ser atendido
ultrapasse timeLimit termina a simulação
Os eventos podem ser de chegada ou de partida
44
Implementação do exemplo (5)
Atendente desocupado torna-se ocupado na
chegada de um cliente disparando o gerador
de tempo de atendimento e calculando o
tempo de saída correspondente
Atendente ocupado faz aumentar
numberInQueue
Depois de cada chegada dispara o gerador
de tempo para nova chegada
45
Implementação do exemplo (6)
Evento de saída e fila vazia tornam
atendente desocupado
Evento de saída e fila não vazia chamam o
próximo na fila disparando o gerador de
tempo de atendimento e calculando o tempo
de saída correspondente
46
Lembrete: Classe Association
public class Association
extends AbstractObject
{
protected Comparable key;
protected Object value;
public Association (Comparable key, Object value)
{
this.key = key;
this.value = value;
}
public Association (Comparable key)
{ this (key, null); }
public Comparable getKey ()
{ return key; }
public Object getValue ()
{ return value; }
protected int compareTo (Comparable object)
{
Association association = (Association) object;
return key.compare (association.getKey ());
}
}
47
Classe Event
//
pgm11_22.txt
public class Simulation
{
static class Event
extends Association
{
public static final int arrival = 0;
public static final int departure = 1;
Event (int type, double time)
{ super (new Dbl (time), new Int (type)); }
double getTime ()
{ return ((Dbl) getKey ()).doubleValue (); }
int getType ()
{ return ((Int) getValue ()).intValue (); }
}
}
48
Classe Simulation: Inicialização
//
pgm11_23.txt
public class Simulation
{
PriorityQueue eventList = new LeftistHeap ();
public void run (double timeLimit)
{
boolean serverBusy = false;
int numberInQueue = 0;
RandomVariable serviceTime = new ExponentialRV
(100.);
RandomVariable interArrivalTime =
new ExponentialRV (100.);
eventList.enqueue (new Event (Event.arrival, 0));
49
Classe Simulation: Tratamento do evento de
chegada
while (!eventList.isEmpty ())
{
Event event = (Event) eventList.dequeueMin ();
double t = event.getTime ();
if (t > timeLimit)
{ eventList.purge (); break; }
switch (event.getType ())
{
case Event.arrival:
if (!serverBusy)
{
serverBusy = true;
eventList.enqueue (new Event(Event.departure,
t + serviceTime.nextDouble ()));
}
else
++numberInQueue;
eventList.enqueue (new Event (Event.arrival,
t + interArrivalTime.nextDouble ()));
break;
50
Classe Simulation: Tratamento do evento de
partida
case Event.departure:
if (numberInQueue == 0)
serverBusy = false;
else
{
--numberInQueue;
eventList.enqueue (new
Event(Event.departure,
t + serviceTime.nextDouble ()));
}
break;
}
}
}
// ...
}
51
Implementação C++
Implementação
53
Definições das Classes PriorityQueue
e MergeablePriorityQueue
// pgm11_01.cpp
class PriorityQueue : public virtual Container
{
public:
virtual void Enqueue(Object&) = 0;
virtual Object& FindMin() const = 0;
virtual Object& DequeueMin() = 0;
};
class MergeablePriorityQueue : public virtual PriorityQueue
{
public:
virtual void Merge(MergeablePriorityQueue&) = 0;
};
54
Definição da Classe BinaryHeap
// pgm11_02.cpp
class BinaryHeap : public PriorityQueue
{
Array<Object*> array;
public:
BinaryHeap(unsigned int);
~BinaryHeap();
// ...
};
55
Definições da Função Membro Purge
e do Construtor e Destrutor da
Classe BinaryHeap
// pgm11_03.cpp
BinaryHeap::BinaryHeap(unsigned int length) :
array(length, 1)
{}
void BinaryHeap::Purge()
{
if(IsOwner ())
{
for(unsigned int i = 1; i < count + 1; ++i)
delete array[i];
}
count = 0;
}
BinaryHeap::~BinaryHeap()
{ Purge (); }
56
Método enqueue da classe
BinaryHeap
• Como o heap resultante da inclusão deve ser uma
árvore completa só existe um local para a inclusão
• Este local (vazio ou buraco) vai “subir” no heap
até encontrar seu ligar, deixando para baixo os
valores menores do que o objeto o incluir no heap
• A “subida” no heap é feita buscando-se a posição
do array obtida da divisão por dois da posição
corrente
• Quando o buraco parar de “subir” nele inclui-se o
objeto
57
Definição da Função Membro
Enqueue da Classe BinaryHeap
// pgm11_04.cpp
void BinaryHeap::Enqueue(Object& object)
{
if(count == array.Length())
throw domain_error("priority queue is full");
++count;
unsigned int i = count;
while(i > 1 && *array[i / 2] > object)
{
array[i] = array[i / 2];
i /= 2;
}
array[i] = &object;
}
58
Definição da Função membro
FindMin
// pgm11_05.cpp
Object& BinaryHeap::FindMin() const
{
if(count == 0)
throw domain_error("priority queue is empty");
return *array[1];
}
59
Método dequeue da classe BinaryHeap
O elemento a ser removido é o da raiz do heap
O objeto que estava no último nó do heap deve
procurar seu lugar no heap pois esse nó vai
desaparecer
Inicia-se pela raiz, agora vazia, testando-se seus dois
filhos para verificar o menor
Se o objeto que estava no último nó for menor que os
filhos da raiz termina a repetição
Caso contrário a raiz recebe o menor de seus dois
filhos que passa a ser a raiz do heap corrente a
pesquisar
Quando a repetição termina a raiz no heap corrente
recebe o objeto que estava no último nó
60
Definição da Função Membro
DequeueMin da Classe BinaryHeap (1)
// pgm11_06.cpp
Object& BinaryHeap::DequeueMin()
{
if(count == 0)
throw domain_error("priority queue is empty");
Object& result = *array[1];
Object& last = *array[count];
--count;
unsigned int i = 1;
61
Definição da Função Membro
DequeueMin da Classe BinaryHeap (2)
while(2 * i < count + 1)
{
unsigned int child = 2 * i;
if(child + 1 < count + 1 && *array[child + 1] <
*array[child])
child += 1;
if(last <= *array[child])
break;
array[i] = array[child];
i = child;
}
array[i] = &last;
return result;
}
62
Definição da Classe LeftistHeap
// pgm11_07.cpp
class LeftistHeap :
public BinaryTree,
public MergeablePriorityQueue
{
unsigned int nullPathLength;
void SwapContents(LeftistHeap&);
public:
LeftistHeap();
LeftistHeap(Object&);
LeftistHeap& Left() const;
LeftistHeap& Right() const;
void Merge(MergeablePriorityQueue&);
// ...
};
63
Definição da Função Membro Merge
da Classe LeftistHeap
// pgm11_08.cpp
void LeftistHeap::Merge(MergeablePriorityQueue& queue)
{
LeftistHeap& arg = dynamic_cast<LeftistHeap&> (queue);
if(IsEmpty ())
SwapContents(arg);
else
if(!arg.IsEmpty())
{
if(*key > *arg.key)
SwapContents(arg);
Right().Merge(arg);
if(Left().nullPathLength < Right().nullPathLength)
Swap(left, right);
nullPathLength = 1 + Min(Left().nullPathLength,
Right().nullPathLength);
}
64
}
Definição da Função Membro
Enqueue da Classe LeftistHeap
// pgm11_09.cpp
void LeftistHeap::Enqueue(Object& object)
{
LeftistHeap heap(object);
Merge(heap);
}
65
Definição da Função Membro
FindMin da Classe LeftistHeap
// pgm11_10.cpp
Object& LeftistHeap::FindMin() const
{
if(IsEmpty ())
throw domain_error("priority queue is empty");
return *key;
}
66
Definição da Função Membro
DequeueMin da Classe LeftistHeap
// pgm11_11.cpp
Object& LeftistHeap::DequeueMin()
{
if(IsEmpty())
throw domain_error("priority queue is empty");
Object& result = *key;
LeftistHeap& oldLeft = Left();
LeftistHeap& oldRight = Right();
key = 0;
left = 0;
right = 0;
SwapContents(oldLeft);
delete &oldLeft;
Merge(oldRight);
delete &oldRight;
return result;
67
}
Definição da Classe BinomialTree
// pgm11_12.cpp
class BinomialTree : public GeneralTree
{
void SwapContents(BinomialTree&);
public:
BinomialTree(Object&);
void Add(BinomialTree&);
BinomialTree& Subtree(unsigned int) const;
};
68
Definição da Função Membro Add da
Classe BinomialTree
// pgm11_13.cpp
void BinomialTree::Add(BinomialTree& tree)
{
if(degree != tree.degree)
throw invalid_argument("incompatible degrees");
if(*key > *tree.key)
SwapContents(tree);
AttachSubtree(tree);
}
69
Definição da Classe BinomialQueue
// pgm11_14.cpp
class BinomialQueue : public MergeablePriorityQueue
{
LinkedList<BinomialTree*> list;
BinomialTree& FindMinTree() const;
void AddTree(BinomialTree&);
void RemoveTree(BinomialTree&);
static BinomialTree* Sum( BinomialTree*,
BinomialTree*, BinomialTree*);
static BinomialTree* Carry( BinomialTree*,
BinomialTree*, BinomialTree*);
public:
BinomialQueue();
~BinomialQueue();
// ...
};
70
Definições da Função Membro
AddTree e RemoveTree da Classe
BinomialQueue
// pgm11_15.cpp
void BinomialQueue::AddTree(BinomialTree& tree)
{
list.Append(&tree);
count += tree.Count();
}
void BinomialQueue::RemoveTree(BinomialTree& tree)
{
list.Extract(&tree);
count -= tree.Count();
}
71
Definições da Função Membro
FindMinTree e FindMin da Classe
BinomialHeap
// pgm11_16.cpp
BinomialTree& BinomialQueue::FindMinTree() const
{
ListElement<BinomialTree*> const* ptr;
BinomialTree* minTree = 0;
for(ptr = list.Head(); ptr != 0; ptr = ptr->Next())
{
BinomialTree* tree = ptr->Datum();
if(minTree == 0 || tree->Key() < minTree->Key())
minTree = tree;
}
return *minTree;
}
Object& BinomialQueue::FindMin() const
{
if(count == 0)
throw domain_error("priority queue is empty");
return FindMinTree().Key();
72
}
Definição da Função Membro Merge
da Classe BinomialQueue (1)
// pgm11_17.cpp
void BinomialQueue::Merge(MergeablePriorityQueue& queue)
{
BinomialQueue& arg = dynamic_cast<BinomialQueue&> (queue);
LinkedList<BinomialTree*> oldList = list;
list.Purge();
count = 0;
ListElement<BinomialTree*> const* p = oldList.Head();
ListElement<BinomialTree*> const* q = arg.list.Head();
BinomialTree* carry = 0;
73
Definição da Função Membro Merge
da Classe BinomialQueue (2)
for(unsigned int i = 0; p || q || carry; ++i) {
BinomialTree* a = 0;
if(p && p->Datum()->Degree() == i) {
a = p->Datum();
p = p->Next();
}
BinomialTree* b = 0;
if(q && q->Datum()->Degree() == i) {
b = q->Datum();
q = q->Next();
}
BinomialTree* sum = Sum(a, b, carry);
if(sum)
AddTree(*sum);
carry = Carry(a, b, carry);
}
arg.list.Purge();
arg.count = 0;
}
74
Definições da Função Membro Sum e
Carry da Classe BinomialQueue (1)
// pgm11_18.cpp
BinomialTree* BinomialQueue::Sum( BinomialTree* a,
BinomialTree* b,
BinomialTree* c)
{
if(a && !b && !c)
return a;
else if(!a && b && !c)
return b;
else if(!a && !b && c)
return c;
else if(a && b && c)
return c;
else
return 0;
}
75
Definições da Função Membro Sum e
Carry da Classe BinomialQueue (2)
BinomialTree* BinomialQueue::Carry( BinomialTree* a,
BinomialTree* b,
BinomialTree* c)
{
if(a && b && !c)
{
a->Add(*b);
return a;
}
else if(a && !b && c)
{
a->Add(*c);
return a;
}
76
Definições da Função Membro Sum e
Carry da Classe BinomialQueue (3)
else if(!a && b && c)
{
b->Add(*c);
return b;
}
else if(a && b && c)
{
a->Add(*b);
return a;
}
else
return 0;
}
77
Definição da Função Membro
Enqueue da Classe BinomialQueue
// pgm11_19.cpp
void BinomialQueue::Enqueue(Object& object)
{
BinomialQueue queue;
queue.AddTree(*new BinomialTree(object));
Merge(queue);
}
78
Definição da Função Membro
DequeueMin da Classe
BinomialQueue (1)
// pgm11_20.cpp
Object& BinomialQueue::DequeueMin()
{
if(count == 0)
throw domain_error("priority queue is empty");
BinomialTree& minTree = FindMinTree();
RemoveTree(minTree);
BinomialQueue queue;
while(minTree.Degree() > 0)
{
BinomialTree& child = minTree.Subtree(0);
minTree.DetachSubtree(child);
queue.AddTree(child);
}
Merge(queue);
79
Definição da Função Membro
DequeueMin da Classe
BinomialQueue (2)
Object& result = minTree.Key();
minTree.RescindOwnership();
delete &minTree;
return result;
}
80
Download

Heaps e Filas de Prioridade