C++ Mergesort Segmentation Fault? - c++

I seem to be having some trouble getting this mergesort to run. When I try to run it with g++ the terminal says "Segmentation fault (core dumped)," and I don't know what is causing this to happen (you might be able to tell that I'm still a beginner). Could anybody help out?
#include <iostream>
using namespace std;
void merge (int*, int, int, int);
void mergesort (int* A, int p, int r){
if (p < r){
int q = (p+r)/2;
mergesort (A, p, q);
mergesort (A, q+1, r);
merge ( A, p , q, r);
}
}
void merge (int* A, int p, int q, int r){
int n = q-p+1;
int m = r-q ;
int L [n+1];
int R [m+1];
for (int i=1;i <n+1;i++)
L[i] = A[p+i-1];
for (int j=1; j< m+1; j++)
R[j] = A[q+j];
L[n+1];
R[m+1];
int i= 1;
int j=1;
for (int k = p; k= r + 1; k++){
if (L[i] <= R[j]){
A[k] = L[i];
i+=1;
}
else{
j += 1;
}
}
}
int main() {
int A [15] = {1, 5, 6, 7,3, 4,8,2,3,6};
mergesort (A, 0, 9);
for (int i=0; i <9; i++){
cout << A[i] << endl;
}
return 0;
}
Thanks a lot!

There are three things in your implementation that either don't make sense or are outright wrong:
First these:
L[n+1];
R[m+1];
Neither of these statement have any effect at all, and I've no idea what you're trying to do.
Next, a significant bug:
for (int k = p; k= r + 1; k++){
The conditional clause of this for-loop is the assignment k = r + 1. Since r does not change anywhere within your loop, the only way that expression is false is if r == -1, which it never is. You've just created an infinite-loop on a counter k that will run forever up into the stratosphere, and in the process index, and write, to memory no longer valid in your process. This, as a result, is undefined behavior. I'm fairly sure you wanted this:
for (int k = p; k< (r + 1); k++){
though I can't comment on whether that is a valid limit since I've not dissected your algorithm further. I've not take the time to debug this any further. that I leave to you.
Edit. in your main mergsesort, this is not "wrong" but very susceptible to overflow
int q = (p+r)/2;
Consider this instead:
int q = p + (r-p)/2;
And not least this:
int L [n+1];
int R [m+1];
Uses a variable-length array extension not supported by the standard for C++. You may want to use std::vector<int> L(n+1) etc.. instead.

In your case the segmentation fault is likely being caused when you are trying to read memory in that does not exist for a variable, for example say you have an array called foo of size 10 (so foo[10]) and you this statement foo[11] would cause a segmentation fault.
What you need to do is use debug statements to print out your index variables (i, j, n, m, p and q) and see if any of these are larger than your array sizes
EDIT: Another unrelated issue is that you should not use using namespace std, this line of code can cause scoping issues if you are not careful, just something to keep in mind :)

Related

C++: Pascal's Triangle

I am struggling on how to interpret and/or relate between comb(i, j) to long comb(int n, int k). May you please explain to me how the for loop of the long comb(int n, int k) works? Thank you very much.
#include<iostream>
#include<iomanip>
using namespace std;
long comb(int, int);
int main()
{
int m;
cout << "Type a number and then press ENTER: ";
cin >> m;
for(int i = 0; i < m; i++)
{
for(int j = 1; j < (m - i); j++)
{
cout << setw(2) << "";
}
for(int j = 0; j <= i; j++)
{
cout << setw(4) << comb(i, j);
}
cout << endl;
}
}
long comb(int n, int k)
{
if (n < 0 || k < 0 || n < k)
{
return 0;
}
long c= 1;
for(int i = 1; i <= k; i++, n--)
{
c = c*(n/i);
}
return c;
}
Edit: Thank Yunnosch for the correction.
The for loop in the long comb(int n, int k) is calculating the Binomial Coefficients using the Multiplicative Formula.
You could also write that for loop like below (which looks more like the multiplicative formula):
for(int i = 1; i <= k; i++) {
c = c * ((n - i + 1) / i);
}
The
long comb(int, int);
before int main() is the declaration of the long comb(int n, int k) function. You have to do it, so that the code compiles. Another way would be to define the long comb(int n, int k) function completely before main() instead of after it. You should understand the difference between declaration and definition in C++.
By the way, your code seems to have a bug, and does not print the correct Pascal triangle.
These are the meanings of the different occurrences of comb() in your code.
long comb(int, int);
This means "Dear compiler. Later on I will provide code for a function of this name with these parameter types. Please accept that I call it before you have seen the code."
It is called a "prototype".
cout << setw(4) << comb(i, j);
Means "Dear compiler, remember the function I told you about but have not shown you the code for? Call it here please, as part of making output; the code is below somewhere."
long comb(int n, int k)
{
/* ... */
}
Means "Dear compiler, with the prototype above I promised to provide code for a function of this name and parameters. I even asked you to call it from other code. Here I finally provide the code for it. Please use this code for the execution of the call from main()."
(Some of this last part actually addresses more the linker than the compiler, but I think that level of detail is out of scope here.)
I have the impression that you don't understand how to learn how to program:
An experienced programmer looks at a piece of code and understands what it means, but for a starting programmer most of the times this does not work: you need to try the piece of code, debug it, try to understand it and mostly, try it out.
Let's have a look at comb(n,k): apparently n must be larger than k, so let's have a look at what happens for the values n=8 and k=3:
for(int i = 1; i <= k; i++, n--)
{
c = c*(n/i);
}
What happens with i and c?
i k n c
1 3 8 1*8/1
2 3 7 1*8/1*7/2
3 3 6 1*8/1*7/2*6/3
So, at the end: c becomes 8*7*6/(1*2*3).
I admit: two variables get changed during the loop (i++ and n--), which is confusing indeed, but by trying out you'll get the hang of it.

segmentation fault knapsackproblem

I wrote this knapsack problem solution in c++ however when I run it, it gives me segmentation fault
I have tried everything and my compiler will always give me the segmentation fault error.
#include<iostream>
#include<algorithm>
int knapsack(int v[],int w[],int n,int W)
{
int V[n][W];
for(int i = 0; i<=W;i++)
{
V[0][i] = 0;
}
for(int i = 0; i <= n; i++){
for(int j = 1; j<=W; j++)
{
if(w[i]<=W)
{
V[i][j] = std::max(V[i-1][j], v[i]+V[i-1][j-w[i]]);
}
else
{
V[i][j] = V[i-1][j];
}
}
}
return V[n][W];
}
int main()
{
int v[4] = {10,40,30,50};
int w[4] = {5,4,6,3};
int n = 3;
int W = 10;
std::cout<<"item value:"<<knapsack(v,w,n,W);
}
Don't use VLAs. The size of an array must be known at compile time, else it's not standard C++. Those are compiler extensions that are not portable and introduce some hidden costs.
Array indices go from 0 to length-1. in you loop
for(int i = 0; i<=W;i++)
i can reach W, then V[0][W] is out of bounds which causes the seg fault. You have to use < instead of <=:
for(int i = 0; i < W; i++)
n should probably be 4, if it's meant to represent the size of the array, a std::vector would make your life easier here, because a vector knows it's size
In general don't use C-style arrays or raw pointers at all in this day and age, use std::vector instead.
int V[n][W];
for(int i = 0; i<=W;i++)
{
V[0][i] = 0;
}
Note that V's indexes go from V[0][0] to V[0][W-1]. Your for loop will try to read V[0][W].
The same error is repeated in other places. Your end condition in your for loops should be < (strictly less) instead of <= (less or equal than).

Doing away with Runtime Error(SIGSEGV)

I don't think in my code I tried accessing null pointers, or initialising large arrays, someone help please, I dunno where the Runtime Error(SIGSEGV) is coming from. Question to problem can be found at https://www.codechef.com
/MARCH18B/problems/MINEAT
edit:
I think i found out, NathanOliver was right, v1, because of my code, happens to be sometimes empty. Some answers were actually found out of my loop (above n). Thanks alot. I fixed that and I finally got AC, but just 30 points, my code took an additional 0.01 seconds to run. Can anyone help me optimize it, based on Problem statement, Please.
#include <bits/stdc++.h>
using namespace std;
int main()
{
int t; cin>>t; while(t--)
{
int n = 0, h = 0; cin>>n>>h;
vector<int> v; vector<int> v1;
for(int i = 0; i != n; i++){int a; cin>>a; v.push_back(a);}
for(int j = 1; j <= h; j++)
{
int hold = 0;
for(auto k : v)
{
if (j >= k){hold +=1;}
else if (j < k){if(k % j == 0){hold += (k/j);} else{hold += ((k/j)+1);}}
}
if (hold <= h){v1.push_back(j);}
}
cout<<*min_element(v1.begin(),v1.end())<<endl;
}
}
Did you check the min_element function's return value? According to the user input, min_element function returns an iterator to 'last element' which is basically a nullptr. Since you're dereferencing it directly, you get the error.

Inversion counting giving trouble (implementation of modified merge sort)

Given this question:
Given an array A on size N, you need to find the number of ordered
pairs (i, j) such that i < j and A[i] > A[j]
Input: First line contains one integer, N, size of array. Second line contains N space separated integers denoting the elements of the
array A.
Output: Print the number of ordered pairs (i, j) such that i < j and
A[i] > A[j].
Constraints:
1 ≤ N ≤ 10^6
1 ≤ A[i] ≤ 10^6
Source: hackerearth's merge sort tutorial
I'm encountering problems properly implementing the solution.
This is the code I wrote:
#include <iostream>
using namespace std;
int ar[10000000];
long long counting=0;
void merge(int* ALR, int* L, int left_length, int* R, int right_length) {
int l = 0;
int r = 0;
for (int i = 0; i < left_length + right_length;) {
if (l == left_length)ALR[i++] = R[r++];
else if (r == right_length)ALR[i++] = L[l++];
else if(L[l]>R[r]){
counting+=(left_length-l);
ALR[i++]=L[l++];
}
else ALR[i++]=R[r++];
}
}
void merge_sort(int* ALR, int length) {
if (length == 1)return;
int mid = length / 2;
int* L = new int[mid];
int* R = new int[length - mid];
int k = 0;
for (size_t i = 0; k < mid; i++)L[i] = ALR[k++];
for (size_t i = 0; k < length; i++)R[i] = ALR[k++];
merge_sort(L, mid);
merge_sort(R, length - mid);
merge(ALR, L, mid, R, length - mid);
delete(L);
delete(R);
}
int main() {
int t;
cin>> t;
for(int i=0;i<t;i++)cin>> ar[i];
merge_sort(ar, t);
cout<<counting;
return 0;
}
Now the problem is that I'm getting a wrong answer in the 2nd test case ...
The answer should be: 250194527312
The answer I get: 250002372570
Where did it go wrong?
A general principle you should follow is unit testing small bits of code. In this case, you should test the merge function, to see if what you get when you merges is correct. If you had written a test which merges two very small arrays, then you would have seen the result be in descending order, and the inversion count would usually be wrong.
Here's the test case I used for merge-sort inversion counting:
// expect 3 inversions in [1,3,5,2,4,6]
Your actual problem is an easy error to make (flip the comparitor and count the other branch as an inversion), and I guarantee many experienced programmers would make some equivalent mistake before running their tests. The difference between a novice and veteran is knowing how to find those mistakes (and structure tests so that they are found automatically).

What is wrong with my C++ merge sort program?

I'm stuck at an impass with this implementation. My n2 variable is being overwritten during the merging of the subarrays, what could be causing this? I have tried hard-coding values in but it does not seem to work.
#include <iostream>
#include <cstdlib>
#include <ctime> // For time(), time(0) returns the integer number of seconds from the system clock
#include <iomanip>
#include <algorithm>
#include <cmath>//added last nite 3/18/12 1:14am
using namespace std;
int size = 0;
void Merge(int A[], int p, int q, int r)
{
int i,
j,
k,
n1 = q - p + 1,
n2 = r - q;
int L[5], R[5];
for(i = 0; i < n1; i++)
L[i] = A[i];
for(j = 0; j < n2; j++)
R[j] = A[q + j + 1];
for(k = 0, i = 0, j = 0; i < n1 && j < n2; k++)//for(k = p,i = j = 1; k <= r; k++)
{
if(L[i] <= R[j])//if(L[i] <= R[j])
{
A[k] = L[i++];
} else {
A[k] = R[j++];
}
}
}
void Merge_Sort(int A[], int p, int r)
{
if(p < r)
{
int q = 0;
q = (p + r) / 2;
Merge_Sort(A, p, q);
Merge_Sort(A, q+1, r);
Merge(A, p, q, r);
}
}
void main()
{
int p = 1,
A[8];
for (int i = 0;i < 8;i++) {
A[i] = rand();
}
for(int l = 0;l < 8;l++)
{
cout<<A[l]<<" \n";
}
cout<<"Enter the amount you wish to absorb from host array\n\n";
cin>>size;
cout<<"\n";
int r = size; //new addition
Merge_Sort(A, p, size - 1);
for(int kl = 0;kl < size;kl++)
{
cout<<A[kl]<<" \n";
}
}
What tools are you using to compile the program? There are some flags which switch on checks for this sort of thing in e,.g. gcc (e.g. -fmudflap, I haven't used it, but it looks potehtially useful).
If you can use a debugger (e.g. gdb) you should be able to add a 'data watch' for the variable n2, and the debugger will stop the program whenever it detects anything writing into n2. That should help you track down the bug. Or try valgrind.
A simple technique to temporarily stop this type of bug is to put some dummy variables around the one getting trashed, so:
int dummy1[100];
int n2 = r - q;
int dummy2[100];
int L[5], R[5];
Variables being trashed are usually caused by code writing beyond the bounds of arrays.
The culprit is likely R[5] because that is likely the closest. You can look in the dummies to see what is being written, and may be able to deduce from that what is happening.
ANother option is to make all arrays huge, while you track down the problem. Again set values beyond the correct bounds to a known value, and check those values that should be unchanged.
You could make a little macro to do those checks, and drop it in at any convenient place.
I had used the similar Merge function earlier and it doesn't seem to work properly. Then I redesigned and now it works perfectly fine. Below is the redesigned function definition for merge function in C++.
void merge(int a[], int p, int q, int r){
int n1 = q-p+1; //no of elements in first half
int n2 = r-q; //no of elements in second half
int i, j, k;
int * b = new int[n1+n2]; //temporary array to store merged elements
i = p;
j = q+1;
k = 0;
while(i<(p+n1) && j < (q+1+n2)){ //merging the two sorted arrays into one
if( a[i] <= a[j]){
b[k++] = a[i++];
}
else
b[k++] = a[j++];
}
if(i >= (p+n1)) //checking first which sorted array is finished
while(k < (n1+n2)) //and then store the remaining element of other
b[k++] = a[j++]; //array at the end of merged array.
else
while(k < (n1+n2))
b[k++] = a[i++];
for(i = p,j=0;i<= r;){ //store the temporary merged array at appropriate
a[i++] = b[j++]; //location in main array.
}
delete [] b;
}
I hope it helps.
void Merge(int A[], int p, int q, int r)
{
int i,
j,
k,
n1 = q - p + 1,
n2 = r - q;
int L[5], R[5];
for(i = 0; i < n1; i++)
L[i] = A[i];
You only allocate L[5], but the n1 bound you're using is based on inputs q and p -- and the caller is allowed to call the function with values of q and p that allow writing outside the bounds of L[]. This can manifest itself as over-writing any other automatic variables, but because it is undefined behavior, just about anything could happen. (Including security vulnerabilities.)
I do not know what the best approach to fix this is -- I don't understand why you've got fixed-length buffers in Merge(), I haven't read closely enough to discover why -- but you should not access L[i] when i is greater than or equal to 5.
This entire conversation also holds for R[]. And, since *A is passed to Merge(), it'd make sense to ensure that your array accesses for it are also always in bound. (I haven't spotted them going out of bounds, but since this code needs re-working anyway, I'm not sure it's worth my looking for them carefully.)