priqueue.cc.html
//***********************************************************************
#include <iostream.h>
#include <limits.h>
#include "vertex.h"
#include "priqueue.h"
//***********************************************************************
PriQueue::PriQueue(int number) // Constructor
{
if (number > 0)
{
max_size = number;
head = new Vertex[max_size+1];
mapper = new int[max_size+1];
if (!head || !mapper)
Error("Out of space in PriQueue !!");
head[0].distance = INT_MAX;
for (int i=0;i<=max_size;i++)
mapper[i] = 0;
}
size = 0;
}
//***********************************************************************
PriQueue::~PriQueue() // Destructor
{
delete [] head;
delete [] mapper;
}
//***********************************************************************
void PriQueue::Insert(Vertex& add) // Inserts a new vertex in correct place
{
if (Is_Full())
Error( "Insert(): Priority queue is full !!" );
int i = ++size;
while (i > 1 && head[i/2] > add) // Search for correct place
{
head[i] = head[i/2];
mapper[head[i/2].name] = i;
i /= 2;
}
head[i] = add;
mapper[add.name] = i; // Map vertex name to the actual local index used
}
//***********************************************************************
Vertex PriQueue::Delete_Min() // Returns a vertex with minimum weight
{
if (Is_Empty())
Error("Delete_Min(): Priority queue is empty !!");
Vertex root = head[1]; // Saves root
mapper[head[1].name] = 0; // deleted vertex, hence maps to 0
head[1] = head[size]; // Sets last vertex in array as root
mapper[head[size].name] = 1;
size--; // and decreases size
Percolate_Down(1); // Re-heapifies
return root; // Returns saved root
}
//***********************************************************************
// Decreases the weight at index in array to amt, and reassigns
// parent to newparent. Returns 1 if succesfull, 0 if not.
int PriQueue::Decrease_Key(int vertname,int amt,int newParent)
{
if (Is_Empty())
Error("Decrease_Key(): Priority queue is empty !!");
int index = mapper[vertname]; // maps vertex name to local index
head[index].setDistance(amt);
head[index].setParent(newParent);
Percolate_Up(index); // Re-heapifies
return 1;
}
//***********************************************************************
void PriQueue::Build_Heap() // Heapifies the queue
{
for (int i=size/2;i>0;i--)
Percolate_Down(i);
}
//***********************************************************************
void PriQueue::Percolate_Up(int index) // Up-heapifies starting at index
{
int i=index,parent;
Vertex Child = head[i];
for (;i>=2;i=parent)
{
parent = i/2;
if (head[parent] > Child) // If parent is bigger than child
{
head[i] = head[parent]; // Swap it
mapper[head[parent].name] = i;
}
else
break;
}
head[i] = Child;
mapper[Child.name] = i;
}
//***********************************************************************
void PriQueue::Percolate_Down(int index) // Down-heapifies starting at index
{
int i=index,child;
Vertex Parent = head[i];
for (;i*2<=size;i=child)
{
child = i*2;
if (child < size && head[child+1] < head[child])
child++;
if (Parent > head[child]) // if Parent is bigger than smaller child
{
head[i] = head[child]; // Swap it
mapper[head[child].name] = i;
}
else
break;
}
head[i] = Parent;
mapper[Parent.name] = i;
}
//***********************************************************************
void PriQueue::Error(char *s) // Error handling routine
{
cerr << "Error: " << s << endl;
cerr << "Exiting......." << endl;
exit(-1);
}
//***********************************************************************