Heapifying an array - c++

I'm currently coding a small heapify code that repeated runs bubble down but everytime it seems like nothing's happening. Not sure what's wrong here maybe I'm missing something?
template <class T>
void PriorityQueue<T>::heapify (int* arrs, int size){
int i = (size-1)/2;
while (i >= 0){
bubbleDown(arrs, i, (size));
i--;
}
}
template <class T>
void PriorityQueue<T>::bubbleDown (int* arrs, int i, int size)
{
//Each level node's are indexed at 2^(level) - 2 to 2^(level+2) - 2
//Children of these node's levels are indexed at 2i+1 and 2i+2
//The parent of node i, is indexed at (i-1)/2
int leftChildren = (2*i)+1;
int rightChildren = (2*i)+2;
int largest = i;
if (rightChildren < size)
{
if (arrs[leftChildren] < arrs[rightChildren]){
largest = rightChildren;
}
else{
largest = leftChildren;
}
if (arrs[i] > arrs[largest]){
largest = i;
}
}
else if (leftChildren < size)
{
if (arrs[i] < arrs[leftChildren]){
largest = leftChildren;
}
}
if (arrs[i] < arrs[largest])
{
int temp = arrs[i];
arrs[i] = arr[largest];
arrs[largest] = temp;
}
}
I'm calling it like this:
PriorityQueue<int> test;
int arr[] = {89, 29, 36, 48, 94, 13, 27, 70, 76, 37, 42, 58};
test.heapify(arr, 12);
for (int i = 0; i < 12; i++){
cout << arr[i] << endl;
}
Console prints out it the same way the array has been initialized.
UPDATED:
Still getting weird results
[89, -842150451, 36, 29, 94, 0, 27, 70, 48, 37, 42, 13]
The results I should be getting is
[94, 76, 89, 70, 48, 58, 13, 27, 36, 29, 37, 42, 23]

Basic typo error. Should really use more meaningful names

Related

How to access values from a pointer-to-array in C++

I am using the dereference operator but I don't seem to getting values of x.
#include <iostream>
using namespace std;
class Array {
public:
int* get() {
int x[] = { 31, 45, 39, 32, 9, 23, 75, 80, 62, 9 };
int *r;
r = x;
return r;
}
};
int main() {
Array arr;
int *temp = arr.get();
for (int i = 0; i < 10; ++i) {
cout << temp[i] << " ";
}
}
This prints out 31 32765 0 0 0 0 -1989689609 32624 -989639072 32765 rather than
31 45 39 32 9 23 75 80 62 9
When a variable, that is allocated on stack, goes out of scope, it gets destroyed.
In your example functionArray::get:
int* get() {
int x[] = { 31, 45, 39, 32, 9, 23, 75, 80, 62, 9 };
int *r;
r = x;
return r;
}
variable x gets destroyed. If you don't want this to happen, you can mark your variable with a static keyword: static int x[] = ... or allocate it on heap int* x = new int[10]. If you use the latter, make sure you free the memory when it's no longer used or use smart pointers.
you need to define this as a private member of class
private:
int x[] = { 31, 45, 39, 32, 9, 23, 75, 80, 62, 9 };
or make it static when inside the function
static int x[] = { 31, 45, 39, 32, 9, 23, 75, 80, 62, 9 };
in both this cases this x array will persist and you will be able to get values out of it. Otherwise Your Get function will return only first member of the array and rest will be clear when exiting from scope of the function.

Segement fault with Inversion Counting algorithm

I am working on a program which implements the inversion counting with merge sort algorithm.
When I test my program with given test cases. I experienced segmentation fault which I cannot find the reason.
One test case is shown in the following codes:
int inputArray[5] = {5,4,3,2,1};
inversionCount Inversion(inputArray, 5);
count = Inversion.totalinversionCount(0, 4);
The program gives the correct answer as 10.
Another test case is:
int inputArray[15] = {9, 12, 3, 1, 6, 8, 2, 5, 14, 13, 11, 7, 10, 4, 0};
inversionCount Inversion(inputArray, 15);
count = Inversion.totalinversionCount(0, 14);
The program gives an answer as 48, while the correct answer is 56. I tried to debug the program by printing the array[] elements in the class. It seems in the constructor the copied array[] is {9 12 3 1 6 8 2 5 14 13 11 7 10 4 0}. However, when the program steps into counting, the class member array[] changed to {0 12 3 1 6 8 2 5 14 13 11 7 10 4 0}. The first element changed to 0 from 9. I don't know why.
The last test case is:
int inputArray[100] = { 4, 80, 70, 23, 9, 60, 68, 27, 66, 78, 12, 40, 52, 53, 44, 8, 49, 28, 18, 46, 21, 39, 51, 7, 87, 99, 69, 62, 84, 6, 79, 67, 14, 98, 83, 0, 96, 5, 82, 10, 26, 48, 3, 2, 15, 92, 11, 55, 63, 97, 43, 45, 81, 42, 95, 20, 25, 74, 24, 72, 91, 35, 86, 19, 75, 58, 71, 47, 76, 59, 64, 93, 17, 50, 56, 94, 90, 89, 32, 37, 34, 65, 1, 73, 41, 36, 57, 77, 30, 22, 13, 29, 38, 16, 88, 61, 31, 85, 33, 54 };
inversionCount Inversion(inputArray, 100);
count = Inversion.totalinversionCount(0, 99);
The program runs into segmentation fault in the construction step. The debug shows the program pauses when copying Array[] to array[].
Signal received: SIGSEGV (Segmentation fault)
For program algorithm_design_i_week_1, pid 23,328
You may discard the signal or forward it and you may continue or pause the process
My program is given below. Please help me to find out the reason for segmentation fault. Thank you very much.
inversionCount.h
#ifndef INVERSIONCOUNT_H
#define INVERSIONCOUNT_H
#include <iostream>
using namespace std;
class inversionCount {
private:
int length;
int array[];
public:
inversionCount(int Array[], int Length);
int splitCount(int first, int mid, int last);
int totalinversionCount(int first, int last);
};
#endif /* INVERSIONCOUNT_H */
inversionCount.cpp
#include "inversionCount.h"
inversionCount::inversionCount(int Array[], int Length) {
length = Length;
for (int i = 0; i < length; i++)
array[i] = Array[i];
}
int inversionCount::splitCount(int first, int mid, int last) {
int first1 = first, last1 = mid;
int first2 = mid + 1, last2 = last;
int tempArray[length];
int i = first;
int totalSplitCount = 0;
while (i < last && first1 <= last1 && first2 <= last2) {
if (array[first1] < array[first2]) {
tempArray[i] = array[first1];
first1++;
i++;
}
else {
tempArray[i] = array[first2];
totalSplitCount += last1 + 1 - first1;
first2++;
i++;
}
}
while (first1 <= last1) {
tempArray[i] = array[first1];
first1++;
i++;
}
while (first2 <= last2) {
tempArray[i] = array[first2];
first2++;
i++;
}
for (int j = first; j < last + 1; j++)
array[j] = tempArray[j];
return totalSplitCount;
}
int inversionCount::totalinversionCount(int first, int last) {
int totalCount = 0;
if (first < last) {
int mid = (first + last) / 2;
totalCount = totalinversionCount(first, mid) + totalinversionCount(mid + 1, last) + splitCount(first, mid, last);
}
return totalCount;
}
countDriver.cpp
#include "inversionCount.h"
int main(int argc, char** argv) {
int inputArray[5] = {5,4,3,2,1};
inversionCount Inversion(inputArray, 5);
int count = 0;
count = Inversion.totalinversionCount(0, 4);
cout<<"The number of inversions is "<<count<<endl;
return 0;
}
int array[]; is not legal C++ as the definition of a member variable. Your compiler must allow it as an extension, but in that case it means "no space is allocated for the array, but we will do something like:
A* pA = static_cast<A*>(malloc(sizeof(A) + Length*sizeof(int));
You are not doing this, so when you write to the array, you overwrite some random bits of memory, so bad stuff happens.
The best bet is to use std::vector.
class inversionCount {
private:
std::vector<int> array;
public:
inversionCount(int Array[], int Length) : array(Array, Array+Length) {}
int splitCount(int first, int mid, int last);
int totalinversionCount(int first, int last);
};
One other comment: it is much better to use size_t as the type of lengths and offsets into arrays and containers - it is what the C++ library uses. size_t is an unsigned type so by using the same type as the library, you avoid difficult problems with 'signed/unsigned mismatch'. (The effects are often not what you would expect.)

Why would 2D array access be faster than 1D array access?

I have two programs, compiled with g++ and executed on linux. Program 1 creates a 2D array and then measures how long it takes to access all of its elements 100000 times:
#include <time.h>
#include <iostream>
int main()
{
clock_t time;
int i, y, x;
int matrix[9][9]{{ 0, 1, 2, 3, 4, 5, 6, 7, 8},
{ 9, 10, 11, 12, 13, 14, 15, 16, 17},
{18, 19, 20, 21, 22, 23, 24, 25, 26},
{27, 28, 29, 30, 31, 32, 33, 34, 35},
{36, 37, 38, 39, 40, 41, 42, 43, 44},
{45, 46, 47, 48, 49, 50, 51, 52, 53},
{54, 55, 56, 57, 58, 59, 60, 61, 62},
{63, 64, 65, 66, 67, 68, 69, 70, 71},
{72, 73, 74, 75, 76, 77, 78, 79, 80}};
time = clock();
for (i = 0; i < 100000; i++)
{
for (x = 0; x < 9; x++)
{
for (y = 0; y < 9; y++)
{
matrix[x][y];
}
}
}
time = clock() - time;
std::cout << "Clicks: " << time << std::endl;
std::cout << "Time taken: " << (double) time / CLOCKS_PER_SEC << "s" << std::endl;
}
Program 2 creates a 1D array and also measures how long it takes to access all of its elements 100000 times:
#include <time.h>
#include <iostream>
int main()
{
clock_t time;
int i, j;
int vector[81] = { 0, 1, 2, 3, 4, 5, 6, 7, 8,
9, 10, 11, 12, 13, 14, 15, 16, 17,
18, 19, 20, 21, 22, 23, 24, 25, 26,
27, 28, 29, 30, 31, 32, 33, 34, 35,
36, 37, 38, 39, 40, 41, 42, 43, 44,
45, 46, 47, 48, 49, 50, 51, 52, 53,
54, 55, 56, 57, 58, 59, 60, 61, 62,
63, 64, 65, 66, 67, 68, 69, 70, 71,
72, 73, 74, 75, 76, 77, 78, 79, 80};
time = clock();
for (i = 0; i < 100000; i++)
{
for (j = 0; j < 81; j++)
{
vector[j];
}
}
time = clock() - time;
std::cout << "Clicks: " << time << std::endl;
std::cout << "Time taken: " << (double) time / CLOCKS_PER_SEC << "s" << std::endl;
}
After executing program 1 my output is:
Clicks: 8106
Time taken: 0.008106s
After executing program 2 my output is:
Clicks: 15958
Time taken: 0.015958s
It is my understanding that a 1D array is stored in a continuous block of memory. Likewise the rows of a static 2D array are stored in contiguous blocks of memory. Conversely the rows of a dynamic 2d array might not be stored in contiguous blocks of memory. If this is true then program 2 should be at least similar in speed to program 1 therefore my question is why would program 1 be remarkably faster than program 2?
Here is what I found:
If you actually make use of the value then the run time is almost the same, for example, change matrix[x][y]; to matrix[x][y] += 1; and vector[j]; to vector[j] += 1;
> Clicks: 28519
> Time taken: 0.028519s
and
> Clicks: 29941
> Time taken: 0.029941s
Without the above changes, optimize while compiling, g++ -O3 <filename>.cpp, this results in same time, got the same following output for both programs:
$./a.out
> Clicks: 2
> Time taken: 2e-06s
So, what you are pointing out is compiler optimizations.
The loops are likely to be removed (kind of optimising) by compiler, because
You actually did nothing in loops.
The matrix can be treated as a const array.
program 1 is faster than program 2. ( :< )
To see whether the deletion happens to your code during compiling, you can increase the most outer loop by 100 times, and see whether the time needed for execution is increased significantly (not necessarily by exact 100 times).
If true, you can prevent this kind of optimising by doing some actual works in loop (calculate the sum, and don't forget printing it afterwards) and introduce some "unpredictable" changes to your matrix, for example:
srand(10);
for (int i=0; i<9; ++i) {
matrix[i][i] = rand()%100;
}
And further, compiler may conduct some other optimising to your code, for example, expand your loops, even the address of the element you are visiting (they are no longer calculated at run time), you can prevent this by making the executing times of loops "unpredictable" :
#include <chrono>
#include <iostream>
#include <cstdlib>
int array[100];
int array2[10][10];
int64_t Sum1D(int len) {
int64_t sum = 0;
for (int i=0; i<100000; ++i) {
for (int j=0; j<len; ++j) {
sum += array[j];
}
}
return sum;
}
int64_t Sum2D(int len1, int len2) {
int64_t sum = 0;
for (int i=0; i<100000; ++i) {
for (int j=0; j<len1; ++j) {
for (int k=0; k<len2; ++k)
sum += array2[j][k];
}
}
return sum;
}
int main()
{
for (int i=0; i<100; ++i) {
array[i] = rand();
array2[i%10][i/10] = rand();
}
auto time = std::chrono::steady_clock::now();
//int64_t sum = Sum1D(100);
int64_t sum = Sum2D(10,10);
auto duration = std::chrono::steady_clock::now()-time;
std::cout << sum << "!" << duration.count() << std::endl;
return 0;
}
which finally makes program1 slower than program2. ( :> )

How to use array address to reverse an array?

I understand the array address but this code which I found in a book made me nut.I understand the recursive function too but did not get this one.Here is the code:
int main(){
const int arraySize = 5;
int a[arraySize] = { 32, 27, 64, 18, 95};
cout << "The values in reverse array are:" << endl;
someFunction(a, arraySize);
cout << endl;
cin.get();
return 0;
}
void someFunction(int b[], int size)
{
if (size > 0) {
someFunction(&b[1], size - 1);
cout << b[0] << " ";
}
}
I got this code in a exercise.My question is how it is reversing the array?I will be happy if anyone explain a bit more.thanks
Here is some pseudo-code which shows how the recusive calls to someFunction will be made, and in which order:
someFunction( { 32, 27, 64, 18, 95} , 5)
someFunction( { 27, 64, 18, 95}, 4)
someFunction( { 64, 18, 95}, 3)
someFunction( { 18, 95}, 2)
someFunction( { 95}, 1)
someFunction( { }, 0)
someFunction({ }, 0) will return without doing anything because there is nothing left in the array. Now someFunction will print the first element b[0] of the arrays as it comes out of the recursion, beginning with the array containing only one item {95}:
{ 95 }
{ 18, 95}
{ 64, 18, 95}
{ 27, 64, 18, 95}
{ 32, 27, 64, 18, 95}
So your output will be:
"The values in reverse array are:"
95 18 64 27 32
b[1] is the second element of the array. &b[1] is the address of the second element, so it is just like the original array, but 1 smaller and skipping the first element.
If you print out everything except the first element before you print the first, and do it recursively, the result is it prints out in reverse order.
Note that the actual array has not been reversed. It only gets printed in reverse order. And it's nonsense. A loop is better.

Some Data Unaccounted For When Iterating Over Array

I'm working on a random exercise from my C++ book because I'm "re-learning" C++, but I'm getting some odd output from a program I wrote. I'm fairly certain there are no errors in the logic of the program, but where the sum of the elements in the "scoreCount" array should be 26, the same as the length of the scores array, it is only 20. I can't figure out what happened to the other 6 elements. The description of the exercise is in the code below. Can anyone spot what I might have done wrong?
/* Exercise 09 - 04
Write a program that reads a file consisting of students' test scores
in the range 0-200. It should then determine the number of students having
scores in each of the following ranges: 0-24, 25-49, 50-74, 75-99,
100-124, 125-149, 150-174, and 175-200. Output the score ranges and the
number of students. (Run your program with the following input data:
76, 89, 150, 135, 200, 76, 12, 100, 150, 28, 178, 189, 167, 200, 175,
150, 87, 99, 129, 149, 176, 200, 87, 35, 157, 189.) */
#include <cstdio>
int main(int argc, char ** argv) {
int scores[] = {76, 89, 150, 135, 200, 76, 12, 100, 150, 28, 178, 189,
167, 200, 175, 150, 87, 99, 129, 149, 176, 200, 87,
35, 157, 189};
int size = sizeof(scores) / sizeof(scores[0]);
int scoreCount[] = {0, 0, 0, 0, 0, 0, 0, 0};
printf("Number of Scores: %d\n\n", size);
for(int i = 0; i < size; i++) {
scoreCount[((int)(scores[i]/25))] += 1;
printf("%d - scoreCount Index: %d\n", i, ((int)(scores[i]/25)));
}
printf("\n");
int low = 0;
int high = 24;
size = sizeof(scoreCount) / sizeof(scoreCount[0]);
for(int i = 0; i < size; i++) {
printf("Range %d-%d: %d\n", low, high, scoreCount[i]);
low += 25;
high += 25;
if(high == 199) high = 200;
}
int sum = 0;
for(int i = 0; i < size; i++) {
sum += scoreCount[i];
}
if(sum < 26) printf("\n%d: Wrong number of scores counted.\n", sum);
else printf("\nAll students accounted for.\n");
return 0;
}
Thanks for any help!
Here's proper C++ style. I know the question has already been answered, but here's a bonus:
See it live on http://ideone.com/rBTi42
#include <vector>
#include <map>
#include <iostream>
int main(int argc, char ** argv)
{
const std::vector<int> scores = {76, 89, 150, 135, 200, 76, 12, 100, 150, 28, 178, 189,
167, 200, 175, 150, 87, 99, 129, 149, 176, 200, 87,
35, 157, 189
};
std::map<int, int> scoreCount;
std::cout << "Number of Scores: " << scores.size() << "\n";
for(auto score : scores)
{
scoreCount[score/25] ++;
std::cout << score << " - scoreCount Index: " << score/25 << "\n";
}
for(auto const& slot : scoreCount)
{
auto low = slot.first*25;
auto high = low+24;
std::cout << "Range " << low << "-" << high << ": " << slot.second << "\n";
}
int sum = 0;
for(auto const& slot : scoreCount)
sum += slot.second;
if(sum < 26)
printf("\n%d: Wrong number of scores counted.\n", sum);
else
printf("\nAll students accounted for.\n");
}
scoreCount[((int)(scores[i]/25))] += 1;
This would produce 8 if score[i] is 200. And currently your code does not handle this.
200 / 25 = 8 and
scoreCount[8] does not exist.
You are generating an index out of bounds for scoreCount here:
scoreCount[((int)(scores[i]/25))] += 1;
The valid indexes for scoreCount are from 0 to 7 but with your current scores you will generate indexes up to 8. A solution would be to extend scoreCount by one element or to check if the index is 8 and map it to index 7 since it seems like the problem limits your ranges.
The number of elements should be 9 rather than 8 in the scoreCount array.
As 200/25 will be evaluated to 8 and it results in index out of bound
EDIT:
As suggested by Andrew_CS, the element having value as 200 shoud be added to the last group itself.
scoreCount[(scores[i]/25)==8?7:(scores[i]/25)] += 1;
I ran the code on my machine.
I got 23 out of 26.
The reason for this is that there are 3 values of 200.
When the value is 200 the it will be under 8.
You need to increase the number of elements in the scoreCount array because 200/25 gives 8 and scoreCount[8] does not exists .
200/25 = 8 is out of bounds for scoreCount - only has indexes 0 - 7.
I personally wouldn't increase the number of elements in scoreCount since there are only 8 groups of valid scores. I would instead check for this one case that produces 8 as an index.
for(int i = 0; i < size; i++){
int theIndex = (scores[i]/25);
if(theIndex == 8)
scoreCount[7] += 1;
else
scoreCount[theIndex] += 1;
printf("%d - scoreCount Index: %d\n", i, theIndex;
}