20-CS-122-001 Computer Science II Spring 2012
Priority Queue

Virtual functions, classes, inheritance, lists, queues, stacks, applications

Source

#include <fstream>
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
using namespace std;

// We will require only TreeObjects to be put into
// Binary Trees.  Classes subclassing TreeObject need to implement
// display and value methods.  The value method, in particular, is
// important because it is used to order the objects stored in a
// priority queue.
class TreeObject {
 public:
   virtual void display () { }
   virtual int value () { }
};

// This example stores objects of a BigInt class
class BigInt : public TreeObject {
   int number;
   
public:
   BigInt(int x) { number = x; }
   int value() { return number; }
   void display() { cout << number << " "; }
};

// Cell will carry TreeObjects.  It is different from
// the Cell class used in building Queues because more links are
// necessary.
class Cell {
friend class BinTree;
friend class Heap;
   
   TreeObject *object;
   Cell *leftnext;
   Cell *rghtnext;
   Cell *lefttree;
   Cell *rghttree;
   Cell *parent;
   
public:
   Cell(TreeObject *obj, Cell *ln, Cell *prnt) {
      object   = obj;
      lefttree = NULL;
      rghttree = NULL;
      leftnext = ln;
      rghtnext = NULL;
      parent   = prnt;
   }
};

/***--------------------------------------------------------------------***/
/***  The class of Binary Trees -                                       ***/
/***    includes the following methods                                  ***/
/***       1. getRoot     - returns the object stored in the root cell  ***/
/***       2. putRoot     - replace an object at the root with another  ***/
/***       3. popNode     - delete the last Cell and return its object  ***/
/***       4. addNode     - add Cell to "end" of "list" and add object  ***/
/***       5. display     - outputs values of all objects in the tree   ***/
/***       6. empty       - returns 1 iff the tree has no nodes         ***/
/***       7. displayRoot - outputs value of the root object            ***/
/***    saves information in the following variables                    ***/
/***       1. head, tail  - pointers locating root and end of tree      ***/
/***    tail pointer -                                                  ***/
/***       1. points to a leaf Cell if the tree has an odd number of    ***/
/***          Cells.  It either points to the leftmost childless Cell   ***/
/***          in the row that is one up from the bottom, or, in the     ***/
/***          case of a full tree, it points to the leftmost Cell of    ***/
/***          the bottom level (latter case covers the one-Cell case).  ***/
/***       2. points to the rightmost Cell, one level up from the       ***/
/***          bottom, that has a child.                                 ***/
/***--------------------------------------------------------------------***/
class BinTree {
 protected:
   Cell *head;
   Cell *tail;
   
 public:
   BinTree() { head = tail = NULL;  } 
   TreeObject *getRoot();
   void  putRoot(TreeObject *t);
   TreeObject *popNode();
   void  addNode(TreeObject *t);
   void  display();
   int   empty()   {  return head == NULL;  }
   void  displayRoot() { cout << head->object->value() << " "; }   
};

TreeObject *BinTree::getRoot() {
   TreeObject *t = head->object;
   head->object = NULL;
   return t;
}

void BinTree::putRoot(TreeObject *t) {
   if (t == NULL) return;
   if (head == NULL) return;
   head->object = t;
}

/***--------------------------------------------------------------------***/
/***       Remove the last Cell from a tree and return its object       ***/
/***--------------------------------------------------------------------***/
TreeObject *BinTree::popNode() {
   if (head == NULL) return NULL;
   if (tail->leftnext == NULL && tail->lefttree == NULL) {
      TreeObject *t = head->object;
      delete head;
      head = tail = NULL;
      return t;
   } else if (tail->lefttree != NULL) {
      TreeObject *t = tail->lefttree->object;
      tail->lefttree->leftnext->rghtnext = NULL;
      delete tail->lefttree;
      tail->lefttree = NULL;
      return t;
   } else {
      tail = tail->leftnext;
      TreeObject *t = tail->rghttree->object;
      tail->lefttree->rghtnext = NULL;
      delete tail->rghttree;
      tail->rghttree = NULL;
      return t;
   }
}

/***--------------------------------------------------------------------***/
/***  Add a Cell to the end of a heap and insert an object in that Cell ***/
/***--------------------------------------------------------------------***/
void BinTree::addNode(TreeObject *t) {
   if (t == NULL) return;
   if (head == NULL) head = tail = new Cell(t, NULL, NULL);
   else if (tail->lefttree == NULL) {
      if (tail->leftnext == NULL) {
         tail->lefttree = new Cell(t, tail, tail);
         tail->rghtnext = tail->lefttree;
      } else {
         Cell *last = tail->leftnext->rghttree;
         tail->lefttree = new Cell(t, last, tail);
         last->rghtnext = tail->lefttree;
      }
   } else {
      Cell *last = tail->lefttree;
      tail->rghttree = new Cell(t, last, tail);
      last->rghtnext = tail->rghttree;
      tail = tail->rghtnext;
   }
}

void BinTree::display() {
   Cell *t;
   if (head == NULL) { cout << "(empty)\n";  return; }
   for (t = head ; t != NULL ; t = t->rghtnext)
      t->object->display();
   cout << "\n";
}

/***--------------------------------------------------------------------***/
/***  The Heap class -                                                  ***/
/***    includes the following methods                                  ***/
/***       1. HeapifyDown - percolate an object down from the root      ***/
/***       2. HeapifyUp   - percolate an object up from a leaf          ***/
/***       3. addNode     - adds a Cell and object to the heap          ***/
/***       4. display     - displays contents of the heap               ***/
/***       5. HeapSort    - repeat: setRoot(popNode()); heapifyDown();  ***/
/***--------------------------------------------------------------------***/
class Heap : public BinTree {
public:
   Heap() : BinTree() { } 
   void  heapifyDown();
   void  heapifyUp();
   void  addNode(TreeObject *t);    // Override
   void  display();                 // Override
   void  heapSort();
};

/***--------------------------------------------------------------------***/
/***  Heapify Down -                                                    ***/
/***     let t be a Cell with an object                                 ***/
/***     let h be the child Cell of t with object of least value        ***/
/***     if no such child Cell exists, stop                             ***/
/***     otherwise, if t's object value > h's object value              ***/
/***     then swap t's object with h's object, set t = h, and repeat    ***/
/***--------------------------------------------------------------------***/
void Heap::heapifyDown() {
   Cell *t = head, *h;
   TreeObject *obj;

   if (head == NULL) return;

   while (1) {
      if (t->lefttree == NULL && t->rghttree == NULL)
         break;
      else
      if (t->rghttree == NULL)
         h = t->lefttree;
      else
      if (t->lefttree->object->value() < t->rghttree->object->value())
         h = t->lefttree;
      else
         h = t->rghttree;

      if (h->object->value() < t->object->value()) {
         obj = t->object;
         t->object = h->object;
         h->object = obj;
         t = h;
      }
      else
         break;
   }
}

/***--------------------------------------------------------------------***/
/***  Heapify Up -                                                      ***/
/***     let h be the last Cell of the tree                             ***/
/***     if no such Cell exists, stop                                   ***/
/***     otherwise, if h's object value < h's parent's object value     ***/
/***     then swap h's object with h's parent's object,                 ***/
/***     set h = h's parent,                                            ***/
/***     and repeat                                                     ***/
/***--------------------------------------------------------------------***/
void Heap::heapifyUp() {
   Cell *h;
   TreeObject *obj;

   if (head == NULL || (head == tail && tail->lefttree == NULL)) return;
   if (tail->rghttree == NULL && tail->lefttree == NULL)
      h = tail->leftnext->rghttree;
   else
      h = tail->lefttree;

   while (1) {
      if (h == head) break;
      if (h->object->value() < h->parent->object->value()) {
         obj = h->object;
         h->object = h->parent->object;
         h->parent->object = obj;
         h = h->parent;
      }
      else
         break;
   }
}

/***--------------------------------------------------------------------***/
/***                   Basic function for building a heap               ***/
/***--------------------------------------------------------------------***/
void Heap::addNode(TreeObject *t) {
   BinTree::addNode(t);
   heapifyUp();
}

void Heap::display() {
   int i=0, j=1;
   
   Cell *t;
   if (head == NULL) { cout << "(empty)\n";  return; }
   for (t = head ; t != NULL ; t = t->rghtnext) {
      if ((1 << i) == j++) {
         cout << "\n";
         int place = 40 - (int)(j*(1.5));
         for (int p=0 ; p < place ; p++) cout << " ";
         i++;
      }
      t->object->display();
   }
   cout << "\n";
}

/***--------------------------------------------------------------------***/
/***   Perform the heapsort on a binary tree T that is assumed a heap   ***/
/***--------------------------------------------------------------------***/
void Heap::heapSort() {
   while (!empty()) {
      displayRoot();
      putRoot(popNode());
      heapifyDown();
   }
}

/***--------------------------------------------------------------------***/
/***                      Test of the above functions                   ***/
/***--------------------------------------------------------------------***/
int main() {
   Heap *T = new Heap();

   for (int i=29 ; i > 0 ; i--) T->addNode(new BigInt(i));
   ((BinTree *)T)->display();
   printf("******\n");
   T->display();
   printf("******\n");
   T->heapSort();
   cout << "\n";
}