Merging two sorted arrays with for loop - c++

I have a function that merges two sorted arrays into one and returns a pointer to it. I want to use a for loop rather than a while. However in some test cases the last 1 or 2 elements of the merge array are not in their place. I would appreciate if someone can help solve this problem keeping the for loop.
int * mergeSort(int arr1[], int arr2[],int len)
{
/* len is the combined length of the two arrays */
static int sorted[100];
int pos1=0, pos2=0;
for (int i=0; i<len; i++)
{
if (arr1[pos1]<=arr2[pos2])
{
sorted[i]=arr1[pos1];
pos1++;
}
else
{
sorted[i]=arr2[pos2];
pos2++;
}
}
return sorted;
}

Your problem is that you don't seem to handle going past the end of the input arrays. If there is uninitialized memory - you get undefined behaviour.
You can avoid this by terminating your arrays with a sentinel value, for example INT_MAX, which should always be bigger than all possible values in the arrays:
int a[] = { 1, 2, 104, INT_MAX};
int b[] = { 101, 102, 105, INT_MAX};
int* ptr = mergeSort(a,b,6);
for(int i = 0; i < 6; i++){
cout << i << " " << ptr[i] << endl;
}
live demo
Or you can pass the actual lengths of both arrays and handle them correctly:
int * mergeSort(int arr1[], int len1, int arr2[],int len2)
{
/* len is the combined length of the two arrays */
static int sorted[100];
int pos1=0, pos2=0;
for (int i=0; i< len1 + len2; i++)
{
if ((pos2 == len2) || (arr1[pos1] <= arr2[pos2] && (pos1 < len1)))
{
sorted[i]=arr1[pos1];
pos1++;
}
else
{
sorted[i]=arr2[pos2];
pos2++;
}
}
return sorted;
}
live demo

This doesn't answer the question of what's wrong with your code, but to answer the question of how to merge two sorted ranges I would suggest std::merge:
int * mergeSort(int arr1[], int arr2[], int len1, int len2)
{
//I am not condoning the use of a static buffer here,
//I would probably use a std::vector or std::array,
//possibly a boost::static_vector if really necessary
static int sorted[100];
std::merge(arr1, arr1 + len1, arr2, arr2 + len2, sorted);
return sorted;
}
I also changed int len to int len1, int len2 because you need to know the lengths of the individual arrays, not just their combined length, to avoid reading past the end of the input arrays.

Related

combine 2 array into 1 array c++ [duplicate]

Is there a way to take two int arrays in C++
int * arr1;
int * arr2;
//pretend that in the lines below, we fill these two arrays with different
//int values
and then combine them into one larger array that contains both arrays' values?
Use std::copy defined in the header <algorithm>. The args are a pointer to the first element of the input, a pointer to one past the last element of the input, and a pointer to the first element of the output.
( https://en.cppreference.com/w/cpp/algorithm/copy )
int * result = new int[size1 + size2];
std::copy(arr1, arr1 + size1, result);
std::copy(arr2, arr2 + size2, result + size1);
Just suggestion, vector will do better as a dynamic array rather than pointer
If you're using arrays, you need to allocate a new array large enough to store all of the values, then copy the values into the arrays. This would require knowing the array sizes, etc.
If you use std::vector instead of arrays (which has other benefits), this becomes simpler:
std::vector<int> results;
results.reserve(arr1.size() + arr2.size());
results.insert(results.end(), arr1.begin(), arr1.end());
results.insert(results.end(), arr2.begin(), arr2.end());
Another alternative is to use expression templates and pretend the two are concatenated (lazy evaluation). Some links (you can do additional googling):
http://www10.informatik.uni-erlangen.de/~pflaum/pflaum/ProSeminar/
http://www.altdevblogaday.com/2012/01/23/abusing-c-with-expression-templates/
http://aszt.inf.elte.hu/~gsd/halado_cpp/ch06s06.html
If you are looking for ease of use, try:
#include <iostream>
#include <string>
int main()
{
int arr1[] = {1, 2, 3};
int arr2[] = {3, 4, 6};
std::basic_string<int> s1(arr1, 3);
std::basic_string<int> s2(arr2, 3);
std::basic_string<int> concat(s1 + s2);
for (std::basic_string<int>::const_iterator i(concat.begin());
i != concat.end();
++i)
{
std::cout << *i << " ";
}
std::cout << std::endl;
return 0;
}
Here is the solution for the same-
#include<iostream>
#include<bits/stdc++.h>
using namespace std;
void Concatenate(char *s1,char *s2)
{
char s[200];
int len1=strlen(s1);
int len2=strlen(s2);
int j;
///Define k to store the values on Kth address Kstart from 0 to len1+len2;
int k=0;
for(j=0;j<len1;j++)
{
s[k]=s1[j];
k++;
}
for(j=0;j<len2;j++)
{
s[k]=s2[j];
k++;
}
///To place a null at the last of the concatenated string to prevent Printing Garbage value;
s[k]='\n';
cout<<s;
}
int main()
{
char s1[100];
char s2[100];
cin.getline(s1,100);
cin.getline(s2,100);
Concatenate(s1,s2);
return 0;
}
Hope it helps.
for (int i = 0; i< arraySize * 2; i++)
{
if (i < aSize)
{
*(array3 + i) = *(array1 + i);
}
else if (i >= arraySize)
{
*(array3 + i) = *(array2 + (i - arraySize));
}
}
This might help you along, it doesn't require vectors. I had a similar problem in my programming class. I hope this helps, it was required that I used pointer arithmetic. This assumes that array1 and array2 are initialized dynamically to the size "aSize"
Given int * arr1 and int * arr2, this program Concatenates in int * arr3 the elements of the both arrays. Unfortunately, in C++ you need to know the sizes of each arrays you want to copy. But this is no impediment to choose how many elements you want to copy from arr1 and how many from arr2.
#include <iostream>
using namespace std;
int main(){
int temp[] = {1,2,3,4};
int temp2[] = {33,55,22};
int * arr1, * arr2, *arr3;
int size1(4), size2(3); //size1 and size2 is how many elements you
//want to copy from the first and second array. In our case all.
//arr1 = new int[size1]; // optional
//arr2 = new int[size2];
arr1=temp;
arr2=temp2;
arr3 = new int;
//or if you know the size: arr3 = new int[size1+size2];
for(int i=0; i<size1+size2; i++){
if (i<size1)
arr3[i]=arr1[i];
else
arr3[i] = arr2[i-size1];
}
cout<<endl;
for (int i=0; i<size1+size2; i++) {
cout<<arr3[i]<<", ";
}
}

c++: selectionSort with pointers instead of index

I want to sort numbers using pointers instead of indexes. By the way this is the header file :
int * sort(const int * const array, int size)
And below is the source code I was given
void selectionSort(int list[], int arraySize)
{
for(int i=arraySize-1; i>=1; i--)
{
int currentMax=list[0];
int currentMaxIndex=0;
for(int j=1; j<=i; j++)
{
if(currentMax=list[j])
{
currentMax=list[i];
currentMaxIndex=j;
}
}
if(currentMaxIndex != i)
{
list[currentMaxIndex]=list[i];
list[i]=currentMax;
}
}
}
I know you can switch list[i] to *(list+i) but I don't know how to do it with "currentMaxIndex". I'd really appreciate your help!!
Pointers in C are integers like any others, and can be compared with the usual operations.
So you can do things like:
int *end = list + length; // Create a pointer to one-past the end of an array
for(int *it = list; it < end; it++){ /* use it to read the elements */ }
int *my_favorite_index = list + some_index;
I'm not going to solve your homework for you, but I hope this helps.

C++ QuickSort Algorithm keeps crashing

Trying to implement a Quick Sort algorithm.I think the problem is with the recursion, but I do not know what I should do to fix it. The program continues to crash every time I run it, and I cannot understand why. Here is the code:
#include<iostream>
using namespace std;
int pIndex;
int Partition(int *A,int start,int end){
int pivot;
int pIndex;
if(start<end){
int pivot=A[end];
int pIndex=start;
for(int x=0;x<end;x++){
if(A[x]<A[end]){
swap(A[x],A[pIndex]);
pIndex=pIndex+1;
}
}
swap(A[pIndex],A[end]);
}
//cout<<pIndex<<endl;
swap(A[pIndex],A[end]);
return pIndex;
};
void QuickSort(int *A, int start,int end){
if(start<end)
{
pIndex=Partition(A,start,end);
QuickSort(A,pIndex+1,end);
QuickSort(A,start,pIndex-1);
}
};
int main(){
int A[10]{4,23,1,43,2,10};
//Partition(A,0,9);
QuickSort(A,0,5);
for(int x=0;x<10;x++){
cout<< A[x]<<" ";
}
}
Your partition algorithm is about twice as much code as it needs to be. You seem to be always choosing the last element in the sequence for your pivot, and although not advisable, it will work for academic demonstration.
Your Crash
You're defining two pIndex values, only one of which is actually deterministic. You also declare two pivot variables, but that does NOT cause your crash (the first one is never used). It should be cleaned up none-the-less, but the death knell in your code is duplicate pIndex
int pivot;
int pIndex; // HERE
if(start<end){
int pivot=A[end];
int pIndex=start; // HERE AGAIN
for(int x=0;x<end;x++){
if(A[x]<A[end]){
swap(A[x],A[pIndex]);
pIndex=pIndex+1;
}
}
swap(A[pIndex],A[end]);
}
swap(A[pIndex],A[end]); // uses non-determined pIndex
return pIndex; // returns non-determined pIndex
Changing int pIndex=start; to simply be pIndex=start; will solve your crash, but your partition method still needs... help.
The "Sweep" Partition Method
The "sweep" method of partitioning is generally done like this for a pivot value that is assumed to be right-tailed, and you would be hard pressed to get this simpler (invoking std::partition not withstanding):
size_t Partition(int *A, size_t len)
{
if (len < 2)
return 0;
size_t pvt = 0;
for (size_t i=0; i<end; ++i)
{
if (A[i] < a[len-1])
std::swap(A[i], A[pvt++])
}
std::swap(A[pvt], a[len-1]);
return pvt;
};
The above algorithm includes only the necessities needed for a partition: the sequence iterator (a pointer in your case), and the sequence length. Everything else is deterministic based on those two items. A quick sample program of how this works follows, with a purposely placed 5 for the pivot value:
#include <iostream>
size_t Partition(int *A, size_t len)
{
if (len < 2)
return 0;
size_t pvt = 0;
for (size_t i=0; i<len-1; ++i)
{
if (A[i] < A[len-1])
std::swap(A[i], A[pvt++]);
}
std::swap(A[pvt], A[len-1]);
return pvt;
};
int main()
{
int arr[] = { 4, 8, 7, 3, 9, 2, 1, 6, 5 };
size_t n = Partition(arr, sizeof(arr)/sizeof(*arr));
std::cout << "Partition : " << n << '\n';
for (auto x : arr)
std::cout << x << ' ';
std::cout << '\n';
}
Output
Partition : 4
4 3 2 1 5 7 8 6 9
How To Invoke From QuickSort
Invoking a partition in quicksort sets up the pivot location, which becomes the "end" iteration point of the bottom segment, and the one-BEFORE iteration point of the top segment. It is critical the pivot location returned from an invoke of Partition() should NOT be included in either subsequence when recursing.
void QuickSort(int *A, size_t len)
{
if (len < 2)
return;
size_t pvt = Partition(A, len);
QuickSort(A, pvt++); // NOTE: post increment...
QuickSort(A+pvt, len-pvt); // ...which makes this skip the pivot
}
Yeah, pointer arithmetic rocks, don't you think?
Putting It All Together
The program below incorporates both the Partition and QuickSort :
#include <iostream>
size_t Partition(int *A, size_t len)
{
if (len < 2)
return 0;
size_t pvt = 0;
for (size_t i=0; i<len-1; ++i)
{
if (A[i] < A[len-1])
std::swap(A[i], A[pvt++]);
}
std::swap(A[pvt], A[len-1]);
return pvt;
};
void QuickSort(int *A, size_t len)
{
if (len < 2)
return;
size_t pvt = Partition(A, len);
QuickSort(A, pvt++); // NOTE: post increment
QuickSort(A+pvt, len-pvt);
}
int main()
{
int arr[] = { 4, 8, 7, 3, 9, 2, 1, 6, 5 };
QuickSort(arr, sizeof(arr)/sizeof(*arr));
for (auto x : arr)
std::cout << x << ' ';
std::cout << '\n';
}
Output
1 2 3 4 5 6 7 8 9
I hope it helps.
In this part:
int pivot;
int pIndex;
if(start<end){
int pivot=A[end];
int pIndex=start;
You are defining two pivots, and two pIndex's. You are not using the pivot at all, and with the last swap you are using the uninitialized pIndex. This should work:
int Partition(int *A,int start,int end){
int pIndex = start;
if(start<end){
for(int x=0;x<end;x++){
if(A[x]<A[end]){
swap(A[x],A[pIndex]);
pIndex=pIndex+1;
}
}
swap(A[pIndex],A[end]);
}
swap(A[pIndex],A[end]);
return pIndex;
}
I'm also something of a C++ newbie, but I find myself curious about what happens when start >= end. It looks as though your Partition function will still return a pIndex value, but I don't see where you define it anywhere. If (as I suspect) it returns whatever value happens to reside in memory, then you'll very likely end up referencing some undefined memory locations when you use A[pIndex]

How to change the order of elements in an array using a pointer?

For example, I have an array:
int Arr[10]={1,2,3,4,5,6,7,8,9,10};
How to change its order of elements using a pointer to receive the following array:
Arr={10,9,8,7,6,5,4,3,2,1}
to change the order odd and even using a pointer I've found this:
But I need only to reverse an array (without replacing odd and even)
#include <iostream>
using namespace std;
int main (const int& Argc, const char* Argv[]){
const int Nelem=10;
int Arr[]={1,2,3,4,5,6,7,8,9,10};
int *begAr=&Arr[0];
int *endAr=&Arr[Nelem];
int *itrAr=begAr;
int *tmpValAr=new int(0);
cout<<"Before\t1 2 3 4 5 6 7 8 9 10"<<endl;
while(itrAr<endAr){
*tmpValAr=*itrAr;
*itrAr=*(itrAr+1);
*(itrAr+1)=*tmpValAr;
itrAr+=2;
}
cout<<"After\t";
for(int i=0; i<Nelem; ++i)cout<<Arr[i]<<" ";
cout<<endl;
system("pause");
return 0;
}
Ok, a C-style approach using pointers to reverse an array? That shouldn't be too hard to figure out. Here's one approach:
int main ( void )
{
int i,//temp var
arr[10]= {1,2,3,4,5,6,7,8,9,10};//the array
int *start = &arr[0],//pointer to the start of the array
*end = &arr[9];//pointer to the last elem in array
//print out current arr values
for (i=0;i<10;++i)
printf("arr[%d] = %d\n", i, arr[i]);
do
{//simple loop
i = *start;//assign whatever start points to to i
*start = *end;//assign value of *end to *start
*end = i;//assign initial value of *start (stored in i) to *end
} while ( ++start < --end);//make sure start is < end, increment start and decrement end
//check output:
for (i=0;i<10;++i)
printf("arr[%d] = %d\n", i, arr[i]);
return 0;
}
As you can see here, this reverses the array just fine.
Use reverse found in <algorithm>:
std::reverse(Arr, Arr+10);
It will reverse a set of data like you are requesting.
This is the approximate implementation of the function, which you could adapt if necessary to your needs if you would like to write the loop yourself:
template <class BidirectionalIterator>
void reverse (BidirectionalIterator first, BidirectionalIterator last)
{
while ((first!=last)&&(first!=--last)) {
std::iter_swap (first,last);
++first;
}
}
If you are in C or would like a less general solution, do something like this:
int i = 0; j = 9;
for(;i<j;++i;--j) {
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = arr[i];
}
Take two pointers begAr pointing at arr[0] and endAr pointing at arr[9]. Traverse the array from both sides and swap *begAr with *endAr until begAr > endAr.
int tempValAr;
while(endAr >= begAr )
{
tempValAr = *begAr;
*begAr++ = *endAr;
*endAr-- = tempValAr;
}
See the test program.

C++ concatenate two int arrays into one larger array

Is there a way to take two int arrays in C++
int * arr1;
int * arr2;
//pretend that in the lines below, we fill these two arrays with different
//int values
and then combine them into one larger array that contains both arrays' values?
Use std::copy defined in the header <algorithm>. The args are a pointer to the first element of the input, a pointer to one past the last element of the input, and a pointer to the first element of the output.
( https://en.cppreference.com/w/cpp/algorithm/copy )
int * result = new int[size1 + size2];
std::copy(arr1, arr1 + size1, result);
std::copy(arr2, arr2 + size2, result + size1);
Just suggestion, vector will do better as a dynamic array rather than pointer
If you're using arrays, you need to allocate a new array large enough to store all of the values, then copy the values into the arrays. This would require knowing the array sizes, etc.
If you use std::vector instead of arrays (which has other benefits), this becomes simpler:
std::vector<int> results;
results.reserve(arr1.size() + arr2.size());
results.insert(results.end(), arr1.begin(), arr1.end());
results.insert(results.end(), arr2.begin(), arr2.end());
Another alternative is to use expression templates and pretend the two are concatenated (lazy evaluation). Some links (you can do additional googling):
http://www10.informatik.uni-erlangen.de/~pflaum/pflaum/ProSeminar/
http://www.altdevblogaday.com/2012/01/23/abusing-c-with-expression-templates/
http://aszt.inf.elte.hu/~gsd/halado_cpp/ch06s06.html
If you are looking for ease of use, try:
#include <iostream>
#include <string>
int main()
{
int arr1[] = {1, 2, 3};
int arr2[] = {3, 4, 6};
std::basic_string<int> s1(arr1, 3);
std::basic_string<int> s2(arr2, 3);
std::basic_string<int> concat(s1 + s2);
for (std::basic_string<int>::const_iterator i(concat.begin());
i != concat.end();
++i)
{
std::cout << *i << " ";
}
std::cout << std::endl;
return 0;
}
Here is the solution for the same-
#include<iostream>
#include<bits/stdc++.h>
using namespace std;
void Concatenate(char *s1,char *s2)
{
char s[200];
int len1=strlen(s1);
int len2=strlen(s2);
int j;
///Define k to store the values on Kth address Kstart from 0 to len1+len2;
int k=0;
for(j=0;j<len1;j++)
{
s[k]=s1[j];
k++;
}
for(j=0;j<len2;j++)
{
s[k]=s2[j];
k++;
}
///To place a null at the last of the concatenated string to prevent Printing Garbage value;
s[k]='\n';
cout<<s;
}
int main()
{
char s1[100];
char s2[100];
cin.getline(s1,100);
cin.getline(s2,100);
Concatenate(s1,s2);
return 0;
}
Hope it helps.
for (int i = 0; i< arraySize * 2; i++)
{
if (i < aSize)
{
*(array3 + i) = *(array1 + i);
}
else if (i >= arraySize)
{
*(array3 + i) = *(array2 + (i - arraySize));
}
}
This might help you along, it doesn't require vectors. I had a similar problem in my programming class. I hope this helps, it was required that I used pointer arithmetic. This assumes that array1 and array2 are initialized dynamically to the size "aSize"
Given int * arr1 and int * arr2, this program Concatenates in int * arr3 the elements of the both arrays. Unfortunately, in C++ you need to know the sizes of each arrays you want to copy. But this is no impediment to choose how many elements you want to copy from arr1 and how many from arr2.
#include <iostream>
using namespace std;
int main(){
int temp[] = {1,2,3,4};
int temp2[] = {33,55,22};
int * arr1, * arr2, *arr3;
int size1(4), size2(3); //size1 and size2 is how many elements you
//want to copy from the first and second array. In our case all.
//arr1 = new int[size1]; // optional
//arr2 = new int[size2];
arr1=temp;
arr2=temp2;
arr3 = new int;
//or if you know the size: arr3 = new int[size1+size2];
for(int i=0; i<size1+size2; i++){
if (i<size1)
arr3[i]=arr1[i];
else
arr3[i] = arr2[i-size1];
}
cout<<endl;
for (int i=0; i<size1+size2; i++) {
cout<<arr3[i]<<", ";
}
}