Check if 2 arrays are same or not (C++) - c++

I want to compare two int arrays and find if they are the same and if they are not i want to find the min and the max number that exist in one but not in the other. I use this code in c++ but seems to run into a segmentation fault 11. I would be grateful if someone points out the mistake to me.I would like to see better solutions if there are any.
+ I did the mergesort for time limit of 1 second.
#include <iostream>
using namespace std;
void merge(int *a,int s,int e)
{
int mid = (s+e)/2;
int i = s;
int j = mid+1;
int k = s;
int temp[100];
while(i<=mid && j<=e)
{
if(a[i] < a[j])
{
temp[k++] = a[i++];
}
else
{
temp[k++] = a[j++];
}
}
while(i<=mid)
{
temp[k++] = a[i++];
}
while(j<=e)
{
temp[k++] = a[j++];
}
for(int i=s;i<=e;i++)
{
a[i] = temp[i];
}
}
void mergeSort(int a[],int s,int e)
{
if(s>=e)
{
return;
}
int mid = (s+e)/2;
mergeSort(a,s,mid);
mergeSort(a,mid+1,e);
merge(a,s,e);
}
int min_array (int array1[],int n1)
{
int min = array1[0];
for(int i=1;i<n1;i++)
if(array1[i] < min)
min = array1[i];
return min;
}
int max_array (int array2[],int n2)
{
int max = array2[0];
for(int i=1;i<n2;i++)
if(array2[i] > max)
max = array2[i];
return max;
}
void check_same(int a[], int b[], int n)
{
bool check = true;
int check1 = 2, check2 = 2, counter1 = 0, counter2 = 0, i, j;
int pos1[n], pos2[n];
mergeSort(a, 0, n);
mergeSort(b, 0, n);
for(i=0; i<n; i++)
{
if (a[i] != b[i])
check = false;
for(j=0; j<n; j++)
{
if (a[i] != b[j])
check1 = 0;
else if (a[i] == b[j])
check1 = 1;
else if (a[j] != b[i])
check2 = 0;
else if (a[j] == b[i])
check2 = 1;
if (check1 == 1 && check2 == 1)
break;
}
if (check1 == 0)
pos1[counter1++] = i;
else if (check2 == 0)
pos2[counter2++] = i;
}
int differents[counter1 + counter2];
if (counter1 < counter2)
{
for (i=0; i<counter1; i++)
differents[i] = a[pos1[i]];
for (i=counter1; i<counter2; i++)
differents[i] = b[pos2[counter2 - i]];
}
else
{
for (i=0; i<counter2; i++)
differents[i] = b[pos2[i]];
for (i=counter2; i<counter1; i++)
differents[i] = a[pos1[counter1 - i]];
}
if (check)
cout << "yes\n";
else if (check == false)
cout << "no " << min_array(differents, counter1+counter2)<< " " << max_array(differents, counter1+counter2) << endl;
}
int main()
{
int N, i;
cin >> N;
int A[50000], B[50000];
for (i=0;i<N;i++)
cin >> A[i];
for (i=0;i<N;i++)
cin >> B[i];
check_same(A, B, N);
}

Your code is not standard C++, the line int pos1[n], pos2[n]; in check_same is invalid because n is not a compile time constant - VLAs are only allowed in C.
You could make use of the standard library for all of that:
#include <algorithm>
#include <iostream>
#include <iterator>
#include <vector>
void check_same(int a[], int b[], int n) {
std::sort(a, a + n);
std::sort(b, b + n);
if(std::equal(a, a + n, b)) {
std::cout << "yes\n";
} else {
std::vector<int> elements_not_in_both;
std::set_symmetric_difference(a, a + n,
b, b + n,
std::back_inserter(elements_not_in_both));
auto [min, max] = std::minmax_element(elements_not_in_both.cbegin(),
elements_not_in_both.cend());
std::cout << "no " << *min << " " << *max << '\n';
}
}
int main()
{
int N;
std::cin >> N;
int A[50000], B[50000];
for (int i=0; i<N; i++)
std::cin >> A[i];
for (int i=0; i<N; i++)
std::cin >> B[i];
check_same(A, B, N);
}
Live demo.
An even better solution is to not use C-style arrays either, then you don't allocate way too much stack space for small input arrays and you can't have too little space when someone decides to run this on more than 50000 elements:
#include <algorithm>
#include <iostream>
#include <iterator>
#include <vector>
void check_same(std::vector<int>& a, std::vector<int>& b) {
std::sort(a.begin(), a.end());
std::sort(b.begin(), b.end());
if(a == b) {
std::cout << "yes\n";
} else {
std::vector<int> elements_not_in_both;
std::set_symmetric_difference(a.cbegin(), a.cend(),
b.cbegin(), b.cend(),
std::back_inserter(elements_not_in_both));
auto [min, max] = std::minmax_element(elements_not_in_both.cbegin(),
elements_not_in_both.cend());
std::cout << "no " << *min << " " << *max << '\n';
}
}
int main()
{
int N;
std::cin >> N;
std::vector<int> a, b;
a.reserve(N);
b.reserve(N);
std::copy_n(std::istream_iterator<int>(std::cin), N, std::back_inserter(a));
std::copy_n(std::istream_iterator<int>(std::cin), N, std::back_inserter(b));
check_same(a, b);
}

Please check out for these points for solving segmentation fault issue:
merge function
1) Is this statement int k = s; correct? Shouldn't it be int k = 0;
2) Is this allocation int temp[100]; OK? Or Should it be int temp[e - s + 1];
3) Is this statement a[i] = temp[i]; correct? Shouldn't it be a[i] = temp[i - s];
4) Do you need to have base condition s < e or something? i.e. Handling the case when s == e.
check_same function
1) Is this call mergeSort(a, 0, n); correct? Shouldn't it be mergeSort(a, 0, n - 1);
As far as better approach is concerned, it can be solved in O(n) using hashing.
#include <iostream>
#include <vector>
#include <unordered_set>
using namespace std;
void check_same(int a[], int b[], int n) {
int minNotInA, maxNotInA, minNotInB, maxNotInB;
bool elementMissingInA = false, elementMissingInB = false;
{
unordered_set<int> elementsInB;
for (int i = 0; i < n; i++) {
elementsInB.insert(b[i]);
}
for (int i = 0; i < n; i++) {
if (elementsInB.find(a[i]) == elementsInB.end()) {
if (!elementMissingInA) {
elementMissingInA = true;
minNotInB = maxNotInB = a[i];
} else {
if (minNotInB > a[i]) {
minNotInB = a[i];
} else if (maxNotInB < a[i]) {
maxNotInB = a[i];
}
}
}
}
}
if (elementMissingInA) {
unordered_set<int> elementsInA;
for (int i = 0; i < n; i++) {
elementsInA.insert(a[i]);
}
for (int i = 0; i < n; i++) {
if (elementsInA.find(b[i]) == elementsInA.end()) {
if (!elementMissingInB) {
elementMissingInB = true;
minNotInA = maxNotInA = b[i];
} else {
if (minNotInA > b[i]) {
minNotInA = b[i];
} else if (maxNotInA < b[i]) {
maxNotInA = b[i];
}
}
}
}
}
if (elementMissingInA and elementMissingInB) {
cout << "no " << min(minNotInA, minNotInB) << " " << max(maxNotInA, maxNotInB) << "\n";
} else {
cout << "yes\n";
}
}
int main()
{
int N;
std::cin >> N;
int A[50000], B[50000];
for (int i=0; i<N; i++)
std::cin >> A[i];
for (int i=0; i<N; i++)
std::cin >> B[i];
check_same(A, B, N);
return 0;
}

Thank all of you for your interest and your help.
Because i am not used to those kinds of libraries you use and i dont want to study them at the moment(i am just in the first semester of my ece class) i corrected my code(both improved it and fixed the segmentation fault 11)
You can take a look right here.
#include <iostream>
using namespace std;
void merge(int *a, int s, int e)
{
int mid = (s + e) / 2;
int i = s;
int j = mid + 1;
int k = s;
int temp[50000];
while (i <= mid && j <= e)
{
if (a[i] < a[j])
{
temp[k++] = a[i++];
}
else
{
temp[k++] = a[j++];
}
}
while (i <= mid)
{
temp[k++] = a[i++];
}
while (j <= e)
{
temp[k++] = a[j++];
}
for (int i = s; i <= e; i++)
{
a[i] = temp[i];
}
}
void mergeSort(int a[], int s, int e)
{
if (s >= e)
{
return;
}
int mid = (s + e) / 2;
mergeSort(a, s, mid);
mergeSort(a, mid + 1, e);
merge(a, s, e);
}
int min_array(int array1[], int n1)
{
int min = array1[0];
for (int i = 1; i<n1; i++)
if (array1[i] < min)
min = array1[i];
return min;
}
int max_array(int array2[], int n2)
{
int max = array2[0];
for (int i = 1; i<n2; i++)
if (array2[i] > max)
max = array2[i];
return max;
}
void check_same(int a[], int b[], int n)
{
int differents[50000];
int counter1 = 0, counter2 = 0;
int i = 0, j = 0;
while (i < n && j < n)
{
if (a[i] < b[j])
{
differents[counter1++ + counter2] = a[i];
i++;
}
else if (b[j] < a[i])
{
differents[counter2++ + counter1] = b[j];
j++;
}
else
{
i++;
j++;
}
}
if (counter1 == 0 && counter2 == 0)
cout << "yes\n";
else
cout << "no " << min_array(differents, counter1 + counter2) << " " << max_array(differents, counter1 + counter2) << endl;
}
int main()
{
int A[50000], B[50000];
int N, i;
cin >> N;
for (i = 0; i<N; i++)
cin >> A[i];
for (i = 0; i<N; i++)
cin >> B[i];
mergeSort(A, 0, N-1);
mergeSort(B, 0, N-1);
check_same(A, B, N);
return 0;
}

Related

Quick Sorting in C++ is working intermittently

What is wrong with my quick sorting algorithm? Sometimes it gives the right answer, sometimes it doesn't. Here's my code.
#include <iomanip>
#include <iostream>
using namespace std;
void foo(int*, int, int);
int main()
{
int* a, n;
cin >> n;
a = new int[n];
srand(time(NULL));
for (int i = 0; i <= n - 1; i++)
{
a[i] = rand() % 100;
cout << setw(3) << a[i];
}
cout << endl;
cout << "sorting array" << endl;
foo(a, 0, n - 1);
for (int i = 0; i <= n - 1; i++)
cout << setw(3) << a[i];
cout << endl;
return 0;
}
void foo(int* a, int left, int right)
{
int j = right;
int i = left;
int mid = (i + j) / 2;
while (i < j)
{
while (a[i] < a[mid]) i++;
while (a[j] > a[mid]) j--;
if (i <= j)
{
swap(a[i], a[j]); i++; j--;
}
}
if (i < right)
foo(a, i, right);
if (left < j) foo(a, left, j);
}
I've done some changed to my program And it started working properly, the problem is that I don't understand why. I mentioned the changed in the code below. All the expected outputs matches the result.
#include <iomanip>
#include <iostream>
using namespace std;
void foo(int*, int, int);
int main()
{
int* a, n;
cin >> n;
a = new int[n];
srand(time(NULL));
for (int i = 0; i <= n - 1; i++)
{
a[i] = rand() % 100;
cout << setw(3) << a[i];
}
cout << endl;
cout << "sorting array" << endl;
foo(a, 0, n - 1);
for (int i = 0; i <= n - 1; i++)
cout << setw(3) << a[i];
cout << endl;
return 0;
}
void foo(int* a, int left, int right)
{
int j = right;
int i = left;
int mid = (a[right] + a[left]) / 2;//CHANGED LINE from mid=(i+j)/2
while (i < j)
{
while (a[i] < mid) i++; //CHANGED LINE from a[i]<a[mid]
while (a[j] > mid) j--; //CHANGED LINE from a[j]>a[mid]
if (i <= j)
{
swap(a[i], a[j]); i++; j--;
}
}
if (i < right)
foo(a, i, right);
if (left < j) foo(a, left, j);
}

Replacing nested for loops in C++

So I wrote this code but the problem is I have a restriction in my assignment that I can't use nested for loops in my code.
#include<iostream>
using namespace std;
void Exchange(int* a, int* b) {
int var;
var = *a; //For swapping or exchanging values. O_o
*a = *b;
*b = var;
}
void Algorithm(int array[], int nerd) {
int i, j, k; //This is the actual algorithm which is required. ;)
for (i = 0; i < nerd;) {
for (j = i + 1; j < nerd; j++) {
if (array[j] < array[j - 1])
Exchange(&array[j], &array[j - 1]);
}
nerd--;
for (k = nerd - 1; k > i; k--) {
if (array[k] < array[k - 1])
Exchange(&array[k], &array[k - 1]);
}
i++;
}
}
int main() {
int n, i;
cout << "\nEnter the count of numbers for the algorithm: ";
cin >> n;
int arr[10];
for (i = 0; i < n; i++) {
cout << "Enter number " << i + 1 << ": ";
cin >> arr[i];
}
Algorithm(arr, n);
cout << "\nFinal Data you entered (after the algorithm performed)";
for (i = 0; i < n; i++)
cout << " -> " << arr[i];
return 0;
}
One loop using modulus on the one loop counter:
#include <utility> // std::swap
void Algorithm(int array[], int nerd) {
int max = nerd * (nerd - 1);
for(int i = 1; i < max; ++i) {
// If at start of the removed inner loop, skip i % nerd == 0
if(i % nerd == 0) ++i;
if (array[i % nerd] < array[(i-1) % nerd])
std::swap(array[i % nerd], array[(i - 1) % nerd]);
}
}
Demo
Without modulus, decreasing nerd and restarting with i = 1 each time i == nerd:
void Algorithm(int array[], int nerd) {
for(int i = 1; nerd > 1; ++i) {
if(i == nerd) { // start of the removed inner loop
--nerd; // the highest number will already be in place
i = 1;
}
if (array[i] < array[i - 1])
std::swap(array[i], array[i - 1]);
}
std::cout << "ted " << nerd << '\n';
}
Demo
An alternative to quit looping early if no swaps were made last round:
void Algorithm(int array[], int nerd) {
if(nerd < 2) return;
bool done = true;
for(int i = 1;; ++i) {
if(i % nerd == 0) {
if(done) break;
++i;
done = true;
}
if (array[i % nerd] < array[(i-1) % nerd]) {
std::swap(array[i % nerd], array[(i-1) % nerd]);
done = false;
}
}
}
Demo
The alternative without modulus and with the decreasing nerd optimization:
void Algorithm(int array[], int nerd) {
if(nerd < 2) return;
bool done = true;
for(int i = 1;; ++i) {
if(i == nerd) {
if(done || --nerd == 1) break;
i = 1;
done = true;
}
if (array[i] < array[i - 1]) {
std::swap(array[i], array[i - 1]);
done = false;
}
}
}
Demo

HackerRank says ~no response on stdout~. C++

I wrote this solution for the absolute permutation problem on HackerRank. It works fine on dev-C++ but doesn't work on Hackerrank. I've found that the code produces output when I remove the abs_perm(). What's the problem here?
#include <iostream>
using namespace std;
int arr[100000];
int check(int n, int k)
{
if ( (2*k == n) || (k == 0) || (n - 4*k == 0) )
return 1;
else if (k < n/2)
return check(n - 4*k, k);
else
return 0;
}
void swap(int &a, int &b)
{
int c = b;
b = a;
a = c;
}
void ini(int n)
{
for (int i = 0; i < n; i++)
{
arr[i] = i+1;
}
}
void abs_perm(int n, int k)
{
for (int i = 0; i < k; i++)
{
swap(arr[i], arr[k+i]);
}
if (2*k == n)
return;
for (int i = n - 1; i > n - k - 1; i--)
{
swap(arr[i], arr[i-k]);
}
if (n - 4*k == 0)
return;
abs_perm(n - 4*k, k);
}
int main()
{
int T;
cin >> T;
int N[T], K[T];
for (int i = 0; i < T; i++)
{
cin >> N[i] >> K[i];
}
for (int i = 0; i < T; i++)
{
cout << N[i] << " " << K[i] << "\n";
}
for (int i = 0; i < T; i++)
{
if ( !check(N[i], K[i]) )
cout << "-1\n";
else
{
ini(N[i]);
abs_perm(N[i], K[i]);
for (int j = 0; j < N[i]; j++)
{
cout << arr[j] << " ";
}
cout << "\n";
}
}
return 0;
}
Array is a structure to use when you know at compile time the dimension of your structure. What you wrote at the begin in abs_perm() is not correct for standard compilers (in fact you don't know the dimension of your array). You can use a std::vector or a std::list which allocate memory dynamically or (bad solution) you can allocate an array with dimension that certainly contains all elements you will put inside.

Why does this code produce a segfault?

Code:
#include <iostream>
using namespace std;
void mix(int *a, int *b, int *c, int m, int n)
{
int i, j = 0;
for(i = 0; i < m; i++)
{
if(a[i] % 2 == 0)
{
c[j] = a[i];
j++;
}
}
for(i = m - 1; i >= 0; i++)
{
if(a[i] % 2 == 1)
{
c[j] = a[i];
j++;
}
}
for(i = 0; i < n; i++)
{
if(b[i] % 2 == 0)
{
c[j] = b[i];
j++;
}
}
for(i = n - 1; i >= 0; i++)
{
if(b[i] % 2 == 1)
{
c[j] = b[i];
j++;
}
}
cout << j << ' ';
}
int main()
{
int a[10], b[10], c[20], m, n;
cout << "m: ";
cin >> m;
cout << "\nn: ";
cin >> n;
int i;
for(i = 0; i < m; i++)
{
cin >> a[i];
}
for(i = 0; i < n; i++)
{
cin >> b[i];
}
mix(a, b, c, m, n);
for(i = 0; i < (m+n); i++)
{
cout << c[i];
}
return 0;
}
I've checked and rechecked the sizes of my arrays and I cannot figure out why the code produces a segfault in the mix(...) function. Could it be a problem of using -O2 optimisation? Furthermore, I've made sure the indices match up. I think the problem is with c[j] = a[i], but I do not understand why that would be causing this segmentation fault.
for these two loop you were doing i++ instead of i--
for(i = m - 1; i >= 0; i--)
{
if(a[i] % 2 == 1)
{
c[j] = a[i];
j++;
}
}
for(i = n - 1; i >= 0; i--)
{
if(b[i] % 2 == 1)
{
c[j] = b[i];
j++;
}
}

implementing merge sort in C++

I have studied the theory of the merge sort but don't have any idea of how to implement it in C++. My question is, merge sort creates arrays in recursion. But when implementing, how do we create arrays in runtime? or what is the general approach for this?
Thanks.
To answer the question: Creating dynamically sized arrays at run-time is done using std::vector<T>. Ideally, you'd get your input using one of these. If not, it is easy to convert them. For example, you could create two arrays like this:
template <typename T>
void merge_sort(std::vector<T>& array) {
if (1 < array.size()) {
std::vector<T> array1(array.begin(), array.begin() + array.size() / 2);
merge_sort(array1);
std::vector<T> array2(array.begin() + array.size() / 2, array.end());
merge_sort(array2);
merge(array, array1, array2);
}
}
However, allocating dynamic arrays is relatively slow and generally should be avoided when possible. For merge sort you can just sort subsequences of the original array and in-place merge them. It seems, std::inplace_merge() asks for bidirectional iterators.
Based on the code here: http://cplusplus.happycodings.com/algorithms/code17.html
// Merge Sort
#include <iostream>
using namespace std;
int a[50];
void merge(int,int,int);
void merge_sort(int low,int high)
{
int mid;
if(low<high)
{
mid = low + (high-low)/2; //This avoids overflow when low, high are too large
merge_sort(low,mid);
merge_sort(mid+1,high);
merge(low,mid,high);
}
}
void merge(int low,int mid,int high)
{
int h,i,j,b[50],k;
h=low;
i=low;
j=mid+1;
while((h<=mid)&&(j<=high))
{
if(a[h]<=a[j])
{
b[i]=a[h];
h++;
}
else
{
b[i]=a[j];
j++;
}
i++;
}
if(h>mid)
{
for(k=j;k<=high;k++)
{
b[i]=a[k];
i++;
}
}
else
{
for(k=h;k<=mid;k++)
{
b[i]=a[k];
i++;
}
}
for(k=low;k<=high;k++) a[k]=b[k];
}
int main()
{
int num,i;
cout<<"*******************************************************************
*************"<<endl;
cout<<" MERGE SORT PROGRAM
"<<endl;
cout<<"*******************************************************************
*************"<<endl;
cout<<endl<<endl;
cout<<"Please Enter THE NUMBER OF ELEMENTS you want to sort [THEN
PRESS
ENTER]:"<<endl;
cin>>num;
cout<<endl;
cout<<"Now, Please Enter the ( "<< num <<" ) numbers (ELEMENTS) [THEN
PRESS ENTER]:"<<endl;
for(i=1;i<=num;i++)
{
cin>>a[i] ;
}
merge_sort(1,num);
cout<<endl;
cout<<"So, the sorted list (using MERGE SORT) will be :"<<endl;
cout<<endl<<endl;
for(i=1;i<=num;i++)
cout<<a[i]<<" ";
cout<<endl<<endl<<endl<<endl;
return 1;
}
I have completed #DietmarKühl s way of merge sort. Hope it helps all.
template <typename T>
void merge(vector<T>& array, vector<T>& array1, vector<T>& array2) {
array.clear();
int i, j, k;
for( i = 0, j = 0, k = 0; i < array1.size() && j < array2.size(); k++){
if(array1.at(i) <= array2.at(j)){
array.push_back(array1.at(i));
i++;
}else if(array1.at(i) > array2.at(j)){
array.push_back(array2.at(j));
j++;
}
k++;
}
while(i < array1.size()){
array.push_back(array1.at(i));
i++;
}
while(j < array2.size()){
array.push_back(array2.at(j));
j++;
}
}
template <typename T>
void merge_sort(std::vector<T>& array) {
if (1 < array.size()) {
std::vector<T> array1(array.begin(), array.begin() + array.size() / 2);
merge_sort(array1);
std::vector<T> array2(array.begin() + array.size() / 2, array.end());
merge_sort(array2);
merge(array, array1, array2);
}
}
I've rearranged the selected answer, used pointers for arrays and user input for number count is not pre-defined.
#include <iostream>
using namespace std;
void merge(int*, int*, int, int, int);
void mergesort(int *a, int*b, int start, int end) {
int halfpoint;
if (start < end) {
halfpoint = (start + end) / 2;
mergesort(a, b, start, halfpoint);
mergesort(a, b, halfpoint + 1, end);
merge(a, b, start, halfpoint, end);
}
}
void merge(int *a, int *b, int start, int halfpoint, int end) {
int h, i, j, k;
h = start;
i = start;
j = halfpoint + 1;
while ((h <= halfpoint) && (j <= end)) {
if (a[h] <= a[j]) {
b[i] = a[h];
h++;
} else {
b[i] = a[j];
j++;
}
i++;
}
if (h > halfpoint) {
for (k = j; k <= end; k++) {
b[i] = a[k];
i++;
}
} else {
for (k = h; k <= halfpoint; k++) {
b[i] = a[k];
i++;
}
}
// Write the final sorted array to our original one
for (k = start; k <= end; k++) {
a[k] = b[k];
}
}
int main(int argc, char** argv) {
int num;
cout << "How many numbers do you want to sort: ";
cin >> num;
int a[num];
int b[num];
for (int i = 0; i < num; i++) {
cout << (i + 1) << ": ";
cin >> a[i];
}
// Start merge sort
mergesort(a, b, 0, num - 1);
// Print the sorted array
cout << endl;
for (int i = 0; i < num; i++) {
cout << a[i] << " ";
}
cout << endl;
return 0;
}
#include <iostream>
using namespace std;
template <class T>
void merge_sort(T array[],int beg, int end){
if (beg==end){
return;
}
int mid = (beg+end)/2;
merge_sort(array,beg,mid);
merge_sort(array,mid+1,end);
int i=beg,j=mid+1;
int l=end-beg+1;
T *temp = new T [l];
for (int k=0;k<l;k++){
if (j>end || (i<=mid && array[i]<array[j])){
temp[k]=array[i];
i++;
}
else{
temp[k]=array[j];
j++;
}
}
for (int k=0,i=beg;k<l;k++,i++){
array[i]=temp[k];
}
delete temp;
}
int main() {
float array[] = {1000.5,1.2,3.4,2,9,4,3,2.3,0,-5};
int l = sizeof(array)/sizeof(array[0]);
merge_sort(array,0,l-1);
cout << "Result:\n";
for (int k=0;k<l;k++){
cout << array[k] << endl;
}
return 0;
}
The problem with merge sort is the merge, if you don't actually need to implement the merge, then it is pretty simple (for a vector of ints):
#include <algorithm>
#include <vector>
using namespace std;
typedef vector<int>::iterator iter;
void mergesort(iter b, iter e) {
if (e -b > 1) {
iter m = b + (e -b) / 2;
mergesort(b, m);
mergesort(m, e);
inplace_merge(b, m, e);
}
}
I know this question has already been answered, but I decided to add my two cents. Here is code for a merge sort that only uses additional space in the merge operation (and that additional space is temporary space which will be destroyed when the stack is popped). In fact, you will see in this code that there is not usage of heap operations (no declaring new anywhere).
Hope this helps.
void merge(int *arr, int size1, int size2) {
int temp[size1+size2];
int ptr1=0, ptr2=0;
int *arr1 = arr, *arr2 = arr+size1;
while (ptr1+ptr2 < size1+size2) {
if (ptr1 < size1 && arr1[ptr1] <= arr2[ptr2] || ptr1 < size1 && ptr2 >= size2)
temp[ptr1+ptr2] = arr1[ptr1++];
if (ptr2 < size2 && arr2[ptr2] < arr1[ptr1] || ptr2 < size2 && ptr1 >= size1)
temp[ptr1+ptr2] = arr2[ptr2++];
}
for (int i=0; i < size1+size2; i++)
arr[i] = temp[i];
}
void mergeSort(int *arr, int size) {
if (size == 1)
return;
int size1 = size/2, size2 = size-size1;
mergeSort(arr, size1);
mergeSort(arr+size1, size2);
merge(arr, size1, size2);
}
int main(int argc, char** argv) {
int num;
cout << "How many numbers do you want to sort: ";
cin >> num;
int a[num];
for (int i = 0; i < num; i++) {
cout << (i + 1) << ": ";
cin >> a[i];
}
// Start merge sort
mergeSort(a, num);
// Print the sorted array
cout << endl;
for (int i = 0; i < num; i++) {
cout << a[i] << " ";
}
cout << endl;
return 0;
}
Here's a way to implement it, using just arrays.
#include <iostream>
using namespace std;
//The merge function
void merge(int a[], int startIndex, int endIndex)
{
int size = (endIndex - startIndex) + 1;
int *b = new int [size]();
int i = startIndex;
int mid = (startIndex + endIndex)/2;
int k = 0;
int j = mid + 1;
while (k < size)
{
if((i<=mid) && (a[i] < a[j]))
{
b[k++] = a[i++];
}
else
{
b[k++] = a[j++];
}
}
for(k=0; k < size; k++)
{
a[startIndex+k] = b[k];
}
delete []b;
}
//The recursive merge sort function
void merge_sort(int iArray[], int startIndex, int endIndex)
{
int midIndex;
//Check for base case
if (startIndex >= endIndex)
{
return;
}
//First, divide in half
midIndex = (startIndex + endIndex)/2;
//First recursive call
merge_sort(iArray, startIndex, midIndex);
//Second recursive call
merge_sort(iArray, midIndex+1, endIndex);
merge(iArray, startIndex, endIndex);
}
//The main function
int main(int argc, char *argv[])
{
int iArray[10] = {2,5,6,4,7,2,8,3,9,10};
merge_sort(iArray, 0, 9);
//Print the sorted array
for(int i=0; i < 10; i++)
{
cout << iArray[i] << endl;
}
return 0;
}
This would be easy to understand:
#include <iostream>
using namespace std;
void Merge(int *a, int *L, int *R, int p, int q)
{
int i, j=0, k=0;
for(i=0; i<p+q; i++)
{
if(j==p) //When array L is empty
{
*(a+i) = *(R+k);
k++;
}
else if(k==q) //When array R is empty
{
*(a+i) = *(L+j);
j++;
}
else if(*(L+j) < *(R+k)) //When element in L is smaller than element in R
{
*(a+i) = *(L+j);
j++;
}
else //When element in R is smaller or equal to element in L
{
*(a+i) = *(R+k);
k++;
}
}
}
void MergeSort(int *a, int len)
{
int i, j;
if(len > 1)
{
int p = len/2 + len%2; //length of first array
int q = len/2; //length of second array
int L[p]; //first array
int R[q]; //second array
for(i=0; i<p; i++)
{
L[i] = *(a+i); //inserting elements in first array
}
for(i=0; i<q; i++)
{
R[i] = *(a+p+i); //inserting elements in second array
}
MergeSort(&L[0], p);
MergeSort(&R[0], q);
Merge(a, &L[0], &R[0], p, q); //Merge arrays L and R into A
}
else
{
return; //if array only have one element just return
}
}
int main()
{
int i, n;
int a[100000];
cout<<"Enter numbers to sort. When you are done, enter -1\n";
i=0;
while(true)
{
cin>>n;
if(n==-1)
{
break;
}
else
{
a[i] = n;
i++;
}
}
int len = i;
MergeSort(&a[0], len);
for(i=0; i<len; i++)
{
cout<<a[i]<<" ";
}
return 0;
}
This is my version (simple and easy):
uses memory only twice the size of original array.
[ a is the left array ] [ b is the right array ] [ c used to merge a and b ] [ p is counter for c ]
void MergeSort(int list[], int size)
{
int blockSize = 1, p;
int *a, *b;
int *c = new int[size];
do
{
for (int k = 0; k < size; k += (blockSize * 2))
{
a = &list[k];
b = &list[k + blockSize];
p = 0;
for (int i = 0, j = 0; i < blockSize || j < blockSize;)
{
if ((j < blockSize) && ((k + j + blockSize) >= size))
{
++j;
}
else if ((i < blockSize) && ((k + i) >= size))
{
++i;
}
else if (i >= blockSize)
{
c[p++] = b[j++];
}
else if (j >= blockSize)
{
c[p++] = a[i++];
}
else if (a[i] >= b[j])
{
c[p++] = b[j++];
}
else if (a[i] < b[j])
{
c[p++] = a[i++];
}
}
for (int i = 0; i < p; i++)
{
a[i] = c[i];
}
}
blockSize *= 2;
} while (blockSize < size);
}