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;
Related
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;
}
}
I edited the code. But now it's showing runtime error. Can anyone tell why ? This is a program to sum 2 arrays and display output in third array.
I also wanted to know if this code could be optimized ?
void sumOfTwoArrays(int arr[], int size1, int brr[], int size2, int crr[])
{
int k;
if(size1>size2){
k = size1;
}
else
k = size2;
int c = k;
int r = 0;
int i = size1-1;
int j = size2-1;
for(;i>=0&&j>=0;i--,j--){
int n = arr[i] + brr[j] + r;
if(n<=9){
crr[c] = n;
}
else
{
int r = n/10;
n = n%10;
crr[c] = n;
}
c--;
}
while(arr[i]>=0){
crr[c] = arr[i] + r;
r = 0;
c--;
}
while(brr[j]>=0){
crr[c] = brr[j] + r;
r = 0;
c--;
}
if(r!=0){
crr[c] = r;
}
}
You declare variables in a block scope, i.e. inside { ... }, and these variables are visible only within this block:
if(size1>size2){
int crr[size1+1];
int c = size1;
}
else{
int crr[size2+1];
int c = size2;
}
...
crr[c] = ... // neither crr nor c are valid here any more
BTW: C++ does not support variable length arrays like int crr[size1+1] (when size is not a compile-time-constant).
To overcome this, write...
int *crr;
int c;
if(size1>size2){
crr = new int[size1+1];
c = size1;
}
else{
crr = new int[size2+1];
c = size2;
}
...
delete[] crr;
About scope issue: see Stephan's answer.
I also wanted to know if this code could be optimized
By use of std::vector. OK, the following is only a fine option if you can use vectors outside as well – copying the raw arrays into vectors wouldn't be efficient either... But if you can, then you might like this variant:
template <typename T> // optional: you're more flexible if you make a template of...
void sumOfTwoArrays(std::vector<T> const& va, std::vector<T> const& vb, std::vector<T>& vr)
{
vr.resize(std::max(va.size(), vb.size() + 1));
int carry = 0; // renamed r to something more meaningful
// these pairs will help to avoid code duplication later
std::pair pa(va, va.rbegin());
std::pair pb(vb, vb.rbegin());
auto ir = vr.rbegin();
while(pa.second != pa.first.rend() && pb.second != pb.first.rend())
{
// just skip the if/else:
// assume you have arbitrary number, the else case will be entered anyway
// in 50 % of the cases - in the other 50 %, the else branch calculates
// the correct result, too; and on most modern machines, the branch is
// rather expensive, so you result in easier code and have quite a good
// chance to even perform better...
carry += *pa.second + *pb.second;
*ir = carry % 10;
carry /= 10;
++ir, ++pa.second, ++pb.second;
}
// avoiding of two identical while loops: iterate over the two pairs...
for(auto p : { pa, pb })
{
// just loop over, if we are already at the end, won't enter...
while(p.second != p.first.rend())
{
// STILL need to continue calculating the carry!
// imagine we have set it and ciphers following are all 9!
carry += *p.second;
*ir = carry % 10;
carry /= 10;
++ir, ++p.second;
}
}
// assign either 0 or 1...
*ir = carry;
}
Variant: instead of assigning 0, you could erase first element at the very end:
if(carry == 0)
{
vr.erase(vr.begin());
}
else
{
*ir = carry;
}
Note that this will move all the elements one position to front. On the other hand, if you repeatedly add vectors already containing a leading zero, you might prepend another one again and again without need, if you don't drop it again.
You wouldn't experience any of these issues if you inverted the order of digits in the vector, having least significant one at position 0 (you'd exchange rbegin() and rend() with begin() and end(), but would use the former for printing data to display...). Erasure at the end would be an O(1) operation then:
if(carry == 0)
{
vr.erase(std::previous(vr.end())
}
// ...
All this above will only work as expected if you keep your vectors normalised (i. e. all digits in between 0 and 9 inclusive). You might consider packing the vector into a separate class such that the data is hidden away from the user and only can be modified in controlled manner (assume you have a fine vector, but a user does v[7] = -1012...).
A runtime error suggests that it is a memory issue i.e. you are writing to some memory which is not allocated to be used by your code. So, as mentioned by other contributors, you should allocate proper memory for your arrays.
Following is modified version of your code which is working fine. You can see it working here:
void sumOfTwoArrays(int arr1[], int size1, int arr2[], int size2, int sumArr[])
{
int maxLen;
int* tArry;
int l;
if(size1>size2) { maxLen = size1; tArry = arr1; l = size1 - size2; }
else { maxLen = size2; tArry = arr2; l = size2 - size1; }
int carry = 0;
while(size1 && size2){
carry += arr1[--size1] + arr2[--size2];
sumArr[maxLen--] = carry%10;
carry /= 10;
}
while(l){
carry += tArry[--l];
sumArr[maxLen--] = carry%10;
carry /= 10;
}
sumArr[maxLen] = carry;
}
Calling code looks something like this:
...
int a[] = {9,9,9,9,9};
int b[] = {1};
int l1 = sizeof(a) / sizeof(int), l2 = sizeof(b)/sizeof(int);
int l3 = ((l1 > l2) ? l1 : l2) + 1;
int *c = new int[l3];
sumOfTwoArrays(a, l1, b, l2, c);
...
delete [] c;
...
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).
I am trying to figure out why my merge sort function is not working. I believe the problem is within the merge() part of it. here is my code:
int mergeSort(int *data, int left, int right) {
//divide
if (left < right) {
int q = floor((left + right) / 2);
//conquer
mergeSort(data, left, q);
mergeSort(data, q + 1, right);
//combine
merge(data, left, q, right);
}
//print results for testing purposes
for (int i = 0; i < n; i++) {
cout << data[i] << "\n";
}
return 0;
}
And here is the merge() part of it. I believe the problem is within this part.
int merge(int *data, int left, int q, int right) {
int *temp = data;
int i = left, j = q + 1, z = left;
int t1 = 0, t2 = 0;
while (i <= q && j <= right) { //while both variables have not reached the end of their sub arrays
if (temp[i] <= temp[j]) {
data[z] = temp[i];
i++;
}
else {
data[z] = temp[j];
j++;
}
z++;
}
//if subarrays are both sorted and in order, combine them
if (i < q) {
t1 = z, t2 = i;
for (t1; t1 < right;) {
data[t1] = temp[t2];
t1++;
t2++;
}
}
else if (j < right) {
int t1 = z; int t2 = j;
for (t1; t1 <= right;) {
data[t1] = temp[t2];
t1++;
t2++;
}
}
I think that my problem is coming from declaring int *temp = data; at the beginning of merge(). My thought is that I'm getting some kind of memory address conflict between these two arrays, but I'm not sure.
I have tried arranging the data in different order, and have found that when a data needs to be moved from index n to index n-i, each index between these two indices is replaced with the value of n. For example:
the passing in the array {4, 13, 8, 12, 9 } would return {4, 8, 8, 9, 9}
My other thought is that the i and j variables are not incrementing correctly. I have been over this code repeatedly and can't seem to find a solution.
This (first line of the merge function)
int *temp = data;
does NOT copy an array; it just creates another pointer pointing to the same memory. This causes your code to overwrite your data.
You probably need to do something like this:
int * temp = new int [right - left + 1];
memcpy (temp, data + left, (right - left + 1) * sizeof(int));
and don't forget to delete[] the memory for temp at the end of your function:
delete[] temp;
Note that you'll need to change your use of z; it should start from 0, not from left.
(The following are optional performance improvements; you can ignore them.)
Allocating and freeing memory in each merge function is a bad idea. Specially since we exactly know how much total extra memory we need for merging: an array of exactly n integers.
For this reason, it's a better idea to pass in another array of the same size along with data to mergeSort, so it can be used as scratch memory (i.e. temp memory) for merging. Or if you are really clever, you can ping-pong between the actual and the scratch memory to minimize copying.
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
}