Build Max Heap algorithm won't work - c++

I am trying to build a max heap using the algorithm given in Introduction to Algorithms, and I can't get it to work. Firstly, I'm having some interesting issues with passing arrays between functions. My understanding is that arrays are passed by reference in C++, but after I pass an array and I check the addresses of the argument and the parameter they don't match. When I try to use sizeof() on an array that is a parameter it doesn't return the correct value.
Secondly, the algorithm just doesn't seem to work. It does make some changes to the array, and gets the numbers closer to a heap but still has a ways to go. I've checked the code dozens of times and it seems to be spot on with pseudo code given in my text. What am I missing?
#include <iostream>
#include <ctime>
#define N 10
#define DISPLAY
using namespace std;
// Display an array
void display(double p[]) {
#ifdef DISPLAY
for (int i = 0; i < N; i++) cout << p[i] << " ";
cout << endl;
#endif
}
inline int parent(int i)
{return i/2;}
inline int left(int i)
{return 2*i;}
inline int right(int i)
{return 2*i+1;}
void maxHeapify(double p[], int i)
{
int largest;
int l = left(i);
int r = right(i);
if (l <= N && (p[l] > p[i]))
largest = l;
else
largest = i;
if (r <= N && (p[r] > p[largest]))
largest = r;
if (largest != i)
{
double temp = p[i];
p[i] = p[largest];
p[largest] = temp;
maxHeapify(p, largest);
}
}
void buildMaxHeap(double p[])
{
for (int i=N/2; i>0; i--)
maxHeapify(p, i);
}
int main() {
double a[] = {4,1,3,2,16,9,10,14,8,7};
buildMaxHeap(a);
display(a);
}

I modified your code as below:
#include <iostream>
#include <ctime>
#define N 10
#define DISPLAY
using namespace std;
// Display an array
void display(double p[]) {
#ifdef DISPLAY
for (int i = 0; i < N; i++) cout << p[i] << " ";
cout << endl;
#endif
}
inline int parent(int i)
{return i/2;}
inline int left(int i)
{return 2*i;}
inline int right(int i)
{return 2*i+1;}
void maxHeapify(double p[], int i)
{
int largest;
int l = left(i)-1;
int r = right(i)-1;
i=i-1;
if (l <= N && (p[l] > p[i]))
largest = l;
else
largest = i;
if (r <= N && (p[r] > p[largest]))
largest = r;
if (largest != i)
{
double temp = p[i];
p[i] = p[largest];
p[largest] = temp;
maxHeapify(p, largest+1);
}
}
void buildMaxHeap(double p[])
{
for (int i=N/2; i>0; i--)
maxHeapify(p, i);
}
int main() {
double a[] = {4,1,3,2,16,9,10,14,8,7};
buildMaxHeap(a);
display(a);
}

Related

Why does this quicksort program not give an output?

I am giving an integer array as input to an int array and I am expecting an output of sorted ints.
But there is no output.
I tried to use a recursive quicksort algo that will take an array of ints as input and give out a sorted array as output. I was expecting the sorted array to be shown in the terminal but there was no output.
This is the code
#include <iostream>
#define SIZE 10
using namespace std;
void swap(int* a, int* b)
{
int temp = *a;
*a = *b;
*b = temp;
}
int partition(int* array,int p, int q)
{
int key = array[p];
int i = p;
for(int j = p+1; j <= q; j++ )
{
if(key > array[j])
{
i++;
swap(&array[i],&array[j]);
}
}
swap(&array[i],&array[p]);
return i;
}
void quicksort(int* array,int p,int q)
{
if(p < q)
{
int r = partition(array,p,q);
quicksort(array,p,r-1);
quicksort(array,r,q);
}
}
int main()
{
int unsorted[SIZE] = {6,2,5,-1,11,3,17,-9,1,10};
quicksort(unsorted,0,SIZE-1);
cout << "The sorted array" << endl;
for(int i = 0; i < SIZE; i++)
{
cout << unsorted[i] <<" ";
}
}
The code you pasted enters infinite recursion in the quicksort function. Also, I would recommend using std::vector and pass that by reference instead of using C-style arrays. The std::vector is a more flexible container.
Here is the corrected code https://onlinegdb.com/q4LxWciVC:
#include <iostream>
#define SIZE 10
using namespace std;
void swap(int* a, int* b)
{
int temp = *a;
*a = *b;
*b = temp;
}
int partition(int* array,int p, int q)
{
int i = p-1;
int pivot = array[q]; // make pivot the last element of the array
for (int j{p};j<q;++j)
{
if (array[j] < pivot)
{
i++;
swap(&array[i], &array[j]);
}
}
swap(&array[i+1], &array[q]);
return i+1;
}
void quicksort(int* array,int p,int q)
{
if(p >= q){
return;
}
std::cout<<"\n---------Reached here---------\n";
int r = partition(array,p,q);
quicksort(array, p, r-1);
quicksort(array, r+1, q);
}
int main()
{
int unsorted[SIZE] = {6,2,5,-1,11,3,17,-9,1,10};
quicksort(unsorted,0,SIZE-1);
cout << "The sorted array" << endl;
for(int i = 0; i < SIZE; i++)
{
cout << unsorted[i] <<" ";
}
}
Output:
---------Reached here---------
---------Reached here---------
---------Reached here---------
---------Reached here---------
---------Reached here---------
---------Reached here---------
The sorted array
-9 -1 1 2 3 5 6 10 11 17

Array without a specified size without using vector [duplicate]

This question already has answers here:
How do I use arrays in C++?
(5 answers)
Why aren't variable-length arrays part of the C++ standard?
(10 answers)
Closed 1 year ago.
I am trying to make a program that reads files with numbers and sort the numbers with different algorithms and there is multiple files that are going to be read and each file has a different amount of integers. so what i need to do is read those integers and cast them into a array.
but for some reason in c++ you cant have a array with an undefined size so what is a solution that i can use? And i can't use vectors (school project)
Here is my program
#ifndef SORT_H
#define SORT_H
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
// =============================================================================
// FILE READER
// =============================================================================
void fileReader(string fileName, int arr[]){
ifstream myfile(fileName);
int pos = 0;
string number;
if(myfile.is_open()){
while (getline(myfile, number))
{
arr[pos] = stoi(number);
pos++;
}
}
}
// =============================================================================
// SWAPER
// =============================================================================
void swap(int* a, int* b)
{
int temp = *a;
*a = *b;
*b = temp;
}
// =============================================================================
// QUICKSORT
// =============================================================================
int partition(int arr[], int beg, int end){
int pivot = arr[end];
int index = beg - 1;
for(int j = beg; j < end; j++){
if(arr[j] <= pivot){
index++;
swap(&arr[index], &arr[j]);
}
}
swap(&arr[index+1], &arr[end]);
return (index+1);
}
void quicksortAlgo(int arr[], int beg, int end){
if(beg < end){
int pi = partition(arr, beg, end);
quicksortAlgo(arr, beg, pi-1);
quicksortAlgo(arr, pi+1, end);
}
}
template <typename T>
void quicksort(T arr[], int n)
{
quicksortAlgo(arr, 0, n-1);
for(int x = 0; x < n; x++)
cout << arr[x] << endl;
}
// =============================================================================
// HEAPSORT
// =============================================================================
void heapify(int arr[], int n, int i){
int max = i;
int left = 2*i + 1; // Left side
int right = 2*i + 2; // Right side
cout << "max: " << arr[max] << endl;
// if there is a left child for root and if is
// bigger then root
if(left < n && arr[max] < arr[left]){
max = left;
}
// If there is a right child of root and if is
// bigger then root
if(right < n && arr[max] < arr[right]){
max = right;
}
if(max != i){
swap(&arr[i], &arr[max]);
heapify(arr, n, max);
}
}
void heapsortAlgo(int arr[], int n){
for (int i = n/2 - 1; i >= 0; i--){
heapify(arr, n, i);
}
for (int i = n-1; i >= 0; i--){
swap(&arr[0], &arr[i]);
heapify(arr, i, 0);
}
}
template <typename T>
void heapsort(T arr[], int n)
{
heapsortAlgo(arr, n);
for (int i = 0; i < n; i++){
cout << arr[i] << " ";
}
}
// =============================================================================
// INTSERTIONSORT
// =============================================================================
template <typename T>
void insertionsort(T arr[], int n)
{
int holePostion;
int valueToInsert;
for (int i = 1; i < n; i++){
valueToInsert = arr[i];
holePostion = i;
while(holePostion > 0 && arr[holePostion-1] > valueToInsert){
arr[holePostion] = arr[holePostion - 1];
holePostion = holePostion - 1;
}
arr[holePostion] = valueToInsert;
}
}
int main(){
string filedest;
string arrSize;
cout << "enter file destenation: ";
cin >> filedest;
int arr[];
int n = sizeof(arr) / sizeof(arr[0]);
fileReader(filedest, arr);
quicksort(arr, n);
return 0;
}
#endif
As #MikeCAT mentioned, you can use std::vector<T>.
You can add push elements at the back of the vector by std::vector<T>::push_back().
Alternatively, you can also resize the vector array by using std::vector<T>::resize() and then add elements at a specific location similar to what you are doing in your fileReader() function. You can also insert elements at a specific location by calling std::vector<T>::insert()
.
Do have a look at the time complexities if you have a time constraint in your programming task.

C++ Turning arrays into functions?

I have been attempting this for hours to no avail, as you can see in my code I have separate functions, they were all together in main, but I am required to turn each into a separate function. However when I try anything I get errors, even when I try to pass parameters. Can someone point me in the right direction?
#include <iostream>
#include <cstdlib>
#include <ctime>
void printarray();
void average();
void largestnumber();
using namespace std;
int main()
{
printarray();
average();
largestnumber();
}
void printarray() {
srand(time(0));
int n[10], tot = 0;
for (int i = 0; i < 10; i++)
{
n[i] = (1 + rand() % 100);
cout << n[i] << endl;
}
}
void average() {
int j, tot = 0, n[10];
for (j = 0; j < 10; j++)
{
tot += n[j];
}
cout << "The average of the numbers in the array are " << tot / j << endl;
}
void largestnumber() {
int w = 1, int n[10];
int temp = n[0];
while (w < 10)
{
if (temp < n[w])
temp = n[w];
w++;
}
cout << "The largest number in the array is " << temp << endl;
}
The array you are working with needs to be passed in to each function, so the same array is used everywhere. It is a good idea to pass the size as well, just for flexibility reasons.
Now your functions pretty much work as you wrote them.
#include <iostream>
#include <cstdlib>
#include <ctime>
void printarray(int n[], size_t size);
void average(int n[], size_t size);
void largestnumber(int n[], size_t size);
using namespace std;
int main()
{
const size_t arr_size = 10;
int n[arr_size];
printarray(n, arr_size);
average(n, arr_size);
largestnumber(n, arr_size);
}
void printarray(int n[], size_t size) {
srand((unsigned int)time(0));
int tot = 0;
for (size_t i = 0; i < size; i++)
{
n[i] = (1 + rand() % 100);
cout << n[i] << endl;
}
}
void average(int n[], size_t size) {
size_t j;
int tot = 0;
for (j = 0; j < size; j++)
{
tot += n[j];
}
cout << "The average of the numbers in the array are " << tot / j << endl;
}
void largestnumber(int n[], size_t size) {
size_t w = 1;
int temp = n[0];
while (w < size)
{
if (temp < n[w])
temp = n[w];
w++;
}
cout << "The largest number in the array is " << temp << endl;
}
One simple improvement is to break the printarray out into an initarray function that fills the array and printarray that prints the content.
It would also be a good idea to do some checking for things like an empty array (functions assume n[0] exists, for instance).
The next obvious step is to put all this in a class. Also, if you are allowed to, the c array should be replaced with a vector, as that does a great job of keeping all the resource information together.

Can't understand why my program throws error

My code is in
#include <iostream>
#include <string>
#include <algorithm>
#include <climits>
#include <vector>
#include <cmath>
using namespace std;
struct State {
int v;
const State *rest;
void dump() const {
if(rest) {
cout << ' ' << v;
rest->dump();
} else {
cout << endl;
}
}
State() : v(0), rest(0) {}
State(int _v, const State &_rest) : v(_v), rest(&_rest) {}
};
void ss(int *ip, int *end, int target, const State &state) {
if(target < 0) return; // assuming we don't allow any negatives
if(ip==end && target==0) {
state.dump();
return;
}
if(ip==end)
return;
{ // without the first one
ss(ip+1, end, target, state);
}
{ // with the first one
int first = *ip;
ss(ip+1, end, target-first, State(first, state));
}
}
vector<int> get_primes(int N) {
int size = floor(0.5 * (N - 3)) + 1;
vector<int> primes;
primes.push_back(2);
vector<bool> is_prime(size, true);
for(long i = 0; i < size; ++i) {
if(is_prime[i]) {
int p = (i << 1) + 3;
primes.push_back(p);
// sieving from p^2, whose index is 2i^2 + 6i + 3
for (long j = ((i * i) << 1) + 6 * i + 3; j < size; j += p) {
is_prime[j] = false;
}
}
}
}
int main() {
int N;
cin >> N;
vector<int> primes = get_primes(N);
int a[primes.size()];
for (int i = 0; i < primes.size(); ++i) {
a[i] = primes[i];
}
int * start = &a[0];
int * end = start + sizeof(a) / sizeof(a[0]);
ss(start, end, N, State());
}
It takes one input N (int), and gets the vector of all prime numbers smaller than N.
Then, it finds the number of unique sets from the vector that adds up to N.
The get_primes(N) works, but the other one doesn't.
I borrowed the other code from
How to find all matching numbers, that sums to 'N' in a given array
Please help me.. I just want the number of unique sets.
You've forgotten to return primes; at the end of your get_primes() function.
I'm guessing the problem is:
vector<int> get_primes(int N) {
// ...
return primes; // missing this line
}
As-is, you're just writing some junk here:
vector<int> primes = get_primes(N);
it's undefined behavior - which in this case manifests itself as crashing.

Merge and QuickSort - stack overloaded

Helo everyone. :)
I have to write a program where I have 4 types of sorting: bubble-, insertion-, merge- i quick-sort.
Program has to sort points x,y in array of structures (random) by amount of total of their coordinates //e.g.: (1,3) is less than (0,6) because 1+3<0+6//. It saves sorted ones in this same array and also in txt file with time of sorting by each B,I,M,Q-sort.
Code from Merge and MergeSort:
void Merge(Structure *tab, int A, int sr, int Z)
{
Structure *tmp = new Structure[Z];
int i;
for (i = A; i <= Z; ++i)
{
tmp[i] = tab[i];
}
i = A;
int j = sr + 1;
int q = A;
while (i <= sr && j <= Z)
{
if (Compare(tab, i, j)) //'Compare' tells if total of coordinates from tab[i] is bigger than total from tab[j]
{
tab[q] = tmp[i];
++j;
}
else
{
tab[q] = tmp[j];
++i;
}
++q;
}
if(i <= sr)
{
while (i <= sr)
{
tab[q] = tmp[i];
++i;
++q;
}
}
else
{
while(j <= Z)
{
tab[q] = tmp[j];
++j;
++q;
}
}
delete[] tmp;
}
void MergeSort(Structure *tab, int A, int Z)
{
int sr = (A + Z)/2;
if(A < Z)
{
MergeSort(tab, A, sr);
MergeSort(tab, sr + 1, Z);
Merge(tab, A, sr, Z);
}
}
And to QuickSort:
int DivideQS(Structure *tab, int A, int Z)
{
Structure tmp;
Structure pivot = tab[A]; // first el. for pivot (A=0)
int i = A, j = Z; //indexes in array
while (true)
{
while (Compare(tab, j, A))
j--;
while (!Compare(tab, i, A)) // until elements are lower than pivot, that's this '!' for
i++;
if (i < j) // swap when i < j
{
tmp = tab[i];
tab[i] = tab[j];
tab[j] = tmp;
i++;
j--;
}
else
return j;
}
}
void QuickSort(Structure *tab, int A, int Z)
{
int dziel;
if (A < Z)
{
dziel = DivideQS(tab, A, Z);
QuickSort(tab, A, dziel);
QuickSort(tab, dziel+1, Z);
}
}
My problem is a stack. No matter how big I make this, it still goes overloaded. I can't manage this problem. I don't know if that's because of mistake in code or it's somewhere else. Bubble and Insertion work impeccable.
I was looking for solving on many sites, in my language and foreign ones (I'm Pole), and modificating code in so many ways but still have no clue what to do.
Help me, please.
===================================
How could I be so blind! Thank you #user3187084. :D
But I think I went from bad to worse. Now I've received new error message:
Windows has triggered a breakpoint in Projekt_AiSD.exe.
This may be due to a corruption of the heap, which indicates a bug in Projekt_AiSD.exe or any >of the DLLs it has loaded.
This may also be due to the user pressing F12 while Projekt_AiSD.exe has focus.
The output window may have more diagnostic information.
And after that this showed to me: http://i40.tinypic.com/314qyl5.png
And this is code for checking:
#include <ctime>
#include <cstdlib>
#include <cstdio>
#include <Windows.h>
#include <string>
#include <fstream>
#include <sstream>
using namespace std;
struct Structure
{
int x;
int y;
};
bool Compare(Structure *tab, int i, int j)
{
if ( (tab[i].x + tab[i].y) > (tab[j].x + tab[j].y))
return true;
return false;
}
void LosujWspolrzedne(Structure* tab, int K)
{
srand(time(NULL));
for (int i = 0; i < K; i++)
{
tab[i].x = rand()%21;
tab[i].y = rand()%21;
}
//return;
}
void Save (Structure *tab, int K, string NazwaPliku)
{
ofstream zap(NazwaPliku);
for (int i = 0; i < K; i++)
{
zap << tab[i].x << ' ' << tab[i].y << endl;
}
zap.close();
}
void Load (Structure *tab, int K, string NazwaPliku)
{
ifstream wcz(NazwaPliku);
if (!wcz)
{
cout << "Can't open the file!!!" << endl;
exit(1);
}
for (int i = 0; i < K; ++i)
{
wcz >> tab[i].x >> tab[i].y;
}
wcz.close();
}
void Time(long long a, long long b, string NazwaPliku)
{
ofstream czas(NazwaPliku);
if (!czas)
{
cout << "Can't open the file!!!" << endl;
}
czas << (b - a) << " ms" << endl;
czas.close();
}
void CopyArray(Structure *tab, Structure *tab1, int K)
{
for (int i = 0 ; i < K ; i++)
{
tab1[i].x = tab[i].x;
tab1[i].y = tab[i].y;
}
}
void Call_MS(Structure *tab, int A, int K)
{
Load(tab, K, "1k.txt");
long long startTime = GetTickCount64();
MergeSort(tab, A, K-1);
long long endTime = GetTickCount64();
cout << (endTime - startTime) << "ms dla MergeSort" << endl;
Save(tab, K, "WartLos_MS_1k.txt");
Time(startTime, endTime, "WartLos_MS_1k_czas.txt");
}
void Call_QS(Structure *tab, int A, int K)
{
Load(tab, K, "1k.txt");
long long startTime = GetTickCount64();
QuickSort(tab, A, K-1);
long long endTime = GetTickCount64();
cout << (endTime - startTime) << "ms dla QuickSort" << endl;
Save(tab, K, "WartLos_QS_1k.txt");
Time(startTime, endTime, "WartLos_QS_1k_czas.txt");
}
const int MAX_EL = 30;
int _tmain(int argc, _TCHAR* argv[])
{
Structure *punkt = new Structure[MAX_EL];
void LosujWspolrzedne(Structure *punkt, int MAX_EL);
Structure *punkt1= new Structure[MAX_EL];
void CopyArray(Structure *punkt, Structure *punkt1, int MAX_EL);
delete[] punkt;
Save(punkt1, MAX_EL, "1k.txt");
cout<<"Start:"<<endl;
Call_MS(punkt1, 0, MAX_EL);
Call_QS(punkt1, 0, MAX_EL);
delete[] punkt1;
return 0;
}
You have MergeSort(tab, A, Z) inside MergeSort, so you always call itself with exact arguments
It should be MergeSort(tab, A, st)
You are using MergeSort(tab,A,Z) which call the same function again with same arguments which is will go one for infinite recursion hence error. You should only pass MergeSort(tab,A,sr) which will reduce your problem to half size.