For this assignment I have to implement a class called HeapPriorityQueue. I have to create a Driver function that will have a to-do list of task with highest priority level. Which every one has the highest priority then the computer will tell the user which task they should do first. Right now I'm having trouble with calling on the ArrayMaxHeap functions to tell the user what task is important. I have included the ArrayMaxHeap.h, Driver.cpp, and the Common.h files.
// ArrayMaxHeap.h
#ifndef ARRAY_MAX_HEAP_
#define ARRAY_MAX_HEAP_
#include "HeapInterface.h"
#include "PrecondViolatedExcept.h"
template<class ItemType>
class ArrayMaxHeap : public HeapInterface<ItemType>
{
private:
staticconstint ROOT_INDEX = 0; // Helps with readibility
staticconstint DEFAULT_CAPACITY = 21;
ItemType* items; // Array of heap items
int itemCount; // Current count of heap items
int maxItems; // Max capcity of the heap
// Returns the array index of the left child
int getLeftChildIndex(constint nodeIndex) const;
// Returns the array index of the right child
int getRightChildIndex(int nodeIndex) const;
// Returns the array index of the parent node
int getParentIndex(int nodeIndex) const;
// Tests whether this node is a leaf
bool isLeaf(int nodeIndex) const;
// Converts the semiheap to a heap
void heapRebuild(int nodeIndex);
// Creates a heap from from unordered array
void heapCreate();
public:
ArrayMaxHeap();
ArrayMaxHeap(const ItemType someArray[], constint arraySize);
virtual ~ArrayMaxHeap();
bool isEmpty() const;
int getNumberOfNodes() const;
int getHeight() const;
ItemType peekTop() constthrow(PrecondViolatedExcep);
bool add(const ItemType& newData);
bool remove();
void clear();
};
template<class ItemType>
int ArrayMaxHeap<ItemType>::getLeftChildIndex(constint nodeIndex) const
{
return (2 * nodeIndex) + 1;
}
template<class ItemType>
int ArrayMaxHeap<ItemType>::getRightChildIndex(constint nodeIndex) const
{
return (2 * nodeIndex) + 2;
}
template<class ItemType>
int ArrayMaxHeap<ItemType>::getParentIndex(constint nodeIndex) const
{
return (nodeIndex - 1) / 2;
}
template<class ItemType>
bool ArrayMaxHeap<ItemType>::isLeaf(constint nodeIndex) const
{
return (getLeftChildIndex(nodeIndex) >= itemCount);
}
template<class ItemType>
void ArrayMaxHeap<ItemType>::heapRebuild(constint subTreeNodeIndex)
{
if (!isLeaf(subTreeNodeIndex))
{
int leftChildIndex = getLeftChildIndex(subTreeNodeIndex);
int largerChildIndex = leftChildIndex;
int rightChildIndex = getRightChildIndex(subTreeNodeIndex);
if (rightChildIndex < itemCount)
{
if (items[rightChildIndex].priorityValue > items[largerChildIndex].priorityValue)
largerChildIndex = rightChildIndex;
}
if (items[subTreeNodeIndex].priorityValue < items[largerChildIndex].priorityValue)
{
swap(items[largerChildIndex], items[subTreeNodeIndex]);
heapRebuild(largerChildIndex);
}
}
}
template<class ItemType>
void ArrayMaxHeap<ItemType>::heapCreate()
{
for (int index = itemCount / 2; index >= 0; index--)
{
heapRebuild(index);
}
}
template<class ItemType>
ArrayMaxHeap<ItemType>::ArrayMaxHeap() :itemCount(0), maxItems(DEFAULT_CAPACITY)
{
items = new ItemType[DEFAULT_CAPACITY];
}
template<class ItemType>
ArrayMaxHeap<ItemType>::ArrayMaxHeap(const ItemType someArray[], constint arraySize) :
itemCount(arraySize), maxItems(2 * arraySize)
{
// Allocate the array
items = new ItemType[2 * arraySize];
// Copy the given values into the array
for (int i = 0; i < itemCount; i++)
items[i] = someArray[i];
// Reorganize the array into the heap
heapCreate();
}
template<class ItemType>
ArrayMaxHeap<ItemType>::~ArrayMaxHeap()
{
delete[] items;
}
template<class ItemType>
bool ArrayMaxHeap<ItemType>::isEmpty() const
{
return itemCount == 0;
}
template<class ItemType>
int ArrayMaxHeap<ItemType>::getHeight() const
{
double y = log(itemCount + 1) / log(2);
return ceil(y);
}
template<class ItemType>
int ArrayMaxHeap<ItemType>::getNumberOfNodes() const
{
return itemCount;
}
template<class ItemType>
void ArrayMaxHeap<ItemType>::clear()
{
itemCount = 0;
}
template<class ItemType>
ItemType ArrayMaxHeap<ItemType>::peekTop() constthrow(PrecondViolatedExcep)
{
if (isEmpty())
throw PrecondViolatedExcep("Attempted peek into an empty heap.");
return items[0];
}
template<class ItemType>
bool ArrayMaxHeap<ItemType>::add(const ItemType& newData)
{
// Returns false if the itemCount is equal to the maximum amount of item.
if (itemCount == maxItems)
returnfalse;
// Insert newData into the bottom of the tree
items[itemCount] = newData;
// Trickle new item up to the appropriate spot in the tree
int newDataIndex = itemCount;
bool inPlace = false;
// Repeat the process as long as newDataIndex is greater than zero
// and inPlace is false
while (newDataIndex > 0 && !inPlace)
{
// Get the parent node's index
int parentIndex = (newDataIndex - 1) / 2;
// Item is in place if the priority value of the newData is
// lesser or equal than the parent node's value
if (items[newDataIndex] <= items[parentIndex])
inPlace = true;
else
{
// Otherwise, swap newDataIndex's value with the parentIndex
swap(items[newDataIndex], items[parentIndex]);
// set newDataIndex to the parentIndex to repeat the process
newDataIndex = parentIndex;
}
}
// Increase the itemCount
itemCount++;
// The process is done, returns true.
returntrue;
}
template<class ItemType>
bool ArrayMaxHeap<ItemType>::remove()
{
bool isSuccessful = false;
if (!isEmpty())
{
items[ROOT_INDEX] = items[itemCount - 1];
itemCount--;
heapRebuild(ROOT_INDEX);
bool isSuccessful = true;
}
return isSuccessful;
}
#endif
// Driver.cpp
#include "ArrayMaxHeap.h"
#include "Common.h"
#include <iostream>
#include <string>
usingnamespace std;
int main()
{
ArrayMaxHeap pqPtr;
item* p = new item[4];
p[0].task = "Send a birthday card to Aunt Chris.";
p[0].priorityValue = 5;
p[1].task = "Start the research paper for world history.";
p[1].priorityValue = 4;
p[2].task = "Finish reading Chapter 13 of Walls and Mirrors.";
p[2].priorityValue = 3;
p[3].task = "Make plans for Saturday Night.";
p[3].priorityValue = 4;
for (int i = 0; i < 4; i++)
{
bool success = pqPtr->add(p[i]);
if (!success)
cout << "Failed to add " << p[i].task << " to the priority queue." << endl;
}
for (int i = 0; i < 4; i++)
{
try
{
cout << "The item witht he largest priority: " >> pqPtr->peekTop().task << endl;
}
catch (PrecondViolatedExcep e)
{
cout << e.what() << endl;
}
cout << "Call remove function" << endl;
pqPtr->remove();
}
system("pause");
return 0;
}
// Common.h
#ifndef COMMON_H
#define COMMON_H
#include <string>
struct item
{
int priorityValue;
std::string task;
};
#endif
I actually called on the wrong class for this code. I should have called on the HeapPriorityQueue class in the Driver.cpp instead of ArrayMaxQueue. Here is my code for the HeapPriorityQueue. How would I call on this class then. The code includes Heap priority queue cpp and h file.
#include "HeapPriorityQueue.h"
#include "Common.h"
#include <iostream>
#include <string>
usingnamespace std;
int main()
{
HeapPriorityQueue<item> pqPtr;
item* p = new item[4];
p[0].task = "Send a birthday card to Aunt Chris.";
p[0].priorityValue = 5;
p[1].task = "Start the research paper for world history.";
p[1].priorityValue = 4;
p[2].task = "Finish reading Chapter 13 of Walls and Mirrors.";
p[2].priorityValue = 3;
p[3].task = "Make plans for Saturday Night.";
p[3].priorityValue = 4;
for (int i = 0; i < 4; i++)
{
bool success = pqPtr.enqueue(p[i]);
if (!success)
cout << "Failed to add " << p[i].task << " to the priority queue." << endl;
}
for (int i = 0; i < 4; i++)
{
try
{
cout << "The item witht he largest priority: " << pqPtr.peekFront().task << endl;
}
catch (PrecondViolatedExcep e)
{
cout << e.what() << endl;
}
cout << "Call remove function" << endl;
pqPtr.dequeue();
}
system("pause");
return 0;
}
UPDATE: I have changed all the methods called so they match the ones in HeapPriorityQueue. However I get an error on L8 saying Severity
Error (active) E0322 object of abstract class type "HeapPriorityQueue<item>" is not allowed
HeapPriorityQueue is derived from PriorityQueueInterface. The error means that the base class has at least one function marked as pure virtual (=0) which hasn't been defined as part of the derived class.
Have a look through the class definition for PriorityQuqueInterface() and make sure that all functions marked as =0 are defined as part of HeapPriorityQueue.
You have to provide overrides for all the pure virtual functions defined in the base class.
If your driver code doesn't use them - then they can be 'dummy' functions which take the required arg(s) and return the required type but doesn't do anything (perhaps a message or something).
Have done what you said @seeplus. Thank you for your help. Now that error has gone away. I'm now getting an error where on L1 of the driver.cpp file it says
LNK2019 unresolved external symbol "public: __thiscall HeapPriorityQueue<struct item>::HeapPriorityQueue<struct item>(void)" (??0?$HeapPriorityQueue@Uitem@@@@QAE@XZ) referenced in function _main
@lacy9265. I've lost off what is the current state of the code. If you post all of the code that is needed to compile, I'll have a look at it. It's probably something simple that's been missed.
PS You do know that HeapPriorityQueue.cpp can't be a separate compilable unit as it is templated code? Normally templated code is in one file. If you have
HeapPriorityQueue.h and HeapPriorityQueue.cpp then HeapPriorityQueue.h needs to have #include HeapPriorityQueue.cpp at the end (just before the final #endif) - and HeapPriorityQueue.cpp doesn't have #include HeapPriorityQueue.h.
But it's much easier to combine HeapProrityQueue.h and HeapPriorityQueue.cpp into one file (say HeapPriorityQueue.hpp) which is then used in driver.cpp
//HeapPriorityQueue.h
#ifndef HEAP_PRIORITY_QUEUE_
#define HEAP_PRIORITY_QUEUE_
#include <iostream>
#include "ArrayMaxHeap.h"
#include "PriorityQueueInterface.h"
#include "PrecondViolatedExcept.h"
template<class ItemType>
class HeapPriorityQueue : public PriorityQueueInterface<ItemType>,
private ArrayMaxHeap<ItemType>
{
public:
HeapPriorityQueue();
bool isEmpty() const;
bool enqueue(const ItemType& newEntry);
bool dequeue();
ItemType peekFront() constthrow(PrecondViolatedExcep);
bool add(const ItemType& newEntry) override { returnfalse; }
bool remove() override { returnfalse; }
ItemType peek() const override { return {}; }
};
#include "HeapPriorityQueue.cpp"
#endif
//PriorityQueueInterface.h
#ifndef PRIORITY_QUEUE_INTERFACE_
#define PRIORITY_QUEUE_INTERFACE_
template<class ItemType>
class PriorityQueueInterface
{
public:
virtualbool isEmpty() const = 0;
virtualbool add(const ItemType& newEntry) = 0;
virtualbool remove() = 0;
virtual ItemType peek() const = 0;
};
#endif
//PrecondViolatedException.h
#ifndef PRECOND_VIOLATED_EXCEP_
#define PRECOND_VIOLATED_EXCEP_
#include <stdexcept>
#include <string>
class PrecondViolatedExcep : public std::logic_error
{
public:
PrecondViolatedExcep(const std::string& message = "")
: std::logic_error("Precondition Violated Exception: " + message)
{
}
}; // end PrecondViolatedExcep
#endif
//HeapInterface.h
#ifndef HEAP_iNTERFACE_
#define HEAP_INTERFACE_
#include <iostream>
template<class ItemType>
class HeapInterface
{
public:
// See if the heap is empty
virtualbool isEmpty() const = 0;
// Gets the number of nodes in this heap
virtualint getNumberOfNodes() const = 0;
// Gets the height of the nodes
virtualint getHeight() const = 0;
// Gets the data that is in the top of this heap
// For the maxHeap the data is the largest value in the heap
// For the minHeap the data is the smmallest value in the heap
virtual ItemType peekTop() const = 0;
// Adds new data to the heap
virtualbool add(const ItemType& newData) = 0;
// Removes the data that is at the top of the heap
virtualbool remove() = 0;
// Removes all data from the heap
virtualvoid clear() = 0;
// Destroys this heap and frees its assigned memory
virtual ~HeapInterface() { }
};
#endif