C++ vector push_back not making a copy? - c++

vector<minHeap> letters;
letters = countLetters(text);
while (letters.size() >= 2) {
minHeap first = popMin(&letters);
minHeap second = popMin(&letters);
minHeap third('$');
third.count = first.count + second.count;
third.left = &first;
third.right = &second;
letters.push_back(third);
}
I tried to debug the code. The 'first', 'second' and 'third' values are working correctly. My problem is: When I push the 'third' into the vector, in the next round of the loop, the object that we pushed in the last round is changed to the new 'third' and is same with the 'third' in the new round.
For example in the first round X is pushed into the vector, In the next round Y is pushed but the problem is it changes the X to Y too, so we have 2 Ys now. and again in the next round we have 3 Z.
Like it's not creating a copy of the 'third', so when I change it, it changes the previous objects too.
What am I doing wrong? :s
Edit:
minHeap class:
class minHeap {
public:
char letter;
int count = 1;
minHeap* left = NULL;
minHeap* right = NULL;
minHeap(char letter) {
this->letter = letter;
}
};
popMin: (Finds the minimum 'count' in the minHeaps and destroys it, then returns a copy of it)
minHeap popMin(vector<minHeap>* letters) {
int index = 0;
for (size_t i = 0; i < letters->size(); i++) {
if (letters->at(i).count < letters->at(index).count)
index = i;
}
minHeap res = letters->at(index);
letters->erase(letters->begin() + index);
return res;
}
countLetters: (Counts letters and creates a minHeap object for each, increases the 'count' (freq) if it's created before.
vector<minHeap> countLetters(string text) {
vector<minHeap> letters; // Stores all the characters with their count
for (size_t i = 0; i < text.length(); i++) {
bool found = false;
for (size_t j = 0; j < letters.size(); j++) {
if (letters.at(j).letter == text[i]) {
letters.at(j).count++; // Character exists in list, increase its count by one
found = true;
break;
}
}
if (!found) { // Character doesn't exist in list, create it and push it to the list
minHeap letter(text[i]);
letters.push_back(letter);
}
}
return letters;
}
In General: I'm trying to do the huffman coding using minHeap.

You're storing &first and &second, which become invalid pointers when
the current iteration ends. If you dereference them after that, your
program has undefined behaviour. #molbdnilo
So I changed my code to :
vector<minHeap> letters;
letters = countLetters(text);
while (letters.size() >= 2) {
minHeap* first = new minHeap('-');
*first = popMin(&letters);
minHeap* second = new minHeap('-');
*second = popMin(&letters);
minHeap third('$');
third.count = first->count + second->count;
third.left = first;
third.right = second;
letters.push_back(third);
}
And it's fixed. Thanks :)

Related

How to "change the size" of an array [Pointers being used]

So I have to implement a stack using an array built in a class, and if the "stack" ever fills up, I am supposed to increase the size of the array which I attempted, and failed. So I am just curious as to what I need to change in order to make this work.
class AbstractStack
{
private:
Type elements; // elements in the array
Type max;
Type *s;
public:
AbstractStack(Type num) { //CONSTRUCTOR
elements= -1;
this->max = num;
s = new Type[max];
}
/* bunch of code that does not apply to this issue
*/
void push ( Type e ) {
if (elements + 1 == max) {
cout << "Stack at max size, WIll increase size of array and add item" << endl;
Type *temp = new Type[max + (max/2)];
for (int i = 0; i < elements+1; i++) {
temp[i] = s[i];
}
s = temp;
delete temp;
elements++;
s[elements] ;
return;
}
else {
elements++;
s[elements] = e;
}
}
When I take the size of this new s, I get the correct size of 1 larger than before because this function is only called when trying to add 1 element to the full stack, but when I attempt to use the top function, it just gives me 0 then I get like 50 lines of error codes starting in:
*** Error in `./a.out': double free or corruption (top): 0x0000000000c53cf0 ***
======= Backtrace: =========
/lib64/libc.so.6(+0x7c619)[0x7fa34a270619]
./a.out[0x400c38]
./a.out[0x400b48]
/lib64/libc.so.6(__libc_start_main+0xf5)[0x7fa34a215c05]
./a.out[0x400979]
Type elements; // elements in the array
Type max;
These are both just ints, or unsigneds, or size_ts, or whatever you prefer for counting. They have nothing to do with Type whatsoever.
void push ( Type e ) {
if (elements + 1 == max) {
cout << "Stack at max size, WIll increase size of array and add item" << endl;
Type *temp = new Type[max + (max/2)];
After this you should increase max to max*3/2.
for (int i = 0; i < elements+1; i++) {
Loop condition should be i < elements. You are using element zero, and element[elements] does not exist yet.
temp[i] = s[i];
}
s = temp;
delete temp;
Last two lines should be delete[] s followed by s = temp.
elements++;
s[elements] ;
Last two lines should be s[elements++] = e;
return;
return is redundant here.
}
else {
elements++;
s[elements] = e;
Again, the last two lines should be s[elements++] = e;
}
}
Corrected and simplified version:
int elements;
int max;
// ...
void push ( Type e ) {
if (elements + 1 == max) {
cout << "Stack at max size, WIll increase size of array and add item" << endl;
max += max/2;
Type *temp = new Type[max];
for (int i = 0; i < elements; i++) {
temp[i] = s[i];
}
delete[] s;
s = temp;
}
s[elements++] = e;
}
You have to delete the old array (s) instead of the new (temp):
delete[] s;
s = temp;
Also: make sure that your class has a proper destructor (deleting s).

linked list access violation writing location

I'm writing a program doing LSD radix sort with SSN. The program will parse the number into 3 digits and do 3 passes. Each pass I store the number into corresponding array element bucket[]; if there's a duplicate, I create a linked list in that location and store the duplicated one behind the one that's already there. The code breaks when I try to insert in the end of the linked list.
EDIT new error message
class node
{
public:
node(int n, node *p){data=n;next=p;}
int data;
node *next;
};
void genData(int *dta, int n)
{
for(int i=0; i < n; i++)// generate the social security numbers at random
dta[i] = rand()%889 + 111 + 1000*(rand()%889 + 111) + 1000000* (rand()%889 + 111);
}
int radixSort(int *dta, int n, int *out)
{
// the dta array contains the data to be sorted.
// n is the number of data items in the array
// out is the array to put the sorted data
node *bucket[1000]; // declare an array of 1000 linked lists (head pointers)
int count = 0; // use this to count the instructions to graph the big-o
for(int i = 0; i < n; i++)out[i] = dta[i];
for (int pass = 0; pass < 3; pass++)
{
for (int j = 0; j < 1000; j++){
bucket[j] = NULL;
}
delete bucket;
delete[]bucket;
for (int i = 0; i < n; i++){
int index=0;
switch (pass)
{
case 0:
index = out[i] % 1000;
case 1:
index = (out[i]/1000) % 1000;
case 2:
index = out[i] / 1000000;
};
if (bucket[index] = NULL){
bucket[index] = new node(out[i], NULL);
}
else{
node *cur=bucket[index];
while (cur->next!= nullptr){ //****access violation reading location
cur = cur->next;
}
node *ptr = new node(out[i], NULL);
cur->next = ptr;
}
}
int idx = 0;
for (int i = 0; i < 1000; i++){
if (bucket[i] == NULL) continue;
else{
out[idx] = bucket[i]->data;
idx++;
count++;
}
}
}
Theres a number of problems in your code:
In your switch-statement you have lines like index == out[i] % 1000;Those do a comparison and i doubt this is what you want. Assignments use single =
Your initialization for (int j = 0; j < 1000; j++){bucket[j] = NULL;} does not check if theres already a pointer in it - this will cause memory leaks after the first pass. Remember: Every new needs a delete.
And thats what is probably breaking your code: while (cur!= NULL){cur = cur->next;} exits the while-loop once cur is the nullptr - which means trying to dereference it 2 lines later is trying to dereference the nullptr and a bad idea. What you probably want to check in order to get your last element is `while(cur->next != nullptr)
And just as a note: if your compiler supports nullptr its a good idea to use it, even if you might need to enable C++11 via appropriate flags.

arrays, removeFirst() not working?

I have created a method that should remove the first element of an array, however when I run my code, the debugger flips out and I'm not sure why.
This is my removeFirst() method:
Loan & ListOfLoans :: removeFirst(){
index = 0;
//determine if the container needs to be shrunk
if((numberOfElements < capacity/4) && (capacity >= 4)){ // shrink container when array is 1/4 full
cout<<"shrinking array! \n";
Loan ** temp = elements;
elements = new Loan * [numberOfElements/2];
//copy temp array to elements
for(int i = 0; i<numberOfElements; i++){
temp[i] = elements[i];
numberOfElements = numberOfElements/2;
delete [] temp;
}
}
numberOfElements--;
return **elements;
}
And my header file for good measure:
#include <iostream>
#include "loan.h"
using namespace std;
class ListOfLoans {
public:
ListOfLoans(int initial_size=4);
~ListOfLoans(void);
void add(Loan & aLoan);
Loan & first() ;
Loan & removeFirst();
// answer the first element from the list and remove it from the list
// if the resulting list is more than three quarters empty release some memory
Loan & removeLast();
// answer the last element from the list and remove it from the list
// if the resulting list is more than three quarters empty release some memory
Loan & next();
int size();
private:
Loan ** elements; //actuall stuff in the array m_pnData;
int numberOfElements; //number of elements in the list stize of the array? m_nLength
int capacity; //size of the available array memory
int index; //used to help with the iteration
};
Try moving delete [] temp; under the for loop.
It looks like one issue may be that delete [] temp; is being called repeatedly within the for loop.
The first iteration through the loop, the memory associated with temp will freed. Subsequent iterations through the loop will access the freed memory.
There may be other issues. It would be very helpful to see the output from the debugger.
There are many issues with this code. Here is an annotated copy.
// Return by reference cannot be used if you are removing the element.
// This looks like a Java-ism.
Loan & ListOfLoans :: removeFirst(){
// unused variable
index = 0;
if((numberOfElements < capacity/4) && (capacity >= 4)){
cout<<"shrinking array! \n";
Loan ** temp = elements;
// you are allocating an array of size numberOfElements/2...
elements = new Loan * [numberOfElements/2];
// then accessing elements which are way past its end.
for(int i = 0; i<numberOfElements; i++){
temp[i] = elements[i];
// you are halving the array size in every iteration
numberOfElements = numberOfElements/2;
// you are deleting temp in every iteration,
// causing double-frees
delete [] temp;
}
}
// if the array does not need to be shrunk,
// you are actually removing the last element.
// the removed element is not freed and is leaking.
numberOfElements--;
// you are returning the first element,
// which is not removed.
return **elements;
}
I would strongly recommend to replace ListOfLoans with an STL container, such as std::deque. If you can't do this, here is a minimal fixed version.
Loan ListOfLoans::removeFirst() {
Loan to_return;
if (numberOfElements == 0) {
return to_return; // return default value, there is nothing to remove
}
if ((numberOfElements < capacity/4) && (capacity >= 4)) {
Loan **old = elements;
capacity = capacity / 2;
elements = new Loan*[capacity];
for (int i=0; i < numberOfElements - 1; ++i) {
elements[i] = old[i+1];
}
to_return = *old[0];
delete old[0];
delete[] old;
} else {
to_return = *elements[0];
delete elements[0];
for (int i=0; i < numberOfElements - 1; ++i) {
elements[i] = elements[i+1];
}
}
--numberOfElements;
return to_return;
}

Inserting an element into an array

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
}

Am I implementing the "Heapify" Algorithm correctly?

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;