Merge Sort Algorithm? - c++

I can't figure out what is wrong with my MergeSort function. This is my code:
void Merge(int* A, int p, int q, int r)
{
int B[100], i = 0, j = 0, k = 0;
i = p;
k = p;
j = q + 1;
while (i <= q && j <= r)
{
if (A[i] <= A[j])
{
B[k] = A[i];
k++;
i++;
}
else
{
B[k] = A[j];
k++;
j++;
}
}
while (i <= q)
{
B[k] = A[i];
k++;
i++;
}
while (j <= r)
{
B[k] = A[j];
k++;
j++;
}
for (i = p; i < r; i++)
{
A[i] = B[i];
}
}
void MergeSort(int A[], int p, int r)
{
int q;
if (p < r)
{
q = (p + r) / 2;
MergeSort(A, p, q);
MergeSort(A, q + 1, r);
Merge(A, p, q, r);
}
}
int main(void)
{
int N[10];
N[0] = 4;
N[1] = 5;
N[2] = 8;
N[3] = 12;
N[4] = 7;
N[5] = 3;
N[6] = 23;
N[7] = 1;
N[8] = 90;
N[9] = 26;
MergeSort(N, 0, 9);
for (int i = 0; i < 10; i++)
{
cout << N[i] << endl;
}
}
The output of program is: 1, 3, 1, 4, 5, 7, 7, 7, 26, 26, which is obviously wrong. However I just don't see what is wrong in code, to me everthing looks good. I googled some C++ codes of MargeSort and try to debug it but i can't find mistake. Anyone see it?

//you have just one err,in last for you missed = :
//err: for(i = p; i < r; i++)
//correct: for(i = p; i <= r; i++)
#include <iostream>
using namespace std;
void Merge(int* A, int p, int q, int r)
{
int B[100], i = 0, j = 0, k = 0;
i = p;
k = p;
j = q + 1;
while (i <= q && j <= r)
{
if (A[i] <= A[j])
{
B[k] = A[i];
k++;
i++;
}
else
{
B[k] = A[j];
k++;
j++;
}
}
while (i <= q)
{
B[k] = A[i];
k++;
i++;
}
while (j <= r)
{
B[k] = A[j];
k++;
j++;
}
for (i = p; i <= r; i++)
{
A[i] = B[i];
}
}
void MergeSort(int A[], int p, int r)
{
int q;
if (p < r)
{
q = (p + r) / 2;
MergeSort(A, p, q);
MergeSort(A, q + 1, r);
Merge(A, p, q, r);
}
}
int main(void)
{
int A[10]={9,8,7,6,5,4,3,2,1,0};
MergeSort(A,0,9);
for (int i = 0; i<10; i++)
{
cout<<A[i]<<",";
}
}
//this is cleaned version of your code:
#include <iostream>
using namespace std;
void Merge(int* A, int p, int q, int r)
{
int* B=new int[r-p+1];
int i = p;
int j = q + 1;
int k = 0;
while (i <= q && j <= r) B[k++] = (A[i] <= A[j])? A[i++] : A[j++];
while (i <= q) B[k++] = A[i++];
while (j <= r) B[k++] = A[j++];
for (i = p; i <= r; i++) A[i] = B[i-p];
delete B;
}
void MergeSort(int* A, int p, int r)
{
if (p >= r) return;
int q = (p + r) / 2;
MergeSort(A, p, q);
MergeSort(A, q + 1, r);
Merge(A, p, q, r);
}
int main(void)
{
int A[15]={10,11,12,13,14,0,8,7,6,5,4,3,2,1,9};
MergeSort(A,0,14);
for (int i = 0; i<15; i++) cout<<A[i]<<",";
}
//this is another answer:
#include <iostream>
#include <climits>
using namespace std;
static void Merge(int* A, int p, int q, int r)
{
int n1 = q - p + 1;// A[p..q]
int n2 = r - q;// A[q+1..r]
int* L = new int[n1 + 1];
int* R = new int[n2 + 1];
int i, j;
for (i = 0; i < n1; i++)
L[i] = A[p + i];
for (i = 0; i < n2; i++)
R[i] = A[q + i+1];
L[n1] = INT_MAX;
R[n2] = INT_MAX;
i = 0;
j = 0;
for (int k = p; k <= r; k++)
A[k] = L[i] <= R[j] ? L[i++] : R[j++];
delete L;
delete R;
}
static void Ascending(int* A, int p, int r)
{
if (p >= r) return;
int q = (p + r) / 2;
Ascending(A, p, q);
Ascending(A, q + 1, r);
Merge(A, p, q, r);
}
int main()
{
int A[10]={9,8,7,6,5,4,3,2,1,0};
Ascending(A,0,9);
for (int i = 0; i<10; i++)
{
cout<<A[i]<<",";
}
}

Related

Segmentation fault with cout in merge sort

I've read many posts but I can't figure out where is my error so I go with it.
My program throws the segfault at the cout<<endl. When I erase it, the program doesn't even print anything. It just prints the segfault. Aparently the program never reach to sort the vector.
#include <iostream>
#include <vector>
using namesapce std
void inserctionSort(std::vector<double> &v, int i, int j)
{
double temp;
for(i; i < v.size(); i++)
{
temp = v[i];
j = i - 1;
while((v[j] > temp) && (j >= 0))
{
v[j+1] = v[j];
j--;
}
v[j+1] = temp;
}
}
void merge_(std::vector<double> &v, int i, int k, int j)
{
std::vector<double> w(v.size());
int n = j - i + 1;
int p = i;
int q = k + 1;
for(int l = 0; l < n; l++)
{
if(p <= k && (q > j || v[p] <= v[q]))
{
w[l] = v[p];
p++;
}else
{
w[l] = v[q];
q++;
}
}
for(int l = 0; l < n; l++)
v[i - 1 + l] = w[l];
}
void mergeSort(std::vector<double> &v, int i, int j)
{
int n = j - i + 1, n0 = 3;
int k;
if(n <= n0)
{
inserctionSort(v,i,j);
}else
{
k = i - 1 + n / 2;
mergeSort(v, i, k);
mergeSort(v, k + 1, j);
merge_(v, i, k, j);
}
}
int main()
{
vector<double> v1 = {3.2,4.1,55.42,2.24,5.424,667.32,35.54};
cout<<"Vector desordenado: ";
for(int i = 0; i < v1.size(); i++)
cout<<v1[i]<<", ";
cout<<"hola";
cout<<endl;
cout<<"hola";
mergeSort(v1, 0, v1.size()-1); //--> Core generado
//quickSort(v1, 0, v1.size()-1);
cout<<"Vector ordenado: ";
for(int i = 0; i < v1.size(); i++)
cout<<v1[i]<<", ";
return 0;
}
You have problems in your code with vector indices assuming value -1 inside a couple of loops.
I have corrected these mistakes below, a working version of your code:
#include <iostream>
#include <vector>
using namespace std;
void inserctionSort(vector<double> &v, int i, int j)
{
int v_size = v.size();
double temp;
for (; i < v_size; i++) {
temp = v[i];
j = i - 1;
while ( (j >= 0) && (v[j] > temp) ) { // swapped conditions, as when j=-1, v[j]>temp is undefined
v[j+1] = v[j];
j--;
}
v[j+1] = temp;
}
}
void merge_(vector<double> &v, int i, int k, int j)
{
vector<double> w( v.size() );
int n = j - i + 1;
int p = i;
int q = k + 1;
for (int l = 0; l < n; l++) {
if ( p <= k && (q > j || v[p] <= v[q]) ) {
w[l] = v[p];
p++;
} else {
w[l] = v[q];
q++;
}
}
for(int l = 0; l < n; l++)
v[i + l] = w[l]; // deleted -1 from v[i - 1 + l], as it leads to v[-1] for i,l = 0
}
void mergeSort(vector<double> &v, int i, int j)
{
int n = j - i + 1, n0 = 3; // n = v.size()
int k;
if (n <= n0) {
inserctionSort(v,i,j);
} else {
k = i - 1 + n / 2;
mergeSort(v, i, k);
mergeSort(v, k + 1, j);
merge_(v, i, k, j);
}
}
int main()
{
vector<double> v1 = {3.2,4.1,55.42,2.24,5.424,667.32,35.54};
cout<<"Vector desordenado: ";
for (unsigned i = 0; i < v1.size(); i++)
cout<<v1[i]<<", ";
cout << "hola";
cout << endl;
cout << "hola";
mergeSort(v1, 0, v1.size()-1); //--> Core generado
//quickSort(v1, 0, v1.size()-1);
cout<<"Vector ordenado: ";
for (unsigned i = 0; i < v1.size(); i++)
cout << v1[i] << ", ";
return 0;
}

C++ Merge Sort returning original vector

I have been attempting to make a merge sort using vectors in C++ and am running into an issue where any vector input is sorted into its original order. I have based the algorithm off the geeks4geeks site here: https://www.geeksforgeeks.org/merge-sort/
So far I have spent about five hours attempting to find the source of the error and it seems that upon ending the merge function the vector somehow goes back to its original format, but I am unsure why. Any suggestions would be much appreciated.
#include <iostream>
#include <vector>
using namespace std;
void merge(vector<int> vect, int p, int q, int r) {
int i, j, k, n1, n2;
n1 = q - p + 1;
n2 = r - q;
vector<int> L, R;
L.resize(n1);
R.resize(n2);
for (i = 0; i < n1; i++) {
L[i] = vect[p + i];
}
for (j = 0; j < n2; j++) {
R[j] = vect[q + 1 + j];
}
i = 0;
j = 0;
k = p;
while (i < n1 && j < n2) {
if (L[i] <= R[j]) {
vect[k] = L[i];
i++;
}
else {
vect[k] = R[j];
j++;
}
k++;
}
while (i < n1) {
vect[k] = L[i];
i++;
k++;
}
while (j < n2) {
vect[k] = R[j];
j++;
k++;
}
}
void mergeSort(vector<int> vect, int p, int r) {
if (p < r) {
int q = (p + r) / 2;
mergeSort(vect, p, q);
mergeSort(vect, q + 1, r);
merge(vect, p, q, r);
}
}
int main() {
vector<int> vect{4,3,5,6,7,8};
mergeSort(vect, 0, vect.size() - 1);
for (int i = 0; i < vect.size(); i++) {
cout << vect[i] << endl;
}
}
First of all you should know the difference between:
pass by value
pass by reference
Go and check it here.
Secondly, you should change your code as it is shown:
#include <iostream>
#include <vector>
//using namespace std; forget about it, start using std::whatever_it_is_in_here
void merge(std::vector<int> &vect, int p, int q, int r) // note the & near vect
{
int i, j, k, n1, n2;
n1 = q - p + 1;
n2 = r - q;
std::vector<int> L, R;
L.resize(n1);
R.resize(n2);
for (i = 0; i < n1; i++) {
L[i] = vect[p + i];
}
for (j = 0; j < n2; j++) {
R[j] = vect[q + 1 + j];
}
i = 0;
j = 0;
k = p;
while (i < n1 && j < n2) {
if (L[i] <= R[j]) {
vect[k] = L[i];
i++;
}
else {
vect[k] = R[j];
j++;
}
k++;
}
while (i < n1) {
vect[k] = L[i];
i++;
k++;
}
while (j < n2) {
vect[k] = R[j];
j++;
k++;
}
}
void mergeSort(std::vector<int> &vect, int p, int r) // note the & near vect
{
if (p < r) {
int q = (p + r) / 2;
mergeSort(vect, p, q);
mergeSort(vect, q + 1, r);
merge(vect, p, q, r);
}
}
int main()
{
std::vector<int> vect{4,3,5,6,7,8};
mergeSort(vect, 0, vect.size() - 1);
for (int i = 0; i < vect.size(); i++)
std::cout << vect[i] << "\n"; // note \n instead of std::endl
return 0; // you forgot the return statement
}
You forgot the return statement in the main function.
Stop using using namespace std. Check why here
Note the "\n" instead of std::endl. You can understand more of it here

Errors Within Void Merge

I've been having problems trying to figure out how to fix this code I wrote for Mergesort.
The intended result was to output a sorted array of inputs, but the void merge function contains errors that result in either an unsorted array or an array of really large or small numbers.
I've tried many times to fix them, but the result still doesn't come out perfectly.
Can you look it over and tell me what I've been doing wrong?
#include "pch.h"
#include <iostream>
using namespace std;
void merge(int* arr, int p, int q, int r) {
//copy A[p.q] into L
//and A[q+1.r] into R
int i, j, k;
int n1 = q - p + 1;
int n2 = r - q;
int* L = new int[n1+1];
int* R = new int[n2+1];
for (i = 1; i <= n1; i++) {
L[i] = arr[p+i-1];
}
for (j = 1; j <= n2; j++){
R[j] = arr[q+j];
}
L[n1+1] = 99999;
R[n2+1] = 99999; //represents infinity
i = j = 1;
for (k = p; k <= r; k++)
{
if (L[i] <= R[j]) {
arr[k] = L[i];
i = i + 1;
}
else {
arr[k] = R[j];
j = j + 1;
}
return;
}
}
void mergesort(int* arr, int p, int r) {
if (p < r) {
int q = floor((p + r) / 2);
mergesort(arr, p, q);
mergesort(arr, q + 1, r);
merge(arr, p, q, r);
}
return;
}
int main() {
int r;
cin >> r;
int* arr = new int[r];
for (int i = 0; i < r; i++) {
int num;
cin >> num;
arr[i] = num;
}
int p = 0;
//sortint function
mergesort(arr,p,r);
for (int i = 0; i < r; i++) {
cout << arr[i] << ";";
}
return 0;
}

Merge_sort without sentinel

Can someone please tell me why I am getting garbage value after sorting?
Initial call is (A,0,n) where n is the size of array? I want to sort the array using merge sort algorithm but without sentinel value.
void merge_sort(int A[], int l, int mid, int r)
{
int n1 = mid - l + 1;
int n2 = r - mid;
int L[n1], R[n2];
for (int i = 0; i < n1; i++)
{
L[i] = A[i];
}
for (int i = 0; i <= n2; i++)
{
R[i] = A[i + mid + 1];
}
cout << endl;
int j = 0, k = 0;
for (int i = l; i < r; i++)
{
if (j == n1 || k == n2)
{
if (j == n1 + 1)
{
A[i] = R[k];
k++;
}
else
{
A[i] = L[j];
j++;
}
}
else if (L[j] >= R[k])
{
A[i] = L[j];
j++;
}
else
{
A[i] = R[k];
k++;
}
}
}
void merge_divide(int A[], int l, int r)
{
if (l < r)
{
int mid = (l + r) / 2;
merge_divide(A, l, mid);
merge_divide(A, mid + 1, r);
merge_sort(A, l, mid, r);
}
}
There are a lot of moves in your logic that is hard to read. It is hard to distinguish where is an error or there is some intention here. But here it is how I see it with fixes. See inline comments.
void merge_sort(int A[], int l, int mid, int r) {
int n1 = mid - l;
int n2 = r - mid;
// this is C, but not C++, consider using vector instead
int L[n1], R[n2];
for (int i = 0; i < n1; i++) {
// need `l` here
L[i] = A[l + i];
}
for (int i = 0; i < n2; i++) {
// need to include `mid`
R[i] = A[i + mid];
}
int j = 0, k = 0;
for (int i = l; i < r; i++) {
if (j == n1) {
A[i] = R[k];
k++;
} else if (k == n2) {
A[i] = L[j];
j++;
} else if (L[j] >= R[k]) {
A[i] = L[j];
j++;
} else {
A[i] = R[k];
k++;
}
}
}
void merge_divide(int A[], int l, int r) {
// need properly compute `mid` here
int mid = r - l;
if (mid > 1) {
mid = l + mid / 2;
merge_divide(A, l, mid);
merge_divide(A, mid, r);
merge_sort(A, l, mid, r);
}
}
int main() {
int A[] = {2, 4, 3, 382, 2342334, 3, 42, 234};
int n = sizeof(A) / sizeof(int);
merge_divide(A, 0, n);
for (int i = 0; i < n; ++i)
cerr << A[i] << " ";
cout << endl;
}

mergesort in C++

#include "stdafx.h"
#include <iostream>
using namespace std;
using namespace System;
void mergesort(int a[], int p, int r);
void merge(int a[], int p, int q, int r);
int main(array<System::String ^> ^args)
{
int result[2] = { 1, 0 };
int *p;
p = result;
mergesort(p, 0,1);
while (1);
return 0;
}
void mergesort(int a[],int p, int r)
{
if (p < r)
{
int q = (p + r) / 2;
mergesort(a, p, q);
cout << endl;
mergesort(a, q + 1, r);
cout << endl;
merge(a,p,q,r);
for (int i = 0; i < 2; i++)
{
cout << a[i] << " ";
}
cout << endl;
}
}
void merge(int a[], int p, int q, int r)
{
int left[100] = {};
int right[100] = {};
for (int i = 0; i < (q - p + 1); i++)
{
left[i] = *(a + p + i);
left[i + 1] = 999;
}
for (int i = 0; i < (r - q); i++)
{
right[i] = *(a + q + 1 + i);
right[i + 1] = 999;
}
for (int k = p; k < r+1; k++)
{
int i = 0;
int j = 0;
if (left[i] <= right[j])
{
a[k] = left[i++];
}
else
{
a[k] = right[j++]; **// it always goes into this route? why does not left[i]<=right[j] work?**
}
}
}
Here is my code about a basic merge sort. I cannot enter the first IF statement in the merge function. Why does if (left[i] <= right[j]) not work? I have tried may time whatever the left[i] is. The program just goes to the else statement.
for (int k = p; k < r+1; k++)
{
int i = 0;
int j = 0;
if (left[i] <= right[j])
{
a[k] = left[i++];
}
else
{
a[k] = right[j++]; **// it always goes into this route? why does not left[i]<=right[j] work?**
}
}
This does not do what you think it does. It will always compare left[0] with right[0], because you declare i and j inside the for loop, so they will be reset to 0 on each iteration.
To make them retain their values, declare them outside the loop:
int i = 0;
int j = 0;
for (int k = p; k < r+1; k++)
{
if (left[i] <= right[j])
{
a[k] = left[i++];
}
else
{
a[k] = right[j++]; **// it always goes into this route? why does not left[i]<=right[j] work?**
}
}
If your intent is to use variables i and j in the loop only then try to restrict the scope of i and j to the loop by doing following.
for (int k = p, i = 0, j = 0; k < r+1; k++)
{
if (left[i] <= right[j])
{
a[k] = left[i++];
}
else
{
a[k] = right[j++];
}
}