// test heap sort <pre name="code" class="cpp">//heapSort.cpp
#include <iostream>#include <algorithm>#include "heapSort.h"using namespace std;int main(void){ int a[11], i, n = 10; // initialize descending data for (i = 1; i <= 10; i++) a[i] = n - i + 1; heapSort(a, 10); // output sorted data copy(a, a+n, ostream_iterator<int>(cout, " ")); cout << endl; return 0;}
// heap sort a[1:n]
#ifndef heapSort_
#define heapSort_
#include "maxHeap.h"
using namespace std;
template <class T>
void heapSort(T a[], int n)
{// Sort a[1:n] using the heap sort method.
// create a max heap of the elements
maxHeap<T> heap(1);
heap.initialize(a, n);
// extract one by one from the max heap
for (int i = n - 1; i >= 1; i--)
{
T x = heap.top();
heap.pop();
a[i+1] = x;
}
// save array a from heap destructor
heap.deactivateArray();
}
#endif
maxHeap.h
// heap implementation of a max priority queue
// derives from the ADT maxPriorityQueue
#ifndef maxHeap_
#define maxHeap_
#include "maxPriorityQueue.h"
#include "myExceptions.h"
#include "changeLength1D.h"
#include <sstream>
#include <algorithm>
using namespace std;
template<class T>
class maxHeap : public maxPriorityQueue<T>
{
public:
maxHeap(int initialCapacity = 10);
~maxHeap() {delete [] heap;}
bool empty() const {return heapSize == 0;}
int size() const
{return heapSize;}
const T& top()
{// return max element
if (heapSize == 0)
throw queueEmpty();
return heap[1];
}
void pop();
void push(const T&);
void initialize(T *, int);
void deactivateArray()
{heap = NULL; arrayLength = heapSize = 0;}
void output(ostream& out) const;
private:
int heapSize; // number of elements in queue
int arrayLength; // queue capacity + 1
T *heap; // element array
};
template<class T>
maxHeap<T>::maxHeap(int initialCapacity)
{// Constructor.
if (initialCapacity < 1)
{ostringstream s;
s << "Initial capacity = " << initialCapacity << " Must be > 0";
throw illegalParameterValue(s.str());
}
arrayLength = initialCapacity + 1;
heap = new T[arrayLength];
heapSize = 0;
}
template<class T>
void maxHeap<T>::push(const T& theElement)
{// Add theElement to heap.
// increase array length if necessary
if (heapSize == arrayLength - 1)
{// double array length
changeLength1D(heap, arrayLength, 2 * arrayLength);
arrayLength *= 2;
}
// find place for theElement
// currentNode starts at new leaf and moves up tree
int currentNode = ++heapSize;
while (currentNode != 1 && heap[currentNode / 2] < theElement)
{
// cannot put theElement in heap[currentNode]
heap[currentNode] = heap[currentNode / 2]; // move element down
currentNode /= 2; // move to parent
}
heap[currentNode] = theElement;
}
template<class T>
void maxHeap<T>::pop()
{// Remove max element.
// if heap is empty return null
if (heapSize == 0) // heap empty
throw queueEmpty();
// Delete max element
heap[1].~T();
// Remove last element and reheapify
T lastElement = heap[heapSize--];
// find place for lastElement starting at root
int currentNode = 1,
child = 2; // child of currentNode
while (child <= heapSize)
{
// heap[child] should be larger child of currentNode
if (child < heapSize && heap[child] < heap[child + 1])
child++;
// can we put lastElement in heap[currentNode]?
if (lastElement >= heap[child])
break; // yes
// no
heap[currentNode] = heap[child]; // move child up
currentNode = child; // move down a level
child *= 2;
}
heap[currentNode] = lastElement;
}
template<class T>
void maxHeap<T>::initialize(T *theHeap, int theSize)
{// Initialize max heap to element array theHeap[1:theSize].
delete [] heap;
heap = theHeap;
heapSize = theSize;
// heapify
for (int root = heapSize / 2; root >= 1; root--)
{
T rootElement = heap[root];
// find place to put rootElement
int child = 2 * root; // parent of child is target
// location for rootElement
while (child <= heapSize)
{
// heap[child] should be larger sibling
if (child < heapSize && heap[child] < heap[child + 1])
child++;
// can we put rootElement in heap[child/2]?
if (rootElement >= heap[child])
break; // yes
// no
heap[child / 2] = heap[child]; // move child up
child *= 2; // move down a level
}
heap[child / 2] = rootElement;
}
}
template<class T>
void maxHeap<T>::output(ostream& out) const
{// Put the list into the stream out.
copy(heap + 1, heap + heapSize + 1, ostream_iterator<T>(cout, " "));
}
// overload <<
template <class T>
ostream& operator<<(ostream& out, const maxHeap<T>& x)
{x.output(out); return out;}
#endif
maxPriorityQueue.h
// abstract class max priority queue
// all methods are pure virtual functions
#ifndef maxPriorityQueue_
#define maxPriorityQueue_
using namespace std;
template<class T>
class maxPriorityQueue
{
public:
virtual ~maxPriorityQueue() {}
virtual bool empty() const = 0;
// return true iff queue is empty
virtual int size() const = 0;
// return number of elements in queue
virtual const T& top() = 0;
// return reference to the max element
virtual void pop() = 0;
// remove the top element
virtual void push(const T& theElement) = 0;
// add theElement to the queue
};
#endif
myExceptions.h
// exception classes for various error types
#ifndef myExceptions_
#define myExceptions_
#include <string>
using namespace std;
// illegal parameter value
class illegalParameterValue
{
public:
illegalParameterValue(string theMessage = "Illegal parameter value")
{message = theMessage;}
void outputMessage() {cout << message << endl;}
private:
string message;
};
// illegal input data
class illegalInputData
{
public:
illegalInputData(string theMessage = "Illegal data input")
{message = theMessage;}
void outputMessage() {cout << message << endl;}
private:
string message;
};
// illegal index
class illegalIndex
{
public:
illegalIndex(string theMessage = "Illegal index")
{message = theMessage;}
void outputMessage() {cout << message << endl;}
private:
string message;
};
// matrix index out of bounds
class matrixIndexOutOfBounds
{
public:
matrixIndexOutOfBounds
(string theMessage = "Matrix index out of bounds")
{message = theMessage;}
void outputMessage() {cout << message << endl;}
private:
string message;
};
// matrix size mismatch
class matrixSizeMismatch
{
public:
matrixSizeMismatch(string theMessage =
"The size of the two matrics doesn't match")
{message = theMessage;}
void outputMessage() {cout << message << endl;}
private:
string message;
};
// stack is empty
class stackEmpty
{
public:
stackEmpty(string theMessage =
"Invalid operation on empty stack")
{message = theMessage;}
void outputMessage() {cout << message << endl;}
private:
string message;
};
// queue is empty
class queueEmpty
{
public:
queueEmpty(string theMessage =
"Invalid operation on empty queue")
{message = theMessage;}
void outputMessage() {cout << message << endl;}
private:
string message;
};
// hash table is full
class hashTableFull
{
public:
hashTableFull(string theMessage =
"The hash table is full")
{message = theMessage;}
void outputMessage() {cout << message << endl;}
private:
string message;
};
// edge weight undefined
class undefinedEdgeWeight
{
public:
undefinedEdgeWeight(string theMessage =
"No edge weights defined")
{message = theMessage;}
void outputMessage() {cout << message << endl;}
private:
string message;
};
// method undefined
class undefinedMethod
{
public:
undefinedMethod(string theMessage =
"This method is undefined")
{message = theMessage;}
void outputMessage() {cout << message << endl;}
private:
string message;
};
#endif
changeLength1D.h
// change the length of an array
#ifndef changeLength1D_
#define changeLength1D_
#include "myExceptions.h"
using namespace std;
template<class T>
void changeLength1D(T*& a, int oldLength, int newLength)
{
if (newLength < 0)
throw illegalParameterValue("new length must be >= 0");
T* temp = new T[newLength]; // new array
int number = min(oldLength, newLength); // number to copy
copy(a, a + number, temp);
delete [] a; // deallocate old memory
a = temp;
}
#endif