I'm very new to C++ and only coded in python before, but python is too slow for my purposes now. I did a mergesort algorithm in python and it worked. But now I translated it into C++ and I got a bunch of errors in my IDE. What are my errors?
#include <iostream>
using namespace std;
int *sort(int lenght, int lis[]) {
int units = lenght;
int umt;
int tiles = 1;
while (units > 1) {
bool whole = true;
umt = units % 2;
if (umt = 1) {
units++;
whole = false;
}
units = units / 2;
tiles = tiles * 2;
if (whole) {
int buffd[units];
int add_l = 0;
int add_r = 0;
int prod_l = 0;
int prod_r = prod_l + tiles / 2;
for (int k = 0; k < units; k++) {
int buffd[units];
int add_l = 0;
int add_r = 0;
int prod_l = k * tiles;
int prod_r = prod_l + tiles / 2;
for (int f = 0; f < tiles; f++) {
if (lis[prod_l + add_l] <= lis[prod_r + add_r]) {
buffd[f] = lis[prod_l + add_l];
add_l++;
if (add_l = tiles / 2) {
for (int e = f; e < tiles; e++) {
buffd[e] = lis[prod_r + add_r + e];
}
f = tiles;
}
} else {
buffd[f] = lis[prod_r + add_r];
add_r++;
if (add_r = tiles / 2) {
for (int e = f; e < tiles; e++) {
buffd[e] = lis[prod_l + add_l + e];
}
f = tiles;
}
}
}
for (int i = prod_l; i < prod_l + tiles; i++) {
lis[i] = buffd[i - prod_l];
}
}
} else {
int buffd[units];
int add_l = 0;
int add_r = 0;
int prod_l = 0;
int prod_r = prod_l + tiles / 2;
for (int k = 0; k < units - 1; k++) {
int buffd[units];
int add_l = 0;
int add_r = 0;
int prod_l = k * tiles;
int prod_r = prod_l + tiles / 2;
for (int f = 0; f < tiles; f++) {
if (lis[prod_l + add_l] <= lis[prod_r + add_r]) {
buffd[f] = lis[prod_l + add_l];
add_l++;
if (add_l = tiles / 2) {
for (int e = f; e < tiles; e++) {
buffd[e] = lis[prod_r + add_r + e];
}
f = tiles;
}
} else {
buffd[f] = lis[prod_r + add_r];
add_r++;
if (add_r = tiles / 2) {
for (int e = f; e < tiles; e++) {
buffd[e] = lis[prod_l + add_l + e];
}
f = tiles;
}
}
}
}
for (int i = prod_l; i < prod_l + tiles; i++) {
lis[i] = buffd[i - prod_l];
}
}
}
return lis;
}
int main() {
int to_sort[8] = { 23, 1, 654, 2, 4, 87, 3, 1 };
cout << "sortiert: ";
int *sorted;
sorted = sort(8, to_sort);
for (int p = 0; p < 8; p++) {
cout << sorted[p] << " ";
}
return 0;
}
The errors are in German and I have no idea why, the rest of the IDE is in English. Does anyone know how to set that to English, I'm using Clion from JetBrains.
There are some major problems in your code:
comparisons must use == instead of =, which is the assignment operator.
the redundant definitions for buffd, add_l, add_r, prod_l and prod_r should me removed.
variable length array definitions such as int buffd[units] are not supported by many C++ compilers. These are extensions for compatibility with C90 optional features, likely to cause stack overflow for large arrays. You should allocate these arrays or use std::vector.
these local arrays are declared with a incorrect size: it should be int buffd[tiles];, not int buffd[units]. Undefined behavior ensues.
the last for loop is outside the body of the previous loop, which is incorrect.
you do not increment f before copying the remaining elements from the other slice when either add_l or add_r equals tiles / 2.
your non-recursive algorithm cannot succeed in the general case, I got it to work for array lengths that are powers of 2, and it is quite surprising that it may come as a translation from your python version. There are much simpler ways to program mergesort in python, and in C++ too.
With some extra work, I simplified your code and got it to work for the general case:
#include <iostream>
using namespace std;
int *sort(int length, int lis[]) {
for (int tile = 1; tile < length; tile += tile) {
int tiles = tile + tile;
int *buffd = new int[tiles];
for (int prod_l = 0; prod_l < length; prod_l += tiles) {
int add_l = 0;
int max_l = tile;
int add_r = 0;
int max_r = tile;
int prod_r = prod_l + max_l;
int f = 0;
if (prod_r >= length)
break;
if (prod_r + max_r > length)
max_r = length - prod_r;
for (;;) {
if (lis[prod_l + add_l] <= lis[prod_r + add_r]) {
buffd[f++] = lis[prod_l + add_l++];
if (add_l == max_l) {
while (add_r < max_r) {
buffd[f++] = lis[prod_r + add_r++];
}
break;
}
} else {
buffd[f++] = lis[prod_r + add_r++];
if (add_r == max_r) {
while (add_l < max_l) {
buffd[f++] = lis[prod_l + add_l++];
}
break;
}
}
}
for (int i = 0; i < f; i++) {
lis[prod_l + i] = buffd[i];
}
}
delete[] buffd;
}
return lis;
}
int main() {
int to_sort[8] = { 23, 1, 654, 2, 4, 87, 3, 1 };
for (int i = 1; i < 8; i++) {
cout << "sortiert: ";
int *sorted = sort(i, to_sort);
for (int p = 0; p < i; p++) {
cout << sorted[p] << " ";
}
cout << endl;
}
return 0;
}
Here is a classic top-down recursive implementation for reference:
void mergesort(int lis[], int lo, int hi, int *tmp) {
if (hi - lo >= 2) {
int mid = (hi - lo) / 2;
mergesort(lis, lo, lo + mid, tmp);
mergesort(lis, lo + mid, hi, tmp);
for (int i = 0; i < mid; i++)
tmp[i] = lis[lo + i];
for (int i = 0, j = lo + mid, k = lo; i < mid;) {
if (j >= hi || tmp[i] <= lis[j])
lis[k++] = tmp[i++];
else
lis[k++] = lis[j++];
}
}
}
int *mergesort(int length, int lis[]) {
int *tmp = new int[length / 2];
mergesort(lis, 0, length, tmp);
delete[] tmp;
return lis;
}
Related
I have a problem with deallocating a 3 dimensional vector in c++, I get the error "CTR detected that the application wrote to memory after end of heap buffer".
Can somebody tell me what I am doing wrong? Thank you in advance.
Allocation:
count = new int**[w];
for (int i = 0; i < w; ++i)
{
count[i] = new int*[h];
for (int j = 0; j < h; ++j)
{
count[i][j] = new int[120];
for (int k = 20; k < 120; ++k)
{
count[i][j][k] = 0;
}
}
}
Deallocation:
for (int i = 0; i < w; ++i)
{
for (int j = 0; j < h; ++j)
{
delete [] count[i][j];
}
delete [] count[i];
}
delete [] count;
count = NULL;
This is my entire code:
#include <filesystem>
#include <stdexcept>
#include "pch.h"
#include <iostream>
#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include <math.h>
using namespace std;
using namespace cv;
class cerc {
int raza;
int a;
int b;
public:
cerc()
{
a = 0;
b = 0;
raza = 0;
}
inline cerc(int raza, int a, int b)
{
this->a = a;
this->b = b;
this->raza = raza;
}
inline cerc(cerc& c)
{
a = c.a;
b = c.b;
raza = c.raza;
}
void print()
{
std::cout << " (" << (int)this->a << ", " << (int)this->b << ", " << (int)this->raza << ") ";
}
inline bool operator==(const cerc& other) const
{
if (this->a == other.a && this->b == other.b && this->raza == other.raza)
return true;
else return false;
}
inline bool egal(int raza, int a, int b) const
{
if (this->a == a && this->b == b && this->raza == raza)
return true;
else return false;
}
inline void copy(cerc &c2)
{
this->raza = c2.raza;
this->a = c2.a;
this->b = c2.b;
}
inline void copy(int raza, int a, int b)
{
this->a = a;
this->raza = raza;
this->b = b;
}
const int getA()
{
return a;
}
const int getB()
{
return b;
}
const int getRaza()
{
return raza;
}
};
int min(int a, int b)
{
if (a < b)
return a;
return b;
}
void createVector(int*** count, Mat img, int w, int h)
{
int a = 0;
int b = 0;
int r = 0;
int wminus = 5 * (w / 6);
int hminus = 5 * (h / 6);
int wstart = w / 6;
int hstart = h / 6;
int x, y;
for (x = wstart; x < wminus; x++)
for (y = hstart; y < hminus; y++)
{
if (((Scalar)(img.at<uchar>(Point(x, y)))).val[0] == 255)
{
for (a = wstart; a < wminus; a += 1)
for (b = hstart; b < hminus; b += 1)
{
r = (int)sqrt((b - y)*(b - y) + (a - x)*(a - x));
if (r >= 20 && r <= 120)
count[a][b][r]++;
}
}
}
}
void cercFinal(cerc &cercMax, int***count, int w, int h)
{
int wminus = 5 * (w / 6);
int hminus = 5 * (h / 6);
int wstart = w / 6;
int hstart = h / 6;
int maxNr = count[0][0][0];
for (int i = wstart; i < wminus; i += 1)
for (int j = hstart; j < hminus; j += 1)
for (int k = 20; k < 60; k++)
if (maxNr < count[i][j][k])
{
maxNr = count[i][j][k];
cercMax.copy(k, i, j);
}
cout << maxNr;
}
void cercFinalSecund(cerc &SecondCircle, cerc &FirstCircle, int***count, int w, int h)
{
int wminus = 3 * (w / 4);
int hminus = 3 * (h / 4);
int wstart = w / 4;
int hstart = h / 4;
int minIrisRay = (int)(FirstCircle.getRaza() * 1.5);
int maxIrisRay = FirstCircle.getRaza() * 4;
int maxNr = count[0][0][0];
for (int i = wstart; i < wminus; i += 1)
for (int j = hstart; j < hminus; j += 1)
for (int k = 40; k < 120; k++)
{
if (k >= minIrisRay && k <= maxIrisRay)
{
if (maxNr < count[i][j][k] && !(cerc(k, i, j) == FirstCircle) && abs(j - FirstCircle.getB()) < 2 && abs(i - FirstCircle.getA()) < 2)
{
maxNr = count[i][j][k];
SecondCircle.copy(k, i, j);
}
}
}
}
int main()
{
Mat imgCanny;
Mat imgBlur;
int ***count;
for (int i = 10; i < 50; i++)
{
Mat_<uchar> img = imread("C://Users//Maria//Downloads//CASIA-IrisV2//CASIA-IrisV2//device1//00" + std::to_string(i) + "//00" + std::to_string(i) + "_000.bmp", IMREAD_GRAYSCALE);
//img.convertTo(img, -1, 4, 0);
//int t = img.at<uchar>(1, 2).val[0];
int w = img.size().width;
int h = img.size().height;
medianBlur(img, imgBlur, 15);
//GaussianBlur(img, imgBlur, Size(8, 8), 0);
Canny(imgBlur, imgCanny, 30, 40);
//imshow("canny", imgCanny);
int m = min(w, h);
count = new int**[w];
for (int i = 0; i < w; ++i)
{
count[i] = new int*[h];
for (int j = 0; j < h; ++j)
{
count[i][j] = new int[120];
for (int k = 20; k < 120; ++k)
{
count[i][j][k] = 0;
}
}
}
createVector(count, imgCanny, w, h);
cerc final(0, 0, 0);
cerc finalSecund(0, 0, 0);
cercFinal(final, count, w, h);
cercFinalSecund(finalSecund, final, count, w, h);
cout << endl << "cerc=";
final.print();
Point p(final.getA(), final.getB());
Mat imgColor = imread("C://Users//Maria//Downloads//CASIA-IrisV2//CASIA-IrisV2//device1//00" + std::to_string(i) + "//00" + std::to_string(i) + "_000.bmp", IMREAD_COLOR);
circle(imgColor, p, final.getRaza(), Scalar(255, 0, 0), 4, 8, 0);
Point ps(finalSecund.getA(), finalSecund.getB());
cout << endl << "cerc=";
finalSecund.print();
circle(imgColor, ps, finalSecund.getRaza(), Scalar(255, 0, 0), 4, 8, 0);
imshow("iris", imgColor);
for (int i = 0; i < w; ++i)
{
for (int j = 0; j < h; ++j)
{
delete [] count[i][j];
}
delete [] count[i];
}
delete [] count;
count = NULL;
waitKey(0);
}
return 0;
}
If I delete the line count[a][b][r]++; the deallocation works fine. Is anything wrong with this statement?
I have written code for matrix chain multiplication in dynamic programming in c++.
there is an error in the recursive call for printing the correct parenthesization of the matrices. I am taking input from text file and giving output on a text file. please help..
#include <iostream>
#include <fstream>
#include <limits.h>
using namespace std;
int * MatrixChainOrder(int p[], int n)
{
static int m[100][100];
static int s[100][100];
int j, q;
int min = INT_MAX;
for (int i = 1; i <= n; i++)
m[i][i] = 0;
for (int L = 2; L <= n; L++) {
for (int i = 1; i <= n - L + 1; i++) {
j = i + L - 1;
m[i][j] = min;
for (int k = i; k <= j - 1; k++) {
q = m[i][k] + m[k + 1][j] + p[i - 1] * p[k] * p[j];
if (q < m[i][j]) {
m[i][j] = q;
s[i][j] = k;
}
}
}
}
return (*s);
}
void Print(int *s, int i, int j)
{
ofstream outfile("output.text");
if (i == j)
{
outfile << "a1";
}
else
outfile << "(";
{
Print(*s, i, s[i][j]);
Print(*s, s[i][j] + 1, j);
outfile << ")";
}
outfile.close();
}
int main()
{
int arr[100];
int num, i = 0;
ifstream infile("input.text");
while (infile)
{
infile >> num;
arr[i] = num;
i++;
}
i = i - 1;
infile.close();
Print(MatrixChainOrder(arr, i - 1), 0, i - 1);
return 0;
}
In C++ it is better to use std::vector for arrays. Aside from that, you can't mix pointers and arrays like that because the compiler loses track of array size.
For example this doesn't work:
int x[10][20];
void foo(int *ptr)
{
//the numbers 10 and 20 have not been passed through
}
But you can change it to
int x[10][20];
void foo(int arr[10][20])
{
//the numbers 10 and 20 are available
}
MatrixChainOrder is supposed to return a number, according to this link
int MatrixChainOrder(int s[100][100], int p[], int n)
{
int m[100][100];
for (int i = 0; i < 100; i++) m[i][i] = 0;
for (int i = 0; i < 100; i++) s[i][i] = 0;
int q = 0;
for (int L = 2; L <= n; L++) {
for (int i = 1; i <= n - L + 1; i++) {
int j = i + L - 1;
m[i][j] = INT_MAX;
for (int k = i; k <= j - 1; k++) {
q = m[i][k] + m[k + 1][j] + p[i - 1] * p[k] * p[j];
if (q < m[i][j]) {
m[i][j] = q;
s[i][j] = k;
}
}
}
}
return q;
}
int main()
{
int arr[] = { 40, 20, 30, 10, 30 };
int array_size = sizeof(arr) / sizeof(int);
int n = array_size - 1;
int s[100][100];
int minimum = MatrixChainOrder(s, arr, n);
printf("{ 40, 20, 30, 10, 30 } should result in 26000 : %d\n", minimum);
return 0;
}
Likewise you can change your Print function
void Print(int s[100][100], int i, int j)
{
if (i < 0 || i >= 100 || j < 0 || j >= 100)
{
cout << "array bound error\n";
}
//safely access s[i][j] ...
}
I have a computation with a matrix(88147*2000) and it runs very slow.
So I want to use openMP to speed it up. This is my first time to use
openMP so I just use it in "loop-for".
This is my code:
#include<iostream>
#include<fstream>
#include<math.h>
#include<omp.h>
using namespace std;
#define LONGTH 88147
int label[LONGTH] ;
float data[LONGTH][2000] ;
float w[2000];
float e[2000];
void Input()
{
ifstream fin;
float a;
fin.open("/home/data.train");
if (!fin)
{
cout << "file error";
return;
}
for (int i = 0; i < LONGTH; i++)
{
fin >> a;
label[i] = int(a);
for (int j = 0; j < 2000; j++)
{
fin>>data[i][j];
}
}
fin.close();
cout<<"input over"<<endl;
return;
}
void Initial()
{
for (int i = 0; i < 2000; i++)
{
w[i] = 1;
e[i] = 1;
}
return;
}
bool End()
{
for (int i = 0; i < 2000; i++)
{
if (fabs(e[i])>pow(0.1, 6))
return 0;
}
return 1;
}
float Tkj(int i, int j, int k,float w[2000])
{
return w[i] * data[k][i] - w[j] * data[k][j];
}
float En(int n)//*computation*
{
float result = 0;
#pragma omp parallel for num_threads(64) reduction(+:result)
for (int k = 0; k < LONGTH; k++)
{
int tnum = omp_get_thread_num();
float tmp = 0;
int i = label[k] - 1;
for (int j = 0; j < 2000; j++)
{
if (j != i)
{
float l = 0;
if (n == i)
{
l = data[k][i];
float e = exp(Tkj(i, j, k,w));
tmp = tmp + (-e*l) / pow(1 + e, 2);
}
else if (n == j)
{
l = -data[k][j];
float e = exp(Tkj(i, j, k,w));
tmp = tmp + (-e*l) / pow(1 + e, 2);
}
else
{
continue;
}
}
}
result = result + tmp;
}
return result;
}
float Ex(float w[2000])
{
float result = 0;
#pragma omp parallel for num_threads(64) reduction(+:result)
for (int k = 0; k < LONGTH; k++)
{
int i = label[k] - 1;
float tmp = 0;
int tnum = omp_get_thread_num();
for (int j = 0; j < 2000; j++)
{
if (j != i)
{
tmp = tmp + 1 / (1 + exp(Tkj(i,j,k,w)));
}
}
result = result+tmp;
}
return result;
}
int main()
{
Input();
Initial();
float w2[2000] = { 0 };
float b = pow(0.1,5);
int times = 0;
while (!End()&×<=30000)
{
times++;
cout<<times<<endl;
for (int i = 0; i < 2000; i++)
{
e[i] = En(i);
w2[i] = w[i] - b*e[i];
}
if (Ex(w2)<=Ex(w))//better
{
b = b * 2;
for (int i = 0; i < 2000; i++)
w[i] = w2[i];
}
else//worser
{
b = b / 2;
}
}
ofstream fout("/home/w.txt");
for(int i=0;i<2000;i++)
{
fout<<w[i]<<' ';
}
fout.close();
return 0;
}
The function 'En' costs most of time,so I use "#pragma omp parallel for num_threads(64) reduction(+:result)"to speed it up.
I run it in a CentOS server which has 32 cores and use "-fopenmp" to compile it.But it doesn't be a little quicker.
How can I speed this program up more?
This is for an assignment in an algorithm class. I understand and agree that using a vector would simplify things, but that isn't an option.
The code for the Mergesort / merge algorithm can't be modified either.
I need to run the merge sort as follows:
starting from 100 all the way to 1000, increments of 100. For each increment I run it 5 times, for each of these times I run it 1000 times.
That being said - everything works fine until my loop reaches 700 and crashes with the error: "Unhandled exception at 0x75612F71 in msdebug.exe: Microsoft C++ exception: std::bad_alloc at memory location 0x010672F4."
Here is my code:
int const size = 6;
int const size2 = 1001;
int const times = 6;
int const interval = 11;
void merge(int arr[], int p, int q, int r)
{
int n1 = q - p + 1;
int n2 = r - q;
int * L = new int[n1 + 1];
int * R = new int[n2 + 1]; // line giving the error after 700
for (int i = 1; i <= n1; i++)
{
L[i] = arr[p + i - 1];
}
for (int j = 1; j <= n2; j++)
{
R[j] = arr[q + j];
}
L[n1 + 1] = 32768;
R[n2 + 1] = 32768;
int i, j;
i = j = 1;
for (int k = p; k <= r; k++)
{
if (L[i] <= R[j])
{
arr[k] = L[i];
i++;
}
else
{
arr[k] = R[j];
j++;
}
}
}
void mergeSort(int arr[], int p, int r)
{
int q;
if (p < r)
{
q = ((p + r) / 2);
mergeSort(arr, p, q);
mergeSort(arr, (q + 1), r);
merge(arr, p, q, r);
}
}
void copyArray(int original[][size2], int copy[], int row, int finish)
{
int i = 1;
while (i <= finish)
{
copy[i] = original[row][i];
i++;
}
}
void copyOneD(int orig[], int cop[])
{
for (int i = 1; i < size2; i++)
{
cop[i] = orig[i];
}
}
int main()
{
struct timeval;
clock_t start, end;
srand(time(NULL));
int arr[size][size2];
int arr2[size2];
int arrCopy[size2];
double tMergeSort[times][interval];
double avgTmergeSort[11];
/*for (int i = 1; i < (size2); i++)
{
arr2[i] = rand();
}*/
for (int i = 1; i < size; i++)
{
for (int j = 1; j < size2; j++)
{
arr[i][j] = rand();
}
}
for (int x = 100; x <= 1000; x = x + 100) //This loop crashes >=700
{
for (int r = 1; r <= 5; r++)
{
copyArray(arr, arr2, r, 1001);
for (int k = 0; k < 1000; k++)
{
copyOneD(arr2, arrCopy);
mergeSort(arrCopy, 1, x);
}
}
}
return 0;
}
You can ignore the code and the arrays. Those functions work fine.
Everything works fine until I set 'x <= 700' or higher and then it crashes.
I had a theory that maybe the computer runs out of memory for the pointers in the merge algorithm but when I tried to use delete it also crashed.
Any help is appreciated and suggestions as well.
Thanks
I want to make a function that, depending on the depth of nested loop, does this:
if depth = 1:
for(i = 0; i < max; i++){
pot[a++] = wyb[i];
}
if depth = 2:
for(i = 0; i < max; i++){
for( j = i+1; j < max; j++){
pot[a++] = wyb[i] + wyb[j];
}
}
if depth = 3:
for(i = 0; i < max; i++){
for( j = i+1; j < max; j++){
for( k = j+1; k < max; k++){
pot[a++] = wyb[i] + wyb[j] + wyb[k];
}
}
}
and so on.
So the result would be:
depth = 1
pot[0] = wyb[0]
pot[1] = wyb[1]
...
pot[max-1] = wyb[max-1]
depth = 2, max = 4
pot[0] = wyb[0] + wyb[1]
pot[1] = wyb[0] + wyb[2]
pot[2] = wyb[0] + wyb[3]
pot[3] = wyb[1] + wyb[2]
pot[4] = wyb[1] + wyb[3]
pot[5] = wyb[2] + wyb[3]
I think you get the idea. I can't think of a way to do this neatly.
Could someone present an easy way of using recursion (or maybe not?) to achieve this, keeping in mind that I'm still a beginner in c++, to point me in the right direction?
Thank you for your time.
You may use the std::next_permutation to manage the combinaison:
std::vector<int> compute(const std::vector<int>& v, std::size_t depth)
{
if (depth == 0 || v.size() < depth) {
throw "depth is out of range";
}
std::vector<int> res;
std::vector<int> coeffs(depth, 1);
coeffs.resize(v.size(), 0); // flags is now {1, .., 1, 0, .., 0}
do {
int sum = 0;
for (std::size_t i = 0; i != v.size(); ++i) {
sum += v[i] * coeffs[i];
}
res.push_back(sum);
} while (std::next_permutation(coeffs.rbegin(), coeffs.rend()));
return res;
}
Live example
Simplified recursive version:
int *sums_recursive(int *pot, int *wyb, int max, int depth) {
if (depth == 1) {
while (max--)
*pot++ = *wyb++;
return pot;
}
for (size_t i = 1; i <= max - depth + 1; ++i) {
int *pot2 = sums_recursive(pot, wyb + i, max - i, depth - 1);
for (int *p = pot ; p < pot2; ++p) *p += wyb[i - 1];
pot = pot2;
}
return pot;
}
Iterative version:
void sums(int *pot, int *wyb, int max, int depth) {
int maxi = 1;
int o = 0;
for (int d = 0; d < depth; ++d) { maxi *= max; }
for (int i = 0; i < maxi; ++i) {
int i_div = i;
int idx = -1;
pot[o] = 0;
int d;
for (d = 0; d < depth; ++d) {
int new_idx = i_div % max;
if (new_idx <= idx) break;
pot[o] += wyb[new_idx];
idx = new_idx;
i_div /= max;
}
if (d == depth) o++;
}
}