I am trying to implement an array-based, fixed-size minimum binary heap ADT. As I was testing my program, all the functions I wrote seem to work fine except for finding the minimum element which is only supposed to return the integer value stored at the root node. The root node in this implementation is placed at index 1.
The error I keep getting is the read-access violation.
The following is the Binary Heap class definition and the implementation of the functions:
class BinaryHeap {
public:
BinaryHeap(int); // constructor that takes the capacity of the structure
~BinaryHeap(); // destructor
void insert(int); // inserts a new element to the heap
void deleteMin(); // removes the minimum element from the heap
int getMin(); // returns the minimum element int the heap, returns -1 if the heap is empty
private:
int *heap; // array to store the elements of the heap
int size; // keeps the number of elements in the heap
int capacity; // keeps the total capacity of the heap
void percolateDown(int);
void percolateUp(int);
void swap(int, int);
};
BinaryHeap::BinaryHeap(int capacity) {
this->capacity = capacity;
heap = new int[capacity+1];
size = 0;
}
BinaryHeap::~BinaryHeap() {
delete [] heap;
}
void BinaryHeap::insert(int element) {
if (size < capacity) {
size++;
heap[size] = element;
percolateUp(size);
}
else return;
}
void BinaryHeap::deleteMin() {
if (size < 1)
return;
else {
heap[1] = heap[size];
size--;
percolateDown(1);
}
}
int BinaryHeap::getMin() {
if (size < 1)
return -1;
else return heap[1];
}
void BinaryHeap::percolateDown(int hole) {
int leftChildIndex, rightChildIndex, minIndex;
leftChildIndex = hole * 2;
rightChildIndex = hole * 2 + 1;
if (rightChildIndex >= size) {
if (leftChildIndex >= size) return;
else minIndex = leftChildIndex;
}
else {
if (heap[leftChildIndex] <= heap[rightChildIndex])
minIndex = leftChildIndex;
else
minIndex = rightChildIndex;
}
if (heap[hole] > heap[minIndex]) {
swap(hole, minIndex);
percolateDown(minIndex);
}
}
void BinaryHeap::percolateUp(int index) {
int parentIndex(1);
if (index != 1) {
parentIndex = index / 2;
}
if (heap[parentIndex] > heap[index]) {
swap(parentIndex, index);
percolateUp(parentIndex);
}
}
void BinaryHeap::swap(int i, int j) {
int t = heap[i];
heap[i] = heap[j];
heap[j] = t;
}
There is a bug in your percolateDown function.
void BinaryHeap::percolateDown(int hole) {
int leftChildIndex, rightChildIndex, minIndex;
leftChildIndex = hole * 2;
rightChildIndex = hole * 2 + 1;
if (rightChildIndex >= size) {
if (leftChildIndex >= size) return;
else minIndex = leftChildIndex;
}
else {
if (heap[leftChildIndex] <= heap[rightChildIndex])
minIndex = leftChildIndex;
else
minIndex = rightChildIndex;
}
if (heap[hole] > heap[minIndex]) {
swap(heap[hole], heap[minIndex]);
percolateDown(minIndex);
}
}
Let's assume you have 4 items in your heap. Visually, it looks like this:
1
/ \
3 2
/
4
The array, since you start your heap at 1, would contain [0,1,3,2,4], and size is 4. You call deleteMin, which moves the last item to the front, giving you [0,4,3,2,4], with size = 3. Then it calls percolateDown(1).
percolateDown computes leftChildIndex = 2 and rightChildIndex = 3. Then you hit this:
`if (rightChildIndex >= size)`
But rightChildIndex is equal to 3, which is the same as size. So the code will never enter the conditional to compare the right child with the left child. Instead, it will compare the left child with the parent, find that it's less, and swap the nodes. You will end up with this invalid heap:
3
/ \
4 2
It's interesting to note that the >= check on the indexes is a common idiom when dealing with 0-based arrays. But the code you're working with treats the array as though it's 1-based. And with 1-based arrays the standard idiom is >. This is one of the reasons I strongly recommend putting the root node of a binary heap at 0 when you're working with a language that has 0-based arrays.
A cleaner (and correct) way to do this would be:
int leftChildIndex, rightChildIndex, minIndex;
leftChildIndex = hole * 2;
rightChildIndex = hole * 2 + 1;
if (leftChildIndex > size) {
// if the left child index is outside the heap,
// then the right child index will be, too.
return;
}
// assume left is smallest
minIndex = leftChildIndex;
// and only check the right if it exists
if (rightChildIndex <= size) {
if (heap[rightChildIndex] < heap[leftChildIndex]) {
minIndex = rightChildIndex;
}
}
Related
I'm learning C++ and am playing around with searching/sorting algorithms.
I am trying to do binary search on an unsorted list of items and return the original array index. I have to sort it first, so to preserve the original indices, I created a 2D array, put the data in the first column and the original indices in the second. (I pared it down a little, which is why I had to put //insert data items here.)
template <class TYPE>
int SomeClass<TYPE>::find(TYPE data)
{
TYPE(*ary)[2] = new TYPE[size()][2];
for (int i = 0; i < size(); i++)
{
ary[i][0] = //insert data items here;
ary[i][1] = i;
}
//reading the data items and indexes into the new 2D array works
someSort(ary, size());
return bsearch(ary, 0, size()-1, data);
}
Assume you have some sorting algorithm. As an example, I'll just put bubble sort below because it doesn't take up much space to write.
template <class DT>
void SomeClass<TYPE>::someSort(TYPE A[][2], int n)
{
int i, j;
for (i = 0; i < n- 1; i++)
{
for (j = 0; j < n- i - 1; j++)
{
if (A[j] > A[j + 1])
swap(&A[j][0], &A[j + 1][0]);
}
}
}
Alright, so my question is how would you modify binary search for a 2D array and return the original value (which is in the second slot of the array)? (Feel free to modify my sorting example, too, in case there are issues there.)
template <class TYPE>
int SomeClass<TYPE>::bsearch(TYPE A[][2], int left, int right, TYPE data)
{
while (right>= left)
{
int mid = left + (right+ left) / 2;
if (A[mid][0] == data)
return A[mid][1];
if (A[mid][0] > data)
right= mid- 1;
else
left= mid+ 1;
}
return -1;
}
You need to check your binary search implementation, as it's not correct. Here's improved version:
template <class TYPE>
int SomeClass<TYPE>::bsearch(TYPE A[][2], int left, int right, TYPE data)
{
while (right>= left)
{
int mid = left + (right - left) / 2; // <== corrected here.
if (A[mid][0] == data)
return A[mid][1];
if (A[mid][0] > data)
right= mid- 1;
else
left= mid+ 1;
}
return -1;
}
While learning it's better to code algorithms manually, but you should know that C++ provides implementation for common algorithms like binary search or quick/merge sort.
For example, you could define your value-pair struct vp that holds value and position in original array:
struct vp
{
TYPE val;
int pos;
bool operator<(const vp& vp) const {
return val < vp.val;
}
static bool cmp(TYPE b, const vp& a) {
return b < a.val;
}
};
then you can sort array of value-pairs using std::sort:
vp *arr = ...
std::sort(arr, arr+size());
then, you can use lower_bound or upper_bound to do binary search in your array of value-pairs:
auto p = std::upper_bound(arr, arr+size(), data, vp::cmp);
But you'll need to interpret properly returned value to figure out if value was found in the array or not.
Trying to understand the insertion sort algorithm..
My algorithm looks like this currently:
void insertionSort(int *array, int N) {
int value;
int hole;
int *array2;
for (int i = 1; i < N - 1; i++) {
value = array[i]; //next item to be inserted in array 2
hole = i;
while (hole > 0 && array[hole - 1] > value) {
array[hole] = array[hole - 1];
hole = hole - 1;
}
array[hole] = value;
}
}
My algorithm works for sorting arrays, however I now need to change it so that I build up a new sorted array (array2) one element at a time, rather than just working with the original array.
Is there a simple way to implement this given my completed algorithm?
Thanks.
You can use the following method:
int *array2 = calloc(N, sizeof(int));
for(var index = 0; index < N; index++)
{
array2[index] = array[index];
}
and after that use array2 instead of array
then just change the prototype of your function to int *insertionSort
All remaining is to return array2 at the end of task
But be aware of memory leak: https://en.wikipedia.org/wiki/Memory_leak
I have an ordered arrayList. Where elements are to be ordered in 1,2,3,4,5,6.
At the moment the push function is not working. It will insert an element, but there is a problem which i cannot figure out. The push will work once you insert an incremented number... So like 1,2,3,4,5 but will not work once i insert like this 5,2,4,3,2,1.
Can anyone help me with this?
Here is my code:
Initialisation
template <class Datatype>
//--------------------------------------------------------------------------------------------
// Class: OrderedArray.
//--------------------------------------------------------------------------------------------
class OrderedArray
{
//--------------------------------------------------------------------------------------------
// Member Variables.
//--------------------------------------------------------------------------------------------
private:
Datatype* m_array;
int size;
int g_size;
int num_elements;
//---------------------------------------------------------------------------------------
// Name: Print Function:
// Description: To print out all elemenst in the Array.
//---------------------------------------------------------------------------------------
void print()
{
for(int i=0;i< size;i++)
{
cout << "Position: " <<m_array[i]<<endl;
}
}
//---------------------------------------------------------------------------------------
// Name: Resize Function:
// Description: To resize the Array.
//---------------------------------------------------------------------------------------
void Resize(int p_size)//resizes the array to the size of p_size
{
if(p_size < 0)//checks if new size is less than 0
{
cout << "ERROR! Size of an array can not be less than 0!" << endl;
}
else//else its ok to continue
{
Datatype* newArray = new Datatype[p_size];//creates a pointer newArray that points at a new array
if(newArray == 0)
return;
int min;
if(p_size < m_size)//checks the if the new array is smaller than the old one
min = p_size;
else//else its going to be bigger
min = m_size;
int index;
int temp = num_elements;//puts num_elements into a temporary variable called temp
num_elements = 0;//num_elements is set to 0
for(index = 0; index < min; index++)
{
newArray[index] = m_array[index];//places everything from the old array into the new array that will fit.
if(num_elements < temp)//if the num_elements is less than temp(the original num_elements)
{
num_elements++;//increment num_elements. This will keep incrementing to create the new num_elements based the number of elements cut off in the resize
}
}
m_size = p_size;//sets the old size to be equal to the new size
if(m_array != 0)
delete[] m_array;//deletes the old array
m_array = newArray;//makes m_array point at the new array
newArray = 0;//makes newArray a null pointer
}
}
//---------------------------------------------------------------------------------------
// Name: Push
// Description:
//---------------------------------------------------------------------------------------
void push(Datatype p_item)
{
if(num_elements == size)//checks if the array is full and needs to be resized
{
Resize(size + g_size);//calls the resize function
}
int pos = num_elements;
for(int x=0;x<num_elements;x++)
{
if(p_item < m_array[x])
pos=x;
break;
}
//loops through the array from high to low moving all values to the right
//to make space for the passed in value until it gets to the right place
for(int index = num_elements; index >= pos; index--)
{
m_array[index] = m_array[index-1];//moves the values to the right
}
m_array[pos] = p_item;//the passed in value is positioned into its ordered position
num_elements++;
cout<< "Num Elements " << num_elements;
cout<< "Size " <<size;
}
I think I found the beginning of the problem:
for(int x=0;x<num_elements;x++)
{
if(p_item < m_array[x])
pos=x;
}
your pos will always always be at the end of the array that way(assuming the array is properly sorted up to that point). add a break statement to let your loop know when it should stop assigning greater and greater values to pos
for(int x=0;x<num_elements;x++)
{
if(p_item < m_array[x])
{
pos=x;
break;
}
}
your code has some other issues too, for instance
for(int index = num_elements; index > pos; index--)
{
m_array[index] = m_array[index+1];//moves the values to the right
}
actually moves the values left. change the assignment to
for(int index = num_elements; index > pos; index--)
{
m_array[index] = m_array[index-1];//moves the values to the right
}
How can I make an inset method that will add a number into the array in the correct order?
void addElement(int table[], int element, int length) {
int x = 0;
int temporary=0;
cout<<length<<endl;
if(length == 1) {
table[0] = element;
}
else {
if(length == 2) {
if (table[0] > element) {
int temp = table[0];
table[0] = element;
table[1] = temp;
}
else {
table[1] = element;
}
}
else {
for(int i = 0; i< length && x == 0; i++) {
if(element<table[i] && element>=table[i-1]) {
for(int y = i; y<length; y++) {
temporary = table[y+2];
int temp = table[y];
table[y] = element;
table[y+1] = table
}
}
}
}
}
}
This is as far as I have gotten. In my main class I have worked it out so that array is increased by 1. So there is one open space at the end of the array for everything to be pushed back by 1.
You can scan the array from back to front, moving values up until you find the correct insertion point.
void addElement(int *table, int element, int length)
{
int i = length - 1;
for (; i > 0 && table[i-1] > element; --i)
{
table[i] = table[i-1];
}
table[i] = element;
}
Write a shiftElements function, write a findIndexOfFirstGreaterThan function, then in addElement - find the index, if -1 then put in last slot, else shift elements using index, then a[index]=elem;
Draw yourself an example, then work out a list of very simple steps required to do what you want.
Then write code that does those steps.
Im not sure if this is what your looking for, but I think you want something that adds an element depending on its integer value. Also, I do not have access to a compiler at this moment so there might be a couple of errors. The code below is just written to give you a brief idea of what you could do, but probably not a perfect solution to your problem.
int addElement (int element, int array [], int length)
{
vector <int> vectorOfInts; //vector to store current order of ints
vector <int> vectorOfArrangedInts; //vector to store arranged order
for (int counter = 0; counter < length; counter ++) //loop to fill the array with values
{
vectorOfInts.push_back (array [counter]);
}
for (int counter = 0; counter < vectorOfInts.length(); counter ++) //loop through all elements
{
int temp = 0; //stores temp value of biggest number found at a specific moment
int elementIndex; //stores indexes
for (int counterTwo = 0; counterTwo < vectorOfInts.length(); counterTwo ++) //loop through all elements to find the biggest array
{
if (vectorOfInts.at (counterTwo) >= temp) //if value is bigger than current biggest number
{
temp = vectorOfInts.at (counterTwo); //change temp value
elementIndex = counterTwo; //remember index
}
}
vectorOfArrangedInts.push_back (vectorOfInts.at(elementIndex)); //add the biggest number to the arranged values
vectorOfInts.erase (vectorOfInts.begin() + elementIndex); //remove the biggest element
}
I'm creating a heap implementation for a computer science class, and I was wondering if the following recursive function would create a heap out of an array object that was not already a heap.
the code is as follows:
void Heap::Heapify(int i)
{
int temp, l, r, heapify;
l = LeftChild(i);// get the left child
r = RightChild(i);// get the right child
//if one of the children is bigger than the index
if((Data[i] < Data[l]) || (Data[i]< Data[r]))
{
//if left is the bigger child
if(Data[l] > Data[r])
{
//swap parent with left child
temp = Data[i];
Data[i] = Data[l];
Data[l] = temp;
heapify = l; // index that was swapped
}
//if right is the bigger child
else
{
//swap parent with right child
temp = Data[i];
Data[i] = Data[r];
Data[r] = temp;
heapify = r; // index that was swapped
}
// do a recursive call with the index
//that was swapped
Heapify(heapify);
}
}
the idea is that you see if the data at the index given is bigger than all of it's children. If it is, the function ends no problem. Otherwise, it check to see which is biggest(left or right children), and then swaps that with the index. The heapify is then called at the index where the swapping happened.
by ildjarn's request, I'm including my full class definition and implementation files to aid in the answering of my question:
here's the header file:
#ifndef HEAP_H
#define HEAP_H
//Programmer: Christopher De Bow
//Date: november 15, 2011
class Heap
{
private:
int Data [100];
int Parent(int);
int RightChild(int);
int LeftChild(int);
void Heapify(int);
void BuildHeap();
public:
Heap();
void insert();
void HeapSort();
void ExtractMaximum();
int Maximum();
void PrintHeap();
int heapsize;
void SetData(int[]);
};
#endif
and the implementation file:
#include <iostream>
#include "Heap.h"
using namespace std;
//Programmer: Christopher De Bow
//Date: november 15, 2011
Heap::Heap()
{
int init [10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
heapsize = 10;
SetData(init);
}
int Heap::Parent(int index)
{
int Rval;
if(index%2 == 0)// if the index is even
{
Rval = ((index-1)/2);
}
else// if the index is odd
{
Rval = (index/2);
}
return Rval;
}
int Heap::RightChild(int arrplace)
{
int ret;
ret = ((2*arrplace)+2); //rightchild is index times 2 plus 2
return ret;
}
int Heap::LeftChild(int i)
{
int rval;
rval = ((2*i)+1); //leftchild is index times 2 plus 1
return rval;
}
void Heap::Heapify(int i)
{
int temp, l, r, heapify;
l = LeftChild(i); // get the left child
r = RightChild(i); // get the right child
if((l <= heapSize) && (data[l] > data[i]))
{
heapify = l;
{
else
{
heapfiy = i;
}
if((r <= heapSize) && (data[r] > data[heapify]))
{
heapify = r;
}
if(heapify != i) // one of the two child nodes has proved
{ // larger than Data[i], so interchange values
//swap parent with left child
temp = Data[i];
Data[i] = Data[heapify];
Data[heapify] = temp;
Heapify(heapify);
}
}
void Heap::BuildHeap()
{
// we do not have a heap
// we will make a heap
// by calling heapify starting at the lowest
// internal node in the heap
for(int i = heapsize; i >= 1; i--)
{
Heapify(i-1);
}
}
void Heap::insert()
{
int insert;
heapsize = (heapsize + 1);
//getting data from the user
cout<<"what data would you like to insert?"<<endl;
cin>>insert;
Data[heapsize] = insert;
BuildHeap(); //call BuildHeap on array
cout<<"done"<<endl;
}
void Heap::PrintHeap()
{
BuildHeap();
for(int count = 0; count < (heapsize-1); count++)
{
cout<<Data[count];// print out every element in heap
}
cout<<endl<<endl;
}
void Heap::HeapSort()
{
BuildHeap();
int temp;
// do this for every elem in heap:
for(int i = 0; i < heapsize; i++)
{
temp = Data[heapsize-1];
Data[heapsize-1] = Data[0];
Data[0] = temp;
heapsize--;
BuildHeap();
}
PrintHeap();
}
void Heap::ExtractMaximum()
{
BuildHeap();
//assign last thing in heap to first thing in heap
Data[0] = Data[heapsize];
heapsize --; // decrease heapsize by one
Heapify(0); // heapify from the top
}
int Heap::Maximum()
{
int Rval;
BuildHeap();// make sure we have a heap
Rval = Data[0];
return Rval; // return top thing
}
//initialize the elements in the "Data" array
void Heap::SetData(int x[])
{
for(int i = 0; i <= (heapsize); i++)
{
Data[i] = x[i];
}
}
Your algorithm works. The problem is in the translation of algorithm to code. Say you declared Data as :
int Data[7];
and you populate it with the initial values {0, 1, 2, 3, 4, 5, 6}. Presuming definitions of LeftChild(i) and RightChild(i) to be something like:
#define LeftChild(i) ((i << 1) + 1)
#define RightChild(i) ((i << 1) + 2)
then your function BuildHeap(), which should be something like:
void Heap::BuildHeap()
{
for(int i = (7 >> 1); i >= 1; i--) // in general, replace 7 with
// (sizeof(Data)/sizeof(int)), presuming
// you have an array of int's. if not,
// replace int with the relevant data type
Heapify(i-1);
}
will begin the Heapify process on the lower-right-most sub-tree root. In this case, this is array index 2, with a left child of 5 and a right child of 6. Heapify will correctly exchange 2 and 6 and recursively call Heapify(6).
Here the whole thing can run aground! At present your tree looks like :
0
1 2
3 4 5 6
u n d e f i n e d s p a c e
so the call Heapify(6) will dutifully compare the values of Data[6] with Data[13] and Data[14] (the perils of C++ and its lack of array boundaries enforcement, unlike Java). Obviously, the latter two values can be any junk left in RAM. One solution here, ugly but a working patch, is to add 8 elements in the declaration of Data and initialize them all to some value lower than any element of the array. The better solution is to add a heapSize variable to your class and set it equal to the length of your array:
heapSize = (sizeof(Data)/sizeof(int));
Then integrate logic to only compare child nodes if they are valid leaves of the tree. An efficient implementation of this is :
void Heap::Heapify(int i)
{
int temp, l, r, heapify;
l = LeftChild(i); // get the left child
r = RightChild(i); // get the right child
if((l <= heapSize) && (Data[l] > Data[i]))
heapify = l;
else heapfiy = i;
if((r <= heapSize) && (Data[r] > Data[heapify]))
heapify = r;
if(heapify != i) // one of the two child nodes has proved
// larger than Data[i], so interchange values
{
//swap parent with left child
temp = Data[i];
Data[i] = Data[heapify];
Data[heapify] = temp;
Heapify(heapify);
}
}
So to summarize, the solution is as straightforward as adding logic to make sure the child nodes are valid leaves of the tree, and your main function will have something like :
Heap heap;
// initialize Data here
heap.BuildHeap();
Hope that helps.
No. On the tree
1
/ \
/ \
/ \
2 3
/ \ / \
6 7 4 5
the output is going to be
3
/ \
/ \
/ \
2 5
/ \ / \
6 7 4 1
which has several heap violations. (I'm assuming that Data[l] and Data[r] are minus infinity if the corresponding children do not exist. You may need extra logic to ensure this.)
What your function does is fix a tree that may not be a heap but whose left and right subtrees are heaps. You need to call it on every node, in postorder (i.e., for i from n - 1 down to 0) so that the children of i are heaps when Heapify(i) is called.
Your code now successfully builds a heap. There was only one conceptual flaw : the rest were off-by-one indexing errors. The one fundamental error was in BuildHeap : you had
for(int i = heapSize; i >= 1; i--)
{
Heapify(i-1);
}
whereas this should be
for(int i = (heapSize / 2); i >= 1; i--)
{
Heapify(i-1);
}
This is really important, you must see that Heapify is always called on a tree root, and (this is really cool) you can easily find the last tree root in the array at the index ((heapSize/2) - 1) (this is for C++ and Java style where the first index == 0). The way it was written your code called Heapify on the last leaf of the tree, which is in error.
Other than that, I added comments to flag the off-by-one errors. I placed them flush left so you can easily find them. Hope you get a suberb understanding of algorithms and data structures! :-)
Your header file :
#ifndef HEAP_H
#define HEAP_H
//Programmer: Christopher De Bow
//Date: november 15, 2011
class Heap
{
private:
int Data [100];
int Parent(int);
int RightChild(int);
int LeftChild(int);
void Heapify(int);
void BuildHeap();
// SO added heapSize
int heapSize;
public:
Heap();
void insert();
void HeapSort();
void ExtractMaximum();
int Maximum();
void PrintHeap();
int heapsize;
void SetData(int[]);
};
#endif
Your cpp file :
#include <iostream>
#include "Heap.h"
using namespace std;
//Programmer: Christopher De Bow
//Date: november 15, 2011
Heap::Heap()
{
int init [10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
heapSize = 10;
SetData(init);
}
int Heap::Parent(int index)
{
int Rval;
if(index%2 == 0)// if the index is even
{
Rval = ((index-1)/2);
}
else// if the index is odd
{
Rval = (index/2);
}
return Rval;
}
int Heap::RightChild(int arrplace)
{
int ret;
ret = ((2*arrplace)+2); //rightchild is index times 2 plus 2
return ret;
}
int Heap::LeftChild(int i)
{
int rval;
rval = ((2*i)+1); //leftchild is index times 2 plus 1
return rval;
}
void Heap::Heapify(int i)
{
int temp, l, r, heapify;
l = LeftChild(i); // get the left child
r = RightChild(i); // get the right child
// you have to compare the index to (heapSize - 1) because we are working
// with C++ and the first array index is 0 : l and r are direct indices
// into the array, so the maximum possible index is the heapSize'th
// element, which is at heapSize-1. this was kind of nasty as it let the
// heapify index get too large and led to a swap with memory beyond the
// last element of the array (again, C++ doesn't enforce array boundaries
// as Java does).
if((l <= (heapSize-1)) && (Data[l] > Data[i]))
heapify = l;
else
heapify = i;
// you have to compare the index to (heapSize - 1) because we are working
// with C++ and the first array index is 0 : l and r are direct indices
// into the array, so the maximum possible index is the heapSize'th
// element, which is at heapSize-1. this was kind of nasty as it let the
// heapify index get too large and led to a swap with memory beyond the
// last element of the array (again, C++ doesn't enforce array boundaries
// as Java does).
if((r <= (heapSize-1)) && (Data[r] > Data[heapify]))
heapify = r;
if(heapify != i) // one of the two child nodes has proved
{ // larger than Data[i], so interchange values
//swap parent with left child
temp = Data[i];
Data[i] = Data[heapify];
Data[heapify] = temp;
Heapify(heapify);
}
}
void Heap::BuildHeap()
{
// we do not have a heap
// we will make a heap
// by calling heapify starting at the lowest
// internal node in the heap
// i must be initialized to (heapsize/2), please see my
// post for an explanation
for(int i = heapSize/2; i >= 1; i--)
{
Heapify(i-1);
}
}
void Heap::insert()
{
int insert;
heapSize = (heapSize + 1);
//getting data from the user
cout<<"what data would you like to insert?"<<endl;
cin>>insert;
Data[heapSize] = insert;
BuildHeap(); //call BuildHeap on array
cout<<"done"<<endl;
}
void Heap::PrintHeap()
{
BuildHeap();
// the array indices are from 0 through (heapSize-1), so
// count must be less than _or equal to_ (heapSize-1). another
// way of phrasing this (which i applied in this function)
// is (count < heapSize). you'll get better boundary conditions
// with practice.
for(int count = 0; count < heapSize; count++)
{
// added an endl to the output for clarity
cout << Data[count] << endl;// print out every element in heap
}
cout<<endl<<endl;
}
void Heap::HeapSort()
{
BuildHeap();
int temp;
// do this for every elem in heap:
for(int i = 0; i < heapSize; i++)
{
temp = Data[heapSize-1];
Data[heapSize-1] = Data[0];
Data[0] = temp;
heapSize--;
BuildHeap();
}
PrintHeap();
}
void Heap::ExtractMaximum()
{
BuildHeap();
//assign last thing in heap to first thing in heap
Data[0] = Data[heapSize];
heapSize--; // decrease heapSize by one
Heapify(0); // heapify from the top
}
int Heap::Maximum()
{
int Rval;
BuildHeap();// make sure we have a heap
Rval = Data[0];
return Rval; // return top thing
}
//initialize the elements in the "Data" array
void Heap::SetData(int x[])
{
// the array indices are from 0 through (heapSize-1), so
// count must be less than _or equal to_ (heapSize-1). another
// way of phrasing this (which i applied in this function)
// is (i < heapSize). you'll get better boundary conditions
// with practice.
for(int i = 0; i < heapSize; i++)
{
Data[i] = x[i];
}
}
// basic confirmation function
int main()
{
Heap heap;
heap.PrintHeap();
return 0;
}
Your code as written here sure feels right; but there's nothing quite like writing a few test cases to see how it performs. Be sure to test against a heap with 1, 2, 3, 4, and dozens of elements. (I expect the base case to be where this piece falls short -- how does it handle when i has no children?. Testing on small heaps ought to show in a hurry.)
Some small advice for this piece:
if(Data[l] > Data[r])
{
//swap parent with left child
temp = Data[i];
Data[i] = Data[l];
Data[l] = temp;
heapify = l; // index that was swapped
}
//if right is the bigger child
else
{ //swap parent with right child
temp = Data[i];
Data[i] = Data[r];
Data[r] = temp;
heapify = r; // index that was swapped
}
You could probably gain some legibility by setting only the index in the if blocks:
if(Data[l] > Data[r]) {
swapme = l;
} else {
swapme = r;
}
temp = Data[i];
Data[i] = Data[swapme];
Data[swapme] = temp;
heapify = swapme;