Merge and QuickSort - stack overloaded - c++

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.

Related

Blank output screen when I run this searching algorithm

I have been practicing median search algorithm, and this is what I wrote-
#include <iostream>
#include <stdlib.h>
using namespace std;
int S1[10] = { 0 };
int S2[1] = { 0 };
int S3[10] = { 0 };
int mediansearch(int A[], int k, int size)
{
int ran = rand() % size;
int i = 0;
int a = 0;
int b = 0;
int c = 0;
for (i = 0; i < size; i++)
{
if (A[ran] > A[i])
{
S1[a] = A[i];
a++;
}
else if (A[ran] == A[i])
{
S2[b] = A[i];
b++;
}
else
{
S3[c] = A[i];
c++;
}
}
if (a <= k)
{
return mediansearch(S1, k, a);
}
else if (a + b <= k)
{
return A[ran];
}
else
{
return mediansearch(S3, k - a - b, c);
}
}
int main()
{
int arr[] = { 6, 5, 4, 8, 99, 74, 23 };
int n = sizeof(arr) / sizeof(arr[0]);
int x = mediansearch(arr, 5, n);
cout << "5th smallest is:" << x << endl;
}
And I have been getting output as-
Process returned -1073741676 (0xC0000094) execution time : 1.704 s
So, what am I doing wrong? Any kind of help will be appreciated.
There are a few issues with this code, the first one being the naming of variables.
I suggest you choose more significative names in the future, because good naming is fundamental when someone else has to understand your code and your ideas.
Another thing is that the arguments of are in a counterintuitive order because the pair related to the array are separated by the index you want to look for.
I'd write int mediansearch(int A[], int size, int k)
Here the comparisons are reversed, k should be less than rather than greater than equal a
if (a <= k) // (k < a)
{
return mediansearch(S1, k, a);
}
else if (a + b <= k) // (k < a + b)
{
return A[ran];
}
else
{
return mediansearch(S3, k - a - b, c);
}
The other thing is that you're sharing S1, S2, and S3 among all the recursive calls and that causes some error that I wasn't able to identify, maybe someone commenting will help me out.
However, I suggest you read this article that explains in detail the procedure you're trying to implement: https://rcoh.me/posts/linear-time-median-finding/
It's python, but it can be easily ported to C/C++, and in fact that's what I did.
#include <iostream>
#include <stdlib.h>
#include <assert.h>
#include <time.h>
using namespace std;
int medianSearch(int A[], int size, int k)
{
int *lows = (int *)calloc(size, sizeof(int));
int lowsLen = 0;
int *highs = (int *)calloc(size, sizeof(int));
int highsLen = 0;
int *pivots = (int *)calloc(size, sizeof(int));
int pivotsLen = 0;
int median;
int pivot;
int i;
if (size == 1)
return A[0];
// Other ways of randomly picking a pivot
// pivot = 0;
// pivot = size-1;
// pivot = size/2;
assert(size > 0);
pivot = rand() % size;
for (i = 0; i < size; ++i)
{
if (A[i] < A[pivot])
{
lows[lowsLen] = A[i];
lowsLen++;
}
else if (A[i] > A[pivot])
{
highs[highsLen] = A[i];
highsLen++;
}
else
{
pivots[pivotsLen] = A[i];
pivotsLen++;
}
}
if (k < lowsLen)
median = medianSearch(lows, lowsLen, k);
else if (k < lowsLen + pivotsLen)
median = A[pivot];
else
median = medianSearch(highs, highsLen, k - lowsLen - pivotsLen);
free(lows);
free(highs);
free(pivots);
return median;
}
int compare(const void *a, const void *b)
{
return ( *(int *)a - *(int *)b );
}
int medianSorted(int A[], int size, int k)
{
qsort(A, size, sizeof(int), compare);
return A[k];
}
#define N 1000
int main()
{
int arr[N];
int brr[N];
int n = sizeof(arr) / sizeof(arr[0]);
int k = 200;
int x;
int y;
for (int i = 0; i < n; ++i)
arr[i] = brr[i] = rand();
x = medianSearch(arr, n, (k-1)%n);
y = medianSorted(brr, n, (k-1)%n);
string suffix;
switch (k % 10)
{
case 1: suffix = "st"; break;
case 2: suffix = "nd"; break;
case 3: suffix = "rd"; break;
case 4:
case 5:
case 6:
case 7:
case 8:
case 9:
case 0: suffix = "th"; break;
}
cout << k << suffix << " smallest is: " << x << endl;
cout << k << suffix << " smallest is: " << y << endl;
}
https://onlinegdb.com/HJc2V6Lbu

Merge Sort C++ Incorrectly Sorting

I'm writing a program that will do 5 different sorting functions and compare times across them. I'm outputting the 1000th element of each array to see if it's sorted correctly, all of my other sorts except merge sort are producing the correct number. Merge sort is close but off, it is within an element or two of getting the correct answer (outputting 25011 rather than 25034 for the 1000th element.) Here is the code for my merge sort:
//Zach Heesaker. CS3. Project 4
#include <iostream>
#include <fstream>
#include <string>
#include <iomanip>
#include <stdio.h>
#include <ctime>
#include <cstdio>
#include <time.h>
#include <stdint.h>
#include<list>
#include<cmath>
using namespace std;
const int n = 10000;
int numswaps, numcompares;
void swap(int& a, int& b);
void print(int arr[], int n, ofstream& outf, double time);
void read(int arr[], int size);
void mergepass(int arr[], int y[], int& n, int& L);
void mergeSort(int arr[], int n);
void merge(int arr[], int y[], int L, int m, int n);
int main()
{
int numsorts = 5;
string whichsort;
ofstream outf("output.ot");
int arr[n + 1];
clock_t start, end;
double time;
outf << "Sort Name: " << setw(5) << " " << "1000th Element: " << setw(1) << " " << "Number of Moves: " << setw(1) << " " << "Time taken: " << endl;
read(arr, n);
numcompares = 0;
numswaps = 0;
start = clock();
mergeSort(arr, n);
end = clock();
time = double(end - start) / double(CLOCKS_PER_SEC);
}
void mergeSort(int arr[], int size)
{
int L = 1;
int y[n + 1];
while (L < n)
{
mergepass(arr, y, size, L);
L = 2 * L;
mergepass(y, arr, size, L);
L = 2 * L;
}
}
void merge(int arr[], int y[], int L, int m, int n)
{
int i, j, k, t;
i = L;
k = L;
j = m + 1;
while ((i <= m) && (j <= n))
{
numcompares++;
if (arr[i] <= arr[j])
{
numswaps++;
y[k++] = arr[i++];
}
else
{
numswaps++;
y[k++] = arr[j++];
}
}
if (i > m)
{
for (t = j; t <= n; t++)
{
numswaps++;
y[k + t - j] = arr[t];
}
}
else
{
for (t = i; t <= m; t++)
{
numswaps++;
y[k + t - i] = arr[t];
}
}
}
void mergepass(int arr[], int y[], int& n, int& L)
{
int i, t;
i = 1;
while (i <= n - 2 * L + 1)
{
merge(arr, y, i, i + L - 1, i + 2 * L - 1);
i = i + 2 * L;
}
if ((i + L - 1) < n)
{
merge(arr, y, i, i + L - 1, n);
}
else
{
for (t = i; t <= n; t++)
{
numswaps++;
y[t] = arr[t];
}
}
}
void swap(int& a, int& b)
{
int temp;
temp = a;
a = b;
b = temp;
numswaps += 3;
}
void print(int arr[], int n, ofstream& outf, double time)
{
outf << left << setw(6) << " " << left << arr[1000] << setw(12) << " " << left << numswaps << setw(10) << " " << left << "\t" << time << endl;
}
void read(int arr[], int size)
{
ifstream ifs("input.txt");
int i = 0;
while (!ifs.eof())
{
ifs >> arr[i];
i++;
}
}
int merge(int arr[], int left, int right)
{
int pivot = arr[right];
int k = (left - 1);
for (int j = left; j <= right - 1; j++)
{
numcompares++;
if (arr[j] < pivot)
{
k++;
swap(arr[k], arr[j]);
}
}
swap(arr[k + 1], arr[right]);
return (k + 1);
}
Any ideas as to what is going wrong in here? Thank you.

Arrays aren't behaving as I'm expecting

Pointers are still a little confusing to me. I want the split function to copy negative elements of an array into a new array, and positive elements to be copied into another new array. A different function prints the variables. I've included that function but I don't think it is the problem. When the arrays are printed, all elements are 0:
Enter number of elements: 5
Enter list:1 -1 2 -2 3
Negative elements:
0 0
Non-Negative elements:
0 0 0
I assume that the problem is that in the split function below i need to pass the parameters differently. I've tried using '*' and '**' (no quotes) for passing the parameters but I get error messages, I may have done so incorrectly.
void split(int alpha[], int bravo[], int charlie[], int aSize, int bSize, int cSize) {
int a = 0;
int b = 0;
for (int i = 0; i < aSize; ++i) {
if (alpha[i] < 0) {
alpha[i] = bravo[a];
++a;
}
else {
alpha[i] = charlie[b];
++b;
}
}
if (a + b != aSize) {
cout << "SOMETHING HAS GONE HORRIBLY WRONG!";
exit(0);
}
}
my main function (all arrays are required to be pointers):
int num_elements;
cin >> num_elements;
int * arr1 = new int[num_elements];
int x;
cout << "Enter list:";
for (int i = 0; i < num_elements; ++i) {
cin >> x;
arr1[i] = x;
}
int y = 0;
int z = 0;
count(arr1, num_elements, y, z);
int * negs = new int [y];
int * nonNegs = new int[z];
split(arr1, negs, nonNegs, num_elements, y, z);
cout << "Negative elements:" << endl;
print_array(negs, y);
cout << endl;
cout << "Non-Negative elements:" << endl;
print_array(nonNegs, z);
cout << endl;
All functions:
void count(int A[], int size, int & negatives, int & nonNegatives) {
for (int i = 0; i < size; ++i) {
if (A[i] < 0) {
++negatives;
}
if (A[i] >= 0) {
++nonNegatives;
}
}
}
void split(int alpha[], int bravo[], int charlie[], int aSize, int bSize, int cSize) {
int a = 0;
int b = 0;
for (int i = 0; i < aSize; ++i) {
if (alpha[i] < 0) {
alpha[i] = bravo[a];
++a;
}
else {
alpha[i] = charlie[b];
++b;
}
}
if (a + b != aSize) {
cout << "SOMETHING HAS GONE HORRIBLY WRONG!";
exit(0);
}
}
void print_array(int A[], int size) {
for (int i = 0; i < size; ++i) {
cout << A[i] << " ";
}
}
All help is appreciated.
EDIT: I apologize for my unclear question, I was wondering how to get my arrays to behave as I want them to.
Array is behaving correctly as per instruction :), you are doing minor mistake (may be overlook) in split function. I have commented out the statement and given reason of problem, please correct those two line of code, rest is fine.
void split(int alpha[], int bravo[], int charlie[], int aSize, int bSize, int cSize) {
int a = 0;
int b = 0;
for (int i = 0; i < aSize; ++i) {
if (alpha[i] < 0) {
//alpha[i] = bravo[a];// here alpha is your source array, don't overwrite it
bravo[a] = alpha[i];
++a;
}
else {
//alpha[i] = charlie[b];// here alpha is your source array, don't overwrite it
charlie[b] = alpha[i];
++b;
}
}
if (a + b != aSize) {
cout << "SOMETHING HAS GONE HORRIBLY WRONG!";
exit(0);
}
}

Calling function from one class in another in C++

So, I am writing a program in C++ that has a function in the Sort class that I wish to call in the Main class. The function has several data members used that are present in that class, that are not present in the Main class and I keep getting a C2660 error, that "Function does not take 0 arguments". Is there a way (short of writing a bunch of getters and setters) to resolve this?
#include "Sort.h"
#include "Timer.h"
using namespace std;
int main
{
Sort *sort = new Sort();
Timer ti;
sort->SetRandomSeed(12345);
sort->InitArray();
cout << "starting InsertionSort" << endl;
ti.Start();
sort->InsertionSort();
ti.End();
cout << "Insertion sort duration: " << ti.DurationInMilliSeconds() << "ms" << endl;
//sort->InitList();
//cout << "starting InsertionSortList()" << endl;
//ti.Start();
//sort->InsertionSortList();
//ti.End();
//cout << "Insertion sort list duration: " << ti.DurationInMilliSeconds() << "ms" << endl;
sort->InitArray();
cout << "starting SelectionSort" << endl;
ti.Start();
sort->SelectionSort();
ti.End();
cout << "SelectionSort duration: " << ti.DurationInMilliSeconds() << "ms" << endl;
sort->InitArray();
cout << "starting MergeSort" << endl;
ti.Start();
sort->MergeSort();
ti.End();
cout << "MergeSort duration: " << ti.DurationInMilliSeconds() << "ms" << endl;
sort->InitArray();
cout << "starting QuickSort" << endl;
ti.Start();
sort->QuickSort();
ti.End();
cout << "QuickSort duration: " << ti.DurationInMilliSeconds() << "ms" << endl;
sort->InitVector();
cout << "starting std::sort() of Vector<int>" << endl;
ti.Start();
sort->VectorSort();
ti.End();
cout << "std::sort() duration: " << ti.DurationInNanoSeconds() << "ns" << endl;
delete sort;
cout << endl <<"Press [Enter] key to exit";
getchar();
}
Sort.cpp
//const int for array
int num = 10000000;
int val = 10000;
//array
int *tmpArray, *qArr, *insArr, *selArr, *mergArr = NULL;
int low, high;
//duration for timer
int duration = 0;
Sort::Sort()
{
}
Sort::~Sort()
{
}
void Sort::InitArray()
{
//int for index
int i = 0;
tmpArray = new int[num];
qArr = new int[num];
insArr = new int[num];
selArr = new int[num];
mergArr = new int[num];
//fill temp array with sequential numbers
for (int i = 0; i < num; i++)
{
tmpArray[i] = 1 + rand() % val;
}
for (i = 0; i < num; i++)
{
qArr[i] = tmpArray[i];
insArr[i] = tmpArray[i];
selArr[i] = tmpArray[i];
mergArr[i] = tmpArray[i];
}
low = qArr[0];
high = qArr[num - 1];
int n = sizeof(tmpArray) / sizeof(tmpArray[0]);
}
void Sort::InitVector()
{
vector<int> v(num);
std::generate(v.begin(), v.end(), std::rand);
}
void Sort::InitList()
{
// A set to store values
std::list<int> l;
// Loop until we get 50 unique random values
while (l.size() < num)
{
l.push_back(1 + rand() % val);
}
for (int n : l) {
std::cout << n << '\n';
}
}
//setting seed
void Sort::SetRandomSeed(unsigned int seed)
{
seed = rand();
}
void Sort::InsertionSort()
{
int i, key, j;
for (i = 1; i < n; i++)
{
key = insArr[i];
j = i - 1;
/* Move elements of arr[0..i-1], that are
greater than key, to one position ahead
of their current position */
while (j >= 0 && insArr[j] > key)
{
insArr[j + 1] = insArr[j];
j = j - 1;
}
insArr[j + 1] = key;
}
delete[] insArr;
insArr = NULL;
}
int Sort::partition(int qArr[], int low, int high)
{
int pivot = qArr[high]; // pivot
int i = (low - 1); // Index of smaller element
for (int j = low; j <= high - 1; j++)
{
// If current element is smaller than or
// equal to pivot
if (qArr[j] <= pivot)
{
i++; // increment index of smaller element
swap(&qArr[i], &qArr[j]);
}
}
swap(&qArr[i + 1], &qArr[high]);
return (i + 1);
}
void Sort::QuickSort(int qArr[], int low, int high)
{
if (low < high)
{
/* pi is partitioning index, arr[p] is now
at right place */
int pi = partition(qArr, low, high);
// Separately sort elements before
// partition and after partition
QuickSort(qArr, low, pi - 1);
QuickSort(qArr, pi + 1, high);
}
delete[] qArr;
qArr = NULL;
}
void Sort::SelectionSort()
{
int i, j, min_idx;
// One by one move boundary of unsorted subarray
for (i = 0; i < n - 1; i++)
{
// Find the minimum element in unsorted array
min_idx = i;
for (j = i + 1; j < n; j++)
if (selArr[j] < selArr[min_idx])
min_idx = j;
// Swap the found minimum element with the first element
swap(&selArr[min_idx], &selArr[i]);
}
delete[] selArr;
selArr = NULL;
}
void Sort::swap(int *xp, int *yp)
{
int temp = *xp;
*xp = *yp;
*yp = temp;
}
void Sort::VectorSort()
{
std::sort(v.begin(), v.end());
}
/* l is for left index and r is right index of the
sub-array of arr to be sorted */
void Sort::merge(int mergArr[], int l, int m, int r)
{
int i, j, k;
int n1 = m - l + 1;
int n2 = r - m;
int* L;
int* R;
/* create temp arrays */
L = new int[n1];
R = new int[n2];
/* Copy data to temp arrays L[] and R[] */
for (i = 0; i < n1; i++)
L[i] = mergArr[l + i];
for (j = 0; j < n2; j++)
R[j] = mergArr[m + 1 + j];
/* Merge the temp arrays back into arr[l..r]*/
i = 0; // Initial index of first subarray
j = 0; // Initial index of second subarray
k = l; // Initial index of merged subarray
while (i < n1 && j < n2)
{
if (L[i] <= R[j])
{
mergArr[k] = L[i];
i++;
}
else
{
mergArr[k] = R[j];
j++;
}
k++;
}
/* Copy the remaining elements of L[], if there
are any */
while (i < n1)
{
mergArr[k] = L[i];
i++;
k++;
}
/* Copy the remaining elements of R[], if there
are any */
while (j < n2)
{
mergArr[k] = R[j];
j++;
k++;
}
}
void Sort::MergeSort(int mergArr[], int l, int r)
{
if (l < r)
{
// Same as (l+r)/2, but avoids overflow for
// large l and h
int m = l + (r - l) / 2;
// Sort first and second halves
MergeSort(mergArr, l, m);
MergeSort(mergArr, m + 1, r);
merge(mergArr, l, m, r);
}
delete[] mergArr;
mergArr = NULL;
}
Sort.h
#include <iomanip>
#include <fstream>
#include <string>
#include <queue>
#include <stack>
#include <vector>
#include<iostream>
#include<cstdio>
#include<sstream>
#include<algorithm>
#include<list>
using namespace std;
#pragma once
class Sort
{
public:
Sort();
~Sort();
void InitArray();
void InitVector();
void InitList();
void SetRandomSeed(unsigned int seed);
int n, right, left, l, r, m;
vector<int> v;
void InsertionSort();
int partition(int qArr[], int low, int high);
void QuickSort(int qArr[], int low, int high);
void swap(int * xp, int * yp);
void VectorSort();
void MergeSort(int arr[], int l, int r);
void merge(int arr[], int l, int m, int r);
void SelectionSort();
};
Ignoring the Timer class (those are all good) here is the rest of the code. The C2660 errors are shown for the sort->MergeSort() and sort->QuickSort() calls in main.
I resolved the issues myself. I created helper functions in the Sort class that have no arguments and call the functions themselves to use in the main. Helper Functions shown below.
Sort.cpp
//method for Main to run to prevent C2660 errors
void Sort::mergeHelper()
{
MergeSort(mergArr, l, r);//call merge sort method
}
//method for Main to run to prevent C2660 errors
void Sort::quickHelper()
{
QuickSort(qArr, low, high);//call quick sort method
}
int Main
{
sort->quickHelper();
sort->mergeHelper();
}

Why is my code in C++ so much slower than my code in C [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question appears to be off-topic because it lacks sufficient information to diagnose the problem. Describe your problem in more detail or include a minimal example in the question itself.
Closed 8 years ago.
Improve this question
So far, I wrote my code in C (performance is of utmost importance). However, I would like to start writing my algorithms in a generic way. So, I decided to try out C++. I took a simple code in C and translated it into C++ with templates. To my disappointment, the C++ code runs 2.5 times slower. (the C code is compiled with gcc -O3; the C++ code is compiled with g++ -O3)
Am I doing something wrong in C++? Why is there such a performance hit?
Here is the C code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
static int df_output = 0;
int nCalls = 0;
typedef struct {
int *pancakes;
int n;
} STATE;
STATE **solution;
void shuffle(STATE *s) {
int i;
for (i = 0; i < s->n; i++) {
int i1 = rand() % s->n;
int i2 = rand() % s->n;
int temp = s->pancakes[i1];
s->pancakes[i1] = s->pancakes[i2];
s->pancakes[i2] = temp;
}
}
STATE *copyState(STATE *s) {
STATE *res = malloc(sizeof(STATE));
res->n = s->n;
res->pancakes = (int *)malloc(res->n * sizeof(int));
memcpy(res->pancakes, s->pancakes, res->n * sizeof(int));
return res;
}
// reverse n pancakes
void makeMove(STATE *s, int n) {
int i;
for (i = 0; i < n/2; i++) {
int temp = s->pancakes[i];
s->pancakes[i] = s->pancakes[n - 1 - i];
s->pancakes[n - 1 - i]=temp;
}
}
void printState(STATE *s) {
int i;
printf("[");
for (i = 0; i < s->n; i++) {
printf("%d", s->pancakes[i]);
if (i < s->n - 1)
printf(", ");
}
printf("]");
}
int heuristic(STATE *s) {
int i, res = 0;
nCalls++;
for (i = 1; i < s->n; i++)
if (abs(s->pancakes[i]-s->pancakes[i-1])>1)
res++;
if (s->pancakes[0] != 0) res++;
return res;
}
void tabs(int g) {
int i;
for (i = 0; i < g; i++) printf("\t");
}
int df(STATE *s, int g, int left) {
int h = heuristic(s), i;
if (g == 0) printf("Thereshold: %d\n", left);
if (df_output) {
tabs(g);
printf("g=%d,left=%d ", g, left); printState(s); printf("\n");}
if (h == 0) {
assert(left == 0);
solution = (STATE **)malloc((g+1) * sizeof(STATE *));
solution[g] = copyState(s);
return 1;
}
if (left == 0)
return 0;
for (i = 2; i <= s->n; i++) {
makeMove(s, i);
if (df(s, g+1, left-1)) {
makeMove(s, i);
solution[g] = copyState(s);
return 1;
}
makeMove(s, i);
}
return 0;
}
void ida(STATE *s) {
int threshold = 0, i;
while (!df(s, 0, threshold)) threshold++;
for (i = 0; i <= threshold; i++) {
printf("%d. ", i);
printState(solution[i]);
printf("\n");
//if (i < threshold - 1) printf("->");
}
}
int main(int argc, char **argv) {
STATE *s = (STATE *)malloc(sizeof(STATE));
int i, n;
int myInstance[] = {0,5,4,7,2,6,1,3};
s->n = 8;
s->pancakes = myInstance;
printState(s); printf("\n");
ida(s);
printf("%d calls to heuristic()", nCalls);
return 0;
}
Here is the C++ code:
#include <iostream>
#include "stdlib.h"
#include "string.h"
#include "assert.h"
using namespace std;
static int df_output = 0;
int nCalls = 0;
class PancakeState {
public:
int *pancakes;
int n;
PancakeState *copyState();
void printState();
};
PancakeState *PancakeState::copyState() {
PancakeState *res = new PancakeState();
res->n = this->n;
res->pancakes = (int *)malloc(this->n * sizeof(int));
memcpy(res->pancakes, this->pancakes,
this->n * sizeof(int));
return res;
}
void PancakeState::printState() {
int i;
cout << "[";
for (i = 0; i < this->n; i++) {
cout << this->pancakes[i];
if (i < this->n - 1)
cout << ", ";
}
cout << "]";
}
class PancakeMove {
public:
PancakeMove(int n) {this->n = n;}
int n;
};
class Pancake {
public:
int heuristic (PancakeState &);
int bf(PancakeState &);
PancakeMove *getMove(int);
void makeMove(PancakeState &, PancakeMove &);
void unmakeMove(PancakeState &, PancakeMove &);
};
int Pancake::bf(PancakeState &s) {
return s.n - 1;
}
PancakeMove *Pancake::getMove(int i) {
return new PancakeMove(i + 2);
}
// reverse n pancakes
void Pancake::makeMove(PancakeState &s, PancakeMove &m) {
int i;
int n = m.n;
for (i = 0; i < n/2; i++) {
int temp = s.pancakes[i];
s.pancakes[i] = s.pancakes[n - 1 - i];
s.pancakes[n - 1 - i]=temp;
}
}
void Pancake::unmakeMove(PancakeState &state, PancakeMove &move) {
makeMove(state, move);
}
int Pancake::heuristic(PancakeState &s) {
int i, res = 0;
nCalls++;
for (i = 1; i < s.n; i++)
if (abs(s.pancakes[i]-s.pancakes[i-1])>1)
res++;
if (s.pancakes[0] != 0) res++;
return res;
}
void tabs(int g) {
int i;
for (i = 0; i < g; i++) cout << "\t";
}
template <class Domain, class State, class Move>
class Alg {
public:
State **solution;
int threshold;
bool verbose;
int df(Domain &d, State &s, int g);
void ida(Domain &d, State &s);
};
template <class Domain, class State, class Move>
int Alg<Domain, State, Move>::df(Domain &d, State &s, int g) {
int h = d.heuristic(s), i;
if (g == 0)
cout << "Thereshold:" << this->threshold << "\n";
if (this->verbose) {
tabs(g);
cout << "g=" << g;
s.printState(); cout << "\n";
}
if (h == 0) {
solution = (State **)malloc((g+1) * sizeof(State *));
solution[g] = s.copyState();
return 1;
}
if (g == this->threshold)
return 0;
for (i = 0; i < d.bf(s); i++) {
Move *move = d.getMove(i);
d.makeMove(s, *move);
if (this->df(d, s, g+1)) {
d.unmakeMove(s, *move);
solution[g] = s.copyState();
delete move;
return 1;
}
d.unmakeMove(s, *move);
delete move;
}
return 0;
}
template <class Domain, class State, class Move>
void Alg<Domain, State, Move>::ida(Domain &d, State &s) {
int i;
this->threshold = 0;
while (!this->df(d, s, 0)) threshold++;
for (i = 0; i <= threshold; i++) {
cout << i << ".";
this->solution[i]->printState();
cout << "\n";
//if (i < threshold - 1) printf("->");
}
}
int main(int argc, char **argv) {
Pancake *d = new Pancake();
PancakeState *s = new PancakeState();
int myInstance[] = {0,5,4,7,2,6,1,3};
s->pancakes = myInstance;
s->n = 8;
s->printState(); cout << "\n";
Alg<Pancake, PancakeState, PancakeMove> *alg = new Alg<Pancake, PancakeState, PancakeMove>();
//alg->verbose = true;
alg->ida(*d, *s);
cout << nCalls < "calls to heuristic()";
delete alg;
return 0;
}
You have a lot of malloc() and operator new calls in there. Stop doing that, and performance will improve. And don't use malloc() in C++, use operator new always.
For example, PancakeMove is a small, trivial struct. But you allocate instances of it dynamically, which is slow. Just pass it around by value.
Basically, you are allocating a lot of small things on the heap instead of on the stack. That's pretty "expensive", so will take extra time.
This code (which is modified from your original code) runs within 1ms of the C code:
#include <iostream>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <vector>
using namespace std;
static int df_output = 0;
int nCalls = 0;
class PancakeState {
public:
PancakeState(int n) : n(n), pancakes(n)
{
}
PancakeState(int n, int *v) : n(n), pancakes(n)
{
for(int i = 0; i < n; i++)
pancakes[i] = v[i];
}
PancakeState(): n(0) {}
public:
vector<int> pancakes;
int n;
PancakeState *copyState();
void printState();
};
void PancakeState::printState() {
int i;
cout << "[";
for (i = 0; i < this->n; i++) {
cout << this->pancakes[i];
if (i < this->n - 1)
cout << ", ";
}
cout << "]";
}
class PancakeMove {
public:
PancakeMove(int n) : n(n) {}
int n;
};
class Pancake {
public:
int heuristic (PancakeState &);
int bf(PancakeState&);
PancakeMove getMove(int);
void makeMove(PancakeState &, PancakeMove &);
void unmakeMove(PancakeState &, PancakeMove &);
};
int Pancake::bf(PancakeState& s) {
return s.n - 1;
}
PancakeMove Pancake::getMove(int i) {
return PancakeMove(i + 2);
}
// reverse n pancakes
void Pancake::makeMove(PancakeState &s, PancakeMove &m) {
int i;
int n = m.n;
for (i = 0; i < n/2; i++) {
int temp = s.pancakes[i];
s.pancakes[i] = s.pancakes[n - 1 - i];
s.pancakes[n - 1 - i]=temp;
}
}
void Pancake::unmakeMove(PancakeState &state, PancakeMove &move) {
makeMove(state, move);
}
int Pancake::heuristic(PancakeState &s) {
int i, res = 0;
nCalls++;
for (i = 1; i < s.n; i++)
if (abs(s.pancakes[i]-s.pancakes[i-1])>1)
res++;
if (s.pancakes[0] != 0) res++;
return res;
}
void tabs(int g) {
int i;
for (i = 0; i < g; i++) cout << "\t";
}
template <class Domain, class State, class Move>
class Alg {
public:
vector<State> solution;
int threshold;
bool verbose;
int df(Domain &d, State &s, int g);
void ida(Domain &d, State &s);
};
template <class Domain, class State, class Move>
int Alg<Domain, State, Move>::df(Domain &d, State &s, int g) {
int h = d.heuristic(s), i;
if (g == 0)
cout << "Thereshold:" << threshold << "\n";
if (this->verbose) {
tabs(g);
cout << "g=" << g;
s.printState(); cout << "\n";
}
if (h == 0) {
solution.resize(g+1);
solution[g] = s;
return 1;
}
if (g == this->threshold)
return 0;
for (i = 0; i < d.bf(s); i++) {
Move move = d.getMove(i);
d.makeMove(s, move);
if (this->df(d, s, g+1)) {
d.unmakeMove(s, move);
solution[g] = s;
return 1;
}
d.unmakeMove(s, move);
}
return 0;
}
template <class Domain, class State, class Move>
void Alg<Domain, State, Move>::ida(Domain &d, State &s) {
int i;
this->threshold = 0;
while (!this->df(d, s, 0)) threshold++;
for (i = 0; i <= threshold; i++) {
cout << i << ".";
solution[i].printState();
cout << "\n";
//if (i < threshold - 1) printf("->");
}
}
int main(int argc, char **argv) {
Pancake d = Pancake();
int myInstance[] = {0,5,4,7,2,6,1,3};
PancakeState s(8, myInstance);
s.printState(); cout << "\n";
Alg<Pancake, PancakeState, PancakeMove> *alg = new Alg<Pancake, PancakeState, PancakeMove>();
//alg->verbose = true;
alg->ida(d, s);
cout << nCalls < "calls to heuristic()";
delete alg;
return 0;
}
As an extra benefit of not making so many direct allocations, it also doesn't leak 22 lumps of memory throughout the execution, which is quite a useful feature.
(If you want to see what changed, here's a diff - ignoring whitespace only changes):
--- pcake.orig.cpp 2014-04-13 15:43:24.861417827 +0100
+++ pcake.cpp 2014-04-13 15:42:25.145165372 +0100
## -1,7 +1,9 ##
#include <iostream>
-#include "stdlib.h"
-#include "string.h"
-#include "assert.h"
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <vector>
+
using namespace std;
static int df_output = 0;
## -9,21 +11,22 ##
class PancakeState {
public:
- int *pancakes;
+ PancakeState(int n) : n(n), pancakes(n)
+ {
+ }
+ PancakeState(int n, int *v) : n(n), pancakes(n)
+ {
+ for(int i = 0; i < n; i++)
+ pancakes[i] = v[i];
+ }
+ PancakeState(): n(0) {}
+public:
+ vector<int> pancakes;
int n;
PancakeState *copyState();
void printState();
};
-PancakeState *PancakeState::copyState() {
- PancakeState *res = new PancakeState();
- res->n = this->n;
- res->pancakes = (int *)malloc(this->n * sizeof(int));
- memcpy(res->pancakes, this->pancakes,
- this->n * sizeof(int));
- return res;
-}
-
void PancakeState::printState() {
int i;
cout << "[";
## -37,25 +40,25 ##
class PancakeMove {
public:
- PancakeMove(int n) {this->n = n;}
+ PancakeMove(int n) : n(n) {}
int n;
};
class Pancake {
public:
int heuristic (PancakeState &);
- int bf(PancakeState &);
- PancakeMove *getMove(int);
+ int bf(PancakeState&);
+ PancakeMove getMove(int);
void makeMove(PancakeState &, PancakeMove &);
void unmakeMove(PancakeState &, PancakeMove &);
};
-int Pancake::bf(PancakeState &s) {
+int Pancake::bf(PancakeState& s) {
return s.n - 1;
}
-PancakeMove *Pancake::getMove(int i) {
- return new PancakeMove(i + 2);
+PancakeMove Pancake::getMove(int i) {
+ return PancakeMove(i + 2);
}
// reverse n pancakes
## -91,7 +94,7 ##
template <class Domain, class State, class Move>
class Alg {
public:
- State **solution;
+ vector<State> solution;
int threshold;
bool verbose;
int df(Domain &d, State &s, int g);
## -102,30 +105,28 ##
int Alg<Domain, State, Move>::df(Domain &d, State &s, int g) {
int h = d.heuristic(s), i;
if (g == 0)
- cout << "Thereshold:" << this->threshold << "\n";
+ cout << "Thereshold:" << threshold << "\n";
if (this->verbose) {
tabs(g);
cout << "g=" << g;
s.printState(); cout << "\n";
}
if (h == 0) {
- solution = (State **)malloc((g+1) * sizeof(State *));
- solution[g] = s.copyState();
+ solution.resize(g+1);
+ solution[g] = s;
return 1;
}
if (g == this->threshold)
return 0;
for (i = 0; i < d.bf(s); i++) {
- Move *move = d.getMove(i);
- d.makeMove(s, *move);
+ Move move = d.getMove(i);
+ d.makeMove(s, move);
if (this->df(d, s, g+1)) {
- d.unmakeMove(s, *move);
- solution[g] = s.copyState();
- delete move;
+ d.unmakeMove(s, move);
+ solution[g] = s;
return 1;
}
- d.unmakeMove(s, *move);
- delete move;
+ d.unmakeMove(s, move);
}
return 0;
}
## -138,23 +139,22 ##
for (i = 0; i <= threshold; i++) {
cout << i << ".";
- this->solution[i]->printState();
+ solution[i].printState();
cout << "\n";
//if (i < threshold - 1) printf("->");
}
}
int main(int argc, char **argv) {
- Pancake *d = new Pancake();
- PancakeState *s = new PancakeState();
+ Pancake d = Pancake();
int myInstance[] = {0,5,4,7,2,6,1,3};
- s->pancakes = myInstance;
- s->n = 8;
- s->printState(); cout << "\n";
+ PancakeState s(8, myInstance);
+ s.printState(); cout << "\n";
Alg<Pancake, PancakeState, PancakeMove> *alg = new Alg<Pancake, PancakeState, PancakeMove>();
//alg->verbose = true;
- alg->ida(*d, *s);
+ alg->ida(d, s);
cout << nCalls < "calls to heuristic()";
delete alg;
return 0;
}
+