I'm trying to implement a MergeSort algorithm for a vector containing double values. I have the following code with me. However, two values are being treated as zero in my input and are out of place. Can someone tell me where I've gone wrong?
P.S: I'm new to data structures so I do not know the proper use of an iterator here.
Code:
#include <iostream>
#include <vector>
void sort(std::vector<double> vec);
std::vector<double> merge(std::vector<double> left, std::vector<double> right, int len);
std::vector<double> mergeSort(std::vector<double> vec, int len);
void sort(std::vector<double> vec) {
std::vector<double> tmp = mergeSort(vec, vec.size());
for (unsigned int i = 0; i < vec.size(); i++){
vec[i] = tmp[i];
std::cout << vec[i] << " ";
}
}
std::vector<double> merge(std::vector<double> left, std::vector<double> right, int len){
std::vector<double> ret(len + len);
int left_position = 0;
int right_position = 0;
int ret_position = 0;
while (left_position < len && right_position < len){
double left_value = left[left_position];
double right_value = right[right_position];
if (left_value < right_value){
ret.insert((ret.begin() + ret_position), left_value);
//ret[ret_position] = left_value;
ret_position++;
left_position++;
}
else {
ret.insert((ret.begin() + ret_position), right_value);
ret_position++;
right_position++;
}
}
while (left_position < len){
ret.insert((ret.begin() + ret_position), left[left_position]);
ret_position++;
left_position++;
}
while (right_position < len){
ret.insert((ret.begin() + ret_position), right[right_position]);
ret_position++;
right_position++;
}
return ret;
}
std::vector<double> mergeSort(std::vector<double> vec, int len){
if (len == 1){
return vec;
}
int middle = len / 2;
std::vector<double> left(middle);
std::vector<double> right(middle);
for (int i = 0; i < middle; i++){
left.insert((left.begin() + i), vec[i]);
}
for (int j = 0; j < middle; j++){
right.insert((right.begin() + j), vec[j + middle]);
}
left = mergeSort(left, middle);
right = mergeSort(right, middle);
std::vector<double> ret = merge(left, right, middle);
return ret;
}
int main(){
std::vector<double> vec;
vec.push_back(7.04);
vec.push_back(8.04);
vec.push_back(6.04);
vec.push_back(9.04);
vec.push_back(1.04);
vec.push_back(3.04);
vec.push_back(5.04);
vec.push_back(2.04);
vec.push_back(10.04);
vec.push_back(4.04);
vec.push_back(12.04);
vec.push_back(11.04);
sort(vec);
return 0;
}
The output is: 1.04 2.04 4.04 5.04 0 7.04 8.04 0 9.04 0 12.04 0 which is weird.
(Notice that every third element in the input is being treated as 0)
Live: http://ideone.com/fHZzZf
I have corrected your code.
First problem was, as poined by UmNyobe, is loosing elements when computing
int middle = len / 2;
When you use constructor
std::vector<int>(size_type n);
You construct a vecror with n elements 0.0
More about vector's constructors read on here.
When you use
vec.insert(iterator pos, const value_type& val);
you are inserting a new element before position pos and increasing the size of the vector by 1.
In merge sort i recomend you to create a vector with some elements and then assign them to appropriate values.
For example as you can see in code below:
std::vector<double> ret(left.size() + right.size(), -1); // construct vector with left.size() + right.size() elements assigned to -1
int left_position = 0;
int right_position = 0;
int ret_position = 0;
while (left_position < left.size() && right_position < right.size()) {
double left_value = left[left_position];
double right_value = right[right_position];
if (left_value < right_value) {
ret[ret_position++] = left_value;
left_position++;
} else {
ret[ret_position++] = right_value;
right_position++;
}
}
Corrected code:
#include <iostream>
#include <vector>
std::vector<double> merge(std::vector<double> left, std::vector<double> right);
std::vector<double> mergeSort(std::vector<double> vec);
void sort(std::vector<double>& vec) { // using reference here std::vector<double>& - to be able to change vector inside function
vec = mergeSort(vec);
for (unsigned int i = 0; i < vec.size(); i++){
std::cout << vec[i] << " ";
}
}
std::vector<double> merge(std::vector<double> left, std::vector<double> right) {
std::vector<double> ret(left.size() + right.size(), -1); // construct vector with left.size() + right.size() elements assigned to -1
int left_position = 0;
int right_position = 0;
int ret_position = 0;
while (left_position < left.size() && right_position < right.size()) {
double left_value = left[left_position];
double right_value = right[right_position];
if (left_value < right_value) {
ret[ret_position++] = left_value;
left_position++;
} else {
ret[ret_position++] = right_value;
right_position++;
}
}
while (left_position < left.size()) {
ret[ret_position++] = left[left_position++];
}
while (right_position < right.size()) {
ret[ret_position++] = right[right_position++];
}
return ret;
}
std::vector<double> mergeSort(std::vector<double> vec){
if (vec.size() < 2){
return vec;
}
int middle = vec.size() / 2;
std::vector<double> left(vec.begin(), vec.begin() + middle);
std::vector<double> right(vec.begin() + middle, vec.end());
left = mergeSort(left);
right = mergeSort(right);
std::vector<double> ret = merge(left, right);
return ret;
}
int main(){
std::vector<double> vec;
vec.push_back(7.04);
vec.push_back(8.04);
vec.push_back(6.04);
vec.push_back(9.04);
vec.push_back(1.04);
vec.push_back(3.04);
vec.push_back(5.04);
vec.push_back(2.04);
vec.push_back(10.04);
vec.push_back(4.04);
vec.push_back(12.04);
vec.push_back(11.04);
sort(vec);
return 0;
}
Now the output is
1.04 2.04 3.04 4.04 5.04 6.04 7.04 8.04 9.04 10.04 11.04 12.04
You should read more carefully methods of the class vector.
Here is a good site about c++: http://www.cplusplus.com/reference/vector/vector/
You are forgetting elements when breaking the original set into left and right subsets.
int middle = len / 2;
for (int i = 0; i < middle; i++){
...
}
for (int j = 0; j < middle; j++){
...
}
if len is odd you will end up having 2*middle = len -1. You can change to
for (int j = 0; j < len - middle; j++){
...
}
Edit:
Your whole program is based on the fact that the left and right side have equal length. Which means it will be correct only if the input vector has a length which is a power of 2. You need to revisit your functions with the assumption that there is going to be difference in the size of left and right
Do you really need to pass a length parameter when you deal with vectors? For instance
std::vector<double> ret(len + len);
in the merge function could be
std::vector<double> ret(left.size() + right.size());
Related
I tried to implement merge sort using C++, however, something went wrong. I have no idea what is wrong.
The following code is what I wrote based on CLRS. I think it is quite easy to understand the meaning.
#include <iostream>
#include <vector>
using namespace std;
void merge(vector<int>& nums, int p, int q, int r);
void mergeSort(vector<int>& nums, int p, int r){
if (p < r) {
int q = (p + r) / 2;
mergeSort(nums, p, q);
mergeSort(nums, q + 1, r);
merge(nums, p, q, r);
}
}
void merge(vector<int>& nums, int p, int q, int r) {
int s1 = p, s2 = q + 1;
vector<int> l1, l2;
for (int i = s1; i <= q; i++) {
l1.push_back(nums[i]);
}
for (int i = s2; i <= r; i++) {
l2.push_back(nums[i]);
}
int left = 0, right = 0;
int idx = 0;
while (left < l1.size() && right < l2.size()) {
if (l1[left] < l2[right]) {
nums[idx] = l1[left++];
}
else {
nums[idx] = l2[right++];
}
idx++;
}
while (left < l1.size()) {
nums[idx++] = l1[left++];
}
while (right < l2.size()) {
nums[idx++] = l2[right++];
}
}
int main() {
vector<int> vect;
vect.push_back(1);
vect.push_back(3);
vect.push_back(12);
vect.push_back(23);
vect.push_back(4);
vect.push_back(11);
vect.push_back(44);
vect.push_back(322);
mergeSort(vect, 0, vect.size() - 1);
for (int i = 0; i < vect.size(); i++) {
cout << vect[i] << endl;
}
return 0;
}
I want to use the program to sort some integers, however, it only shows many duplicate numbers. What's going on? I don't think there is a problem of the merge function.
The code needs a one line fix:
int idx = p; // not idx = 0
Optimized top down using arrays from Wiki article (note bottom up is slightly faster):
void TopDownMerge(int A[], int bgn, int mid, int end, int B[])
{
int i, j, k;
i = bgn, j = mid, k = bgn;
while(1){
if(A[i] <= A[j]){ // if left smaller
B[k++] = A[i++]; // copy left element
if(i < mid) // if not end of left run
continue; // continue
do // else copy rest of right run
B[k++] = A[j++];
while(j < end);
break; // and break
} else { // else right smaller
B[k++] = A[j++]; // copy right element
if(j < end) // if not end of right run
continue; // continue
do // else copy rest of left run
B[k++] = A[i++];
while(i < mid);
break; // and break
}
}
}
void TopDownSplitMerge(int B[], int bgn, int end, int A[])
{
if (end - bgn <= 1) // if run size == 1
return; // consider it sorted
int mid = (end + bgn) / 2;
TopDownSplitMerge(A, bgn, mid, B);
TopDownSplitMerge(A, mid, end, B);
TopDownMerge(B, bgn, mid, end, A);
}
void TopDownMergeSort(int A[], int n) // n = size (not size-1)
{
if(n < 2)
return;
int *B = new int [n]; // 1 time allocate and copy
for(size_t i = 0; i < n; i++)
B[i] = A[i];
TopDownSplitMerge(B, 0, n, A); // sort data from B[] into A[]
delete B;
}
Afterwards, I finally get to fix the bugs of my program. After modification, here is the code:
class Solution {
public:
vector<int> temp;
vector<int> sortArray(vector<int>& nums) {
temp.resize((int)nums.size(), 0);
mergeSort(nums, 0, nums.size() - 1);
return nums;
}
void mergeSort(vector<int>& nums, int start, int end) {
if (start >= end) return;
int middle = (start + end) / 2;
mergeSort(nums, start, middle);
mergeSort(nums, middle + 1, end);
merge(nums, start, middle, end);
}
void merge(vector<int>& nums, int leftStart, int middle, int rightEnd) {
int leftEnd = middle;
int rightStart = middle + 1;
int i = leftStart, j = rightStart;
int index = 0;
while (i <= leftEnd && j <= rightEnd) {
if (nums[i] < nums[j]) {
temp[index] = nums[i++];
}
else {
temp[index] = nums[j++];
}
index++;
}
while (i <= leftEnd) {
temp[index++] = nums[i++];
}
while (j <= rightEnd) {
temp[index++] = nums[j++];
}
for (int i = 0; i < rightEnd - leftStart + 1; i++) {
nums[i + leftStart] = temp[i];
}
}
};
Here is something should be careful next time:
In the merge part, it is difficult to merge in place. It'd be better to use another temp array to store the merged results and update to the target array (nums in this case).
Readable identifers is very recommended (Although the pseudocode of CLRS may not use that part).
Need to use debuggers to find the bug of program {However, it takes like forever to load local variables of VS Code debugers.
I am writing a C++ program that finds the number of inversions in a vector using merge sort. An inversion happens when the i'th element is greater than the j'th element, where i < j. For example, say the vector is { 1, 3, 5, 2 }, then there are 2 inversions: {3,2} and {5,2}.
The countNsort function keeps recursing and dividing the vector until the length of the subvector is only one element. The countNsortSplit function performs merge sort to sort and count the number of inversions.
I tried:
Different ways of initializing the input vector. vector<int> a{2,1};, vector<int> a; a={2,1};, and vector<int> a(2); a={2,1};.
Different ways of splitting the input vector into subvectors. vector<int> c(a.begin()+half, a.begin()+n); and vector<int> c(a.begin()+half, a.end());, where n is the size of the vector.
Different IDEs. Atoms gives me this: bash: line 1: 13763 Segmentation fault: 11 /tmp/cpp.out [Finished in 20.57s], CodeBlocks gives me this: error: expected expression for this line: a={2,1}:.
#include <stdio.h>
#include <vector>
#include <iostream>
using namespace std;
struct returnVal {
int count;
vector<int> sorted_array;
};
returnVal countNsortSplit(vector<int> left, vector<int> right, int n) {
returnVal output;
int count = 0;
vector<int> merge;
int i = 0;
int j = 0;
for (int k = 0; k < n; k++) {
if (left[i] < right[j]) {
merge[k] = left[i];
i++;
} else {
merge[k] = right[j];
j++;
// increment count by the # of remaining elements in left
count += left.size()-i;
}
}
output.sorted_array = merge;
output.count = count;
return output;
}
returnVal countNsort(vector<int> a, int n) {
returnVal output;
if (n == 1) {
output.sorted_array = a;
output.count = 0;
return output;
} else {
returnVal left;
returnVal right;
returnVal split;
int half = n / 2;
vector<int> b(a.begin(), a.begin() + half);
vector<int> c(a.begin() + half, a.begin() + n);
left = countNsort(b, half);
right = countNsort(c, n - half); // need n-n/2 in case of odd length
split = countNsortSplit(left.sorted_array, right.sorted_array, n);
output.sorted_array = split.sorted_array;
output.count = left.count + right.count + split.count;
return output;
}
}
int main() {
vector<int> a(2);
//a = {1,3,5,2};
//a = {1,3,5,2,4,6};
a = {2, 1};
returnVal result;
result = countNsort(a, a.size());
cout << result.count << endl;
}
There are multiple problems in you code:
You do not define the destination vector with the proper size
You do not test if i or j have reached to size of the left and right vectors respectively.
The initializer for vector a in main() has an invalid syntax.
Note that you do not need to pass the vector sizes to countNsort and countNsortSplit.
Here is a corrected version:
#include <iostream>
#include <vector>
using namespace std;
struct returnVal {
int count;
vector<int> sorted_array;
};
returnVal countNsortMerge(vector<int> left, vector<int> right) {
int leftSize = left.size();
int rightSize = right.size();
int n = leftSize + rightSize;
int count = 0;
vector<int> merge(n);
int i = 0;
int j = 0;
for (int k = 0; k < n; k++) {
if (i < leftSize && (j == rightSize || left[i] < right[j])) {
merge[k] = left[i++];
} else {
merge[k] = right[j++];
// increment count by the # of remaining elements in left
count += leftSize - i;
}
}
returnVal output;
output.sorted_array = merge;
output.count = count;
return output;
}
returnVal countNsort(vector<int> a) {
int n = a.size();
if (n <= 1) {
returnVal output;
output.sorted_array = a;
output.count = 0;
return output;
} else {
int half = n / 2;
vector<int> b(a.begin(), a.begin() + half);
vector<int> c(a.begin() + half, a.begin() + n);
returnVal left = countNsort(b);
returnVal right = countNsort(c);
returnVal result = countNsortMerge(left.sorted_array, right.sorted_array);
result.count += left.count + right.count;
return result;
}
}
int main() {
//int values[] = { 1, 3, 5, 2 };
//int values[] = { 2, 1 };
int values[] = { 1, 3, 5, 2, 4, 6 };
vector<int> a(values, values + sizeof values / sizeof *values);
returnVal result = countNsort(a);
cout << result.count << endl;
return 0;
}
Note however that it would be more efficient and idiomatic to sort the vector in place and return the inversion count:
#include <iostream>
#include <vector>
size_t countNsortMerge(std::vector<int>& a, size_t start, size_t middle, size_t end) {
std::vector<int> temp(a.begin() + start, a.begin() + middle);
size_t i = 0;
size_t leftSize = middle - start;
size_t j = middle;
size_t count = 0;
for (size_t k = start; k < end; k++) {
if (i < leftSize && (j == end || temp[i] < a[j])) {
a[k] = temp[i++];
} else {
a[k] = a[j++];
// increment count by the # of remaining elements in left
count += leftSize - i;
}
}
return count;
}
size_t countNsort(std::vector<int>& a, size_t start, size_t end) {
if (end - start <= 1) {
return 0;
} else {
size_t middle = start + (end - start) / 2;
size_t leftCount = countNsort(a, start, middle);
size_t rightCount = countNsort(a, middle, end);
return leftCount + rightCount + countNsortMerge(a, start, middle, end);
}
}
int main() {
//int values[] = { 1, 3, 5, 2 };
//int values[] = { 2, 1 };
int values[] = { 1, 3, 5, 2, 4, 6 };
std::vector<int> a(values, values + sizeof values / sizeof *values);
size_t result = countNsort(a, 0, a.size());
std::cout << result << std::endl;
return 0;
}
My multiway_merge function is incorrect but not sure why. Seems to be correct logically but if the sorting is correct then it must be the merging. I am supposed to make a min heap of the first element of each sorted vector and then add them to the output_list in the correct sorted order and keep doing that until all the numbers have been added to the output_list.
int partition(vector<int>& list, int first, int last) {
// The pivot should be the median of the
// first, middle, and last elements.
int middle = first + (last - first) / 2;
if (list[first] > list[middle])
swap(list[first], list[middle]);
if (list[first] > list[last])
swap(list[first], list[last]);
if (list[middle] > list[last])
swap(list[middle], list[last]);
swap(list[middle], list[first]);
int pivot = list[first];
int i = first - 1;
int j = last + 1;
while(true) {
do {
i++;
} while(list[i] < pivot);
do {
j--;
} while(list[j] > pivot);
if(i >= j)
return j;
swap(list[i], list[j]);
}
}
void quicksort(vector<int>& list, int first, int last) {
if(first < last) {
int pivotLocation = partition(list, first, last);
quicksort(list, first, pivotLocation);
quicksort(list, pivotLocation + 1, last);
}
}
void multiway_merge(vector<vector<int> >& input_lists,
vector<int>& output_list) {
int numLists = (int) (input_lists.size());
int numElements = (int) (input_lists[0].size());
priority_queue<int, vector<int>, greater<int> > minHeap;
for(int i = 0; i < numLists; i++) {
for(int j = 0; j < numElements; j++) {
minHeap.push(input_lists[i][j]);
if (minHeap.size() > numLists) {
output_list.push_back(minHeap.top());
minHeap.pop();
}
}
}
while (minHeap.size()) {
output_list.push_back(minHeap.top());
minHeap.pop();
}
}
int main(int argc, char** argv) {
int n, m;
cin >> n >> m;
vector<vector<int> > input_lists(n, vector<int>(m));
for (int i = 0; i < n; ++i) {
for (int j = 0; j < m; ++j) {
cin >> input_lists[i][j];
}
}
// Quicksort k sublists
for (int i = 0; i < input_lists.size(); ++i)
quicksort(input_lists[i], 0, m-1);
// Merge n input sublists into one sorted list
vector<int> output_list;
multiway_merge(input_lists, output_list);
for(int i = 0; i < output_list.size(); ++i)
cout << output_list[i] << " ";
cout << endl;
}
I couldn't find any logical error with your partition function, Maybe your problem source is in the way that you call this function from sort function and you didn't share that function with us so I had to guess.
Anyway, using your implementation of partition function the quick sort algorithm would be something like this :
#include <iostream>
#include <vector>
#include <algorithm>
int partition(std::vector<int> &vec, int low, int high)
{
int middle = low + (high - low) / 2;
if((vec.at(middle) >= vec.at(low) && vec.at(middle) <= vec.at(high))
|| (vec.at(middle) <= vec.at(low) && vec.at(middle) >= vec.at(high)))
std::swap(vec.at(high), vec.at(middle));
if((vec.at(high) >= vec.at(low) && vec.at(high) <= vec.at(middle))
|| (vec.at(high) <= vec.at(low) && vec.at(high) >= vec.at(middle)))
std::swap(vec.at(low), vec.at(high));
int pivot = vec.at(low);
int i = low - 1, j = high + 1;
while(true)
{
do
{
i++;
} while(vec.at(i) < pivot);
do
{
j--;
} while(vec.at(j) > pivot);
if(i >= j)
return j;
std::swap(vec.at(i), vec.at(j));
}
}
void quickSort(std::vector<int> &vec, int low, int high)
{
if(low < high)
{
int pi = partition(vec, low, high);
quickSort(vec, low, pi);
quickSort(vec, pi + 1, high);
}
}
int main()
{
std::vector<int> input = {10, 7, 15, 9, 1, 33};
quickSort(input, 0, input.size() - 1);
for(auto iter = input.begin(); iter != input.end(); ++iter)
std::cout << *iter << " ";
std::cout << "\n";
system("pause");
return 0;
}
EDIT : Your quick sort wasn't the source of the problem, You have problem merging sorted vectors, so the source of the problem is in logic of your multiway_merge function.
You used priority_queue to achieve this merge and it's a valid approach, but I think you miss understood how priority_queue actually works.
you can enqueue as many elements you want but the order of outgoing elements are determined by the way you set your priority. Take a loot at priority_queue.
Your compare condition to determine priority is right too, I mean using greater<int>. So the only problem in your code is one extra condition that you don't need it at all. I mean these lines of code :
if(minHeap.size() > numLists)
{
output_list.push_back(minHeap.top());
minHeap.pop();
}
Remove this condition and your multiway_merge will work fine. The final implementation of this function would be :
void multiway_merge(vector<vector<int> >& input_lists,
vector<int>& output_list)
{
unsigned int numLists = (int)(input_lists.size());
int numElements = (int)(input_lists[0].size());
priority_queue<int, vector<int>, greater<int> > minHeap;
for(int i = 0; i < numLists; i++)
{
for(int j = 0; j < numElements; j++)
{
minHeap.push(input_lists[i][j]);
}
}
while(minHeap.size())
{
output_list.push_back(minHeap.top());
minHeap.pop();
}
}
So i've been trying to write out an algorithm for the Karatsuba Multiplication algorithm, and i've been attempting to use vectors as my data structure to handle the really long numbers which will be input...
My program can do smaller numbers fine, however it really struggles with larger numbers, and i get a core dump (Seg Fault). It also outputs strange results when the left hand side number is smaller than the right hand side.
Got any ideas? Heres the code.
#include <iostream>
#include <string>
#include <vector>
#define max(a,b) ((a) > (b) ? (a) : (b))
using namespace std;
vector<int> add(vector<int> lhs, vector<int> rhs) {
int length = max(lhs.size(), rhs.size());
int carry = 0;
int sum_col;
vector<int> result;
while(lhs.size() < length) {
lhs.insert(lhs.begin(), 0);
}
while(rhs.size() < length) {
rhs.insert(rhs.begin(), 0);
}
for(int i = length-1; i >= 0; i--) {
sum_col = lhs[i] + rhs[i] + carry;
carry = sum_col/10;
result.insert(result.begin(), (sum_col%10));
}
if(carry) {
result.insert(result.begin(), carry);
}
int x = 0;
while(result[x] == 0) {
x++;
}
result.erase(result.begin(), result.begin()+x);
return result;
}
vector<int> subtract(vector<int> lhs, vector<int> rhs) {
int length = max(lhs.size(), rhs.size());
int diff;
vector<int> result;
while(lhs.size() < length) {
lhs.insert(lhs.begin(), 0);
}
while(rhs.size() < length) {
rhs.insert(rhs.begin(), 0);
}
for(int i = length-1; i >= 0; i--) {
diff = lhs[i] - rhs[i];
if(diff >= 0) {
result.insert(result.begin(), diff);
} else {
int j = i - 1;
while(j >= 0) {
lhs[j] = (lhs[j] - 1) % 10;
if(lhs[j] != 9) {
break;
} else {
j--;
}
}
result.insert(result.begin(), diff+10);
}
}
int x = 0;
while(result[x] == 0) {
x++;
}
result.erase(result.begin(), result.begin()+x);
return result;
}
vector<int> multiply(vector<int> lhs, vector<int> rhs) {
int length = max(lhs.size(), rhs.size());
vector<int> result;
while(lhs.size() < length) {
lhs.insert(lhs.begin(), 0);
}
while(rhs.size() < length) {
rhs.insert(rhs.begin(), 0);
}
if(length == 1) {
int res = lhs[0]*rhs[0];
if(res >= 10) {
result.push_back(res/10);
result.push_back(res%10);
return result;
} else {
result.push_back(res);
return result;
}
}
vector<int>::const_iterator first0 = lhs.begin();
vector<int>::const_iterator last0 = lhs.begin() + (length/2);
vector<int> lhs0(first0, last0);
vector<int>::const_iterator first1 = lhs.begin() + (length/2);
vector<int>::const_iterator last1 = lhs.begin() + ((length/2) + (length-length/2));
vector<int> lhs1(first1, last1);
vector<int>::const_iterator first2 = rhs.begin();
vector<int>::const_iterator last2 = rhs.begin() + (length/2);
vector<int> rhs0(first2, last2);
vector<int>::const_iterator first3 = rhs.begin() + (length/2);
vector<int>::const_iterator last3 = rhs.begin() + ((length/2) + (length-length/2));
vector<int> rhs1(first3, last3);
vector<int> p0 = multiply(lhs0, rhs0);
vector<int> p1 = multiply(lhs1,rhs1);
vector<int> p2 = multiply(add(lhs0,lhs1),add(rhs0,rhs1));
vector<int> p3 = subtract(p2,add(p0,p1));
for(int i = 0; i < 2*(length-length/2); i++) {
p0.push_back(0);
}
for(int i = 0; i < (length-length/2); i++) {
p3.push_back(0);
}
result = add(add(p0,p1), p3);
int x = 0;
while(result[x] == 0) {
x++;
}
result.erase(result.begin(), result.begin()+x);
return result;
}
int main() {
vector<int> lhs;
vector<int> rhs;
vector<int> v;
lhs.push_back(2);
lhs.push_back(5);
lhs.push_back(2);
lhs.push_back(5);
lhs.push_back(2);
lhs.push_back(5);
lhs.push_back(2);
lhs.push_back(5);
rhs.push_back(1);
rhs.push_back(5);
rhs.push_back(1);
rhs.push_back(5);
rhs.push_back(1);
rhs.push_back(5);
rhs.push_back(1);
v = multiply(lhs, rhs);
for(size_t i = 0; i < v.size(); i++) {
cout << v[i];
}
cout << endl;
return 0;
}
There are several issues with subtract. Since you don't have any way to represent a negative number, if rhs is greater than lhs your borrow logic will access before the beginning of of the data for lhs.
You can also march past the end of result when removing leading zeros if the result is 0.
Your borrow calculation is wrong, since -1 % 10 will return -1, and not 9, if lhs[j] is 0. A better way to calculate that is add 9 (one less than the value you're dividing by), lhs[j] = (lhs[j] + 9) % 10;.
In an unrelated note, you can simplify your range iteration calculations. Since last0 and first1 have the same value, you can use last0 for both, and last1 is lhs.end(). This simpifies lhs1 to
vector<int> lhs1(last0, lhs.end());
and you can get rid of first1 and last1. Same goes for the rhs iterators.
My friend and I are struggling with a merging function. It requires that both arrays have the same size, thus the merged array twice the number. This is what we have so far:
void mergeTwoSortedArrays(const int a1[], const int a2[], int mergedArray[], int n)
{
int i = 0;
int j = 0;
int k = 0;
while (i <= n && j <= n)
{
if (a1[i] == a2[j])
{
mergedArray[k] = a1[i];
mergedArray[k] = a2[j];
i++;
j++;
}
k++;
}
}
It's not working however. Any tips?
Is this for merge sort or something? The usual approach is to do the combined merge, much like you have done already, followed by a copy. Here's the first part. You were a little confused. Read through this and you'll see it makes sense:
while (i < n && j < n) {
if (a1[i] <= a2[j]) {
mergedArray[k++] = a1[i++];
} else {
mergedArray[k++] = a2[j++];
}
}
Then you handle the remaining elements. Obviously the loop finishes when only one array reaches the end. So now you need two much simpler loops. Only one will execute - no need for complicated tests:
while (i < n) mergedArray[k++] = a1[i++];
while (j < n) mergedArray[k++] = a2[j++];
I turned your tests into < instead of <=, because the arrays are zero-based.
This is what i came up with -
void mergeTwoSortedArrays(const int a1[], const int a2[], int mergedArray[], int n) {
int i = 0;
int j = 0;
int k = 0;
// Iterate and compare two input arrays until at least one of them reaches to boundary.
while (i < n && j < n) {
if (a1[i] < a2[j]) {
mergedArray[k++] = a1[i++];
}
else if (a1[i] > a2[j]) {
mergedArray[k++] = a2[j++];
}
else if (a1[i] == a2[j]) {
mergedArray[k++] = a1[i++];
mergedArray[k++] = a2[j++];
}
}
// Copy the remaining items from the other array, without comparison until, boundary.
while (i < n) mergedArray[k++] = a1[i++];
while (j < n) mergedArray[k++] = a2[j++];
}
I don't know if you're trying to merge them as in interleave them or just concatenate two distinct arrays. If it's striding:
#include <iostream>
void mergeTwoArraysIntoOne(const int* lhs, const int* rhs, int* dst, size_t numElements) {
const int* const endLhs = lhs + numElements;
const int* const endRhs = rhs + numElements;
for ( ; lhs < endLhs ; ) {
while (rhs < endRhs && *rhs < *lhs)
*(dst++) = *(rhs++);
*(dst++) = *(lhs++);
}
while (rhs < endRhs)
*(dst++) = *(rhs++);
}
void dumpArray(int* array, size_t elements) {
for (size_t i = 0; i < elements; ++i)
std::cout << array[i] << " ";
std::cout << std::endl;
}
int main() {
int array1[] = { 1, 2, 3 };
int array2[] = { 10, 20, 30 };
int array3[] = { 1, 11, 31 };
int result[6];
mergeTwoArraysIntoOne(array1, array2, result, 3);
dumpArray(result, 6);
mergeTwoArraysIntoOne(array2, array1, result, 3);
dumpArray(result, 6);
mergeTwoArraysIntoOne(array1, array3, result, 3);
dumpArray(result, 6);
mergeTwoArraysIntoOne(array3, array1, result, 3);
dumpArray(result, 6);
mergeTwoArraysIntoOne(array2, array3, result, 3);
dumpArray(result, 6);
mergeTwoArraysIntoOne(array3, array2, result, 3);
dumpArray(result, 6);
return 0;
}
Live demo: http://ideone.com/7ODqWD
If it's just concatenating them:
std::copy(&lhs[0], &lhs[numElements], &dst[0]);
std::copy(&rhs[0], &rhs[numElements], &dst[numElements]);