Reputation: 240
I'm trying to implement mergesort in cpp, I'm having some trouble with the proper syntax with vectors, in particular the part inside the for loop where I'm merging the elements. Some help would be appreciated. My code so far gives the wrong output. Also, I was wondering if this code could be modified to count inversions as well, everytime I go in the else case, inversions increase but it's missing corner cases. I tried doing the v[i] = left[i1]
as v.insert(v.begin() + i, left.at(i1))
, which also did not work, I'm in general confused about the []
operator for vectors, how is it different than array []
operator?
#include <bits/stdc++.h>
using namespace std;
void mergeSort(vector<int>& v) {
if(v.size() > 1) {
vector<int> left(v.begin(), v.begin() + v.size()/2);
vector<int> right(v.begin() + v.size()/2, v.end());
mergeSort(left);
mergeSort(right);
int i1 = 0;
int i2 = 0;
for(int i = 0; i < v.size(); i++) {
if(i2 >= right.size() || (i1 < left.size() && left[i] < right[i])) {
v[i] = left[i1]; i1++;
} else {
v[i] = right[i2]; i2++;
}
}
}
}
int main() {
vector<int> v = {22, 18, 12, -4, 58, 7, 31, 42};
mergeSort(v);
for(auto i = v.begin(); i != v.end(); i++) cout << *i << endl;
return 0;
}
Upvotes: 0
Views: 78
Reputation: 3226
I think your condition is wrong (you comparing elements of vectors with index i
), try this (I also added check for inversions, as you asked). I just changed names of indexes from i2
and i1
to r
and l
respectively.
for (int i = 0; i < v.size; i++) {
if (r < right.size() && (right[r] <= left[l] || l >= left.size)) {
if (right[r] < left[l]) inversions++;
v[i] = right[r++];
} else {
v[i] = left[l++];
}
}
Upvotes: 1
Reputation: 487
Your condition is wrong. You need to use the i1
and i2
indexes because i
quickly goes beyond the size of right
(I checked this with a debugger, you should use it as well!)
Here my full solution and some additional tests:
//#include <bits/stdc++.h>
#include <vector>
#include <iostream>
using namespace std;
void mergeSort(vector<int>& v) {
if (v.size() > 1) {
vector<int> left(v.begin(), v.begin() + v.size() / 2);
vector<int> right(v.begin() + v.size() / 2, v.end());
mergeSort(left);
mergeSort(right);
int i1 = 0;
int i2 = 0;
for (int i = 0; i < v.size(); i++) {
if (i2 >= right.size() || (i1 < left.size() && left[i1] < right[i2])) {
v[i] = left[i1]; i1++;
}
else {
v[i] = right[i2]; i2++;
}
}
}
}
void printVector(vector<int>& v)
{
for (auto i = v.begin(); i != v.end(); i++) cout << *i << ' ';
std::cout << std::endl;
}
void test(vector<int>& v)
{
std::cout << "------\n";
printVector(v);
mergeSort(v);
std::cout << "------\n";
printVector(v);
std::cout << "------\n";
}
int main() {
vector<int> v1 = { 22, 18, 12, -4, 58, 7, 31, 42 };
vector<int> v2 = { 10 };
vector<int> v3 = { 10 , 20 };
vector<int> v4 = { 20 , 10 };
vector<int> v5 = { 20 , 10 , 5};
vector<int> v6 = { 10 , 10 , 10 };
vector<int> v7 = { 11 , 10 , 10 };
vector<int> v8 = { };
test(v1);
test(v2);
test(v3);
test(v4);
test(v5);
test(v6);
test(v7);
test(v8);
return 0;
}
Upvotes: 0