I am trying to write a merge sort algorithm using template functions in c++. The output is close but not correct. When I give the function the array [7, 6, 4, 8, 1, 2, 3], it returns [1, 1, 2, 2, 3, 3, 8]. I specifically believe that the problem is in the merge function rather than the merge sort function. Any help would be much appreciated. Here is my code:
template <class T1>
void mergeSort(T1 array[], int lower, int upper)
{
if (lower < upper)
{
int middle = (lower + upper) / 2;
mergeSort(array, lower, middle);
mergeSort(array, middle + 1, upper);
merge(array, lower, middle, upper);
}
}
template <class T1>
void merge(T1 array1[], int lower, int middle, int upper)
{
int i = 0,
j = 0,
k = 0;
int size1 = middle - lower + 1;
int size2 = upper - middle;
T1* temp1 = new T1[size1];
T1* temp2 = new T1[size2];
for (int i = 0; i < size1; i++)
{
temp1[i] = array1[lower + i];
}
for (int j = 0; j < size2; j++)
{
temp2[j] = array1[middle + 1 + j];
}
while (i < size1 && j < size2)
{
if (temp1[i] < temp2[j])
{
array1[k] = temp1[i];
i++;
}
else
{
array1[k] = temp2[j];
j++;
}
k++;
}
if (i == size1)
{
while (j < size2)
{
array1[k] = temp2[j];
k++;
j++;
}
}
else
{
while (i < size1)
{
array1[k] = temp1[i];
k++;
i++;
}
}
}
int main(){
int a[] = { 7, 6, 4, 8, 1, 2, 3 };
mergeSort(a, 0, 6);
}
Output:
1 1 2 2 3 3 8
In your merge function you shouldn't initialize k to 0 because it will write the result of merge in the wrong place. Instead you should initialize k to lower. Because that is the start index of the part you are actually sorting.
Related
This code is supposed to be an Insertion sort but is it implemented as such? I'm lost. The first loop goes through the array and checks if the next element is smaller than the current element. The nested loop inserts the next element(j) correctly in its place in the sorted portion of the array.
#include <iostream>
using namespace std;
// Print array
void printArray(int array[], int arraySize)
{
for (int i = 0; i < arraySize; i++)
{
cout << array[i] << " ";
}
cout << endl;
}
int main()
{
int array1[] ={5, 3, 1, 9, 8, 2, 4, 7};
int array1Size = sizeof(array1)/sizeof(int);
printArray(array1, array1Size);
for (int i = 0; i < array1Size - 1; i++)
{
int oldNum = array1[i];
if (array1[i] > array1[i + 1])
{
array1[i] = array1[i + 1];
array1[i + 1] = oldNum;
}
int newI = array1[i];
// Check if arranged correctly
if ( i > 0)
{
// Swap bigger number and newI
for (int j = i - 1; newI < array1[j]; j--)
{
if (j < 0)
{
break;
}
array1[j + 1] = array1[j];
array1[j] = newI;
}
}
printArray(array1, array1Size);
}
return 0;
}
The key to insertion sort is to maintain a "sorted zone" and expand it in loop. In the beginning the zone is only one element, and finally it's all the list. We take an element outside the sorted zone and decide which position in sorted zone that it should be placed in.
BTW, loop invariant is easy to understand but powerful and awesome. Recommended.
int main() {
int array1[] ={5, 3, 1, 9, 8, 2, 4, 7};
int array1Size = sizeof(array1)/sizeof(int);
// loop invariant: array1[0..i-1] is sorted
// array1[i] is the element to be inserted
for (size_t i = 1; i < array1Size; i++) {
int temp = array1[i];
// find the right place to insert array1[i]. Can be replaced by binary search(but moving elements is more expensive than comparing)
size_t j = i; // j is used to save the right place
for (; j > 0 && array1[j-1] > temp; j--) {
array1[j] = array1[j-1];
}
array1[j] = temp;
}
return 0;
}
This for loop
for (int j = i - 1; newI < array1[j]; j--)
{
if (j < 0)
{
break;
}
array1[j + 1] = array1[j];
array1[j] = newI;
}
can invoke undefined behavior when j is equal to -1 due to this expression in the condition of the for loop
newI < array1[j]
And the code is too complicated. For example this code snippet
if (array1[i] > array1[i + 1])
{
array1[i] = array1[i + 1];
array1[i + 1] = oldNum;
}
where two elements are swapped is redundant. And this if statement
if ( i > 0)
{
also is redundant. It is enough to start the outer loop from 1 instead of from 0.
It is better to define a separate function. It can look for example the following way
void InsertionSort( int a[], size_t n )
{
for (size_t i = 1; i < n; i++)
{
if (a[i] < a[i - 1])
{
int tmp = a[i];
size_t j = i;
for ( ; j != 0 && tmp < a[j - 1]; --j )
{
a[j] = a[j - 1];
}
a[j] = tmp;
}
}
}
Pay attention to that the operator sizeof yields a value of the type size_t. You should use this type size_t for the variable that will be store the number of elements in the array. In general the type int is not large enough to store sizes of arrays.
If your compiler supports C++ 17 then instead of using the expression with the sizeof operator
int array1Size = sizeof(array1)/sizeof(int);
you could write at least
#include <iterator>
//...
int array1Size = std::size( array1 );
Also as the function printArray does not change the passed array then it first parameter should be declared with the qualifier const.
void printArray(const int array[], int arraySize);
Here is a demonstration program that shows usage of a separate function that sorts arrays using the insertion sort method..
#include <iostream>
#include <iterator>
void InsertionSort( int a[], size_t n )
{
for (size_t i = 1; i < n; i++)
{
if (a[i] < a[i - 1])
{
int tmp = a[i];
size_t j = i;
for ( ; j != 0 && tmp < a[j - 1]; --j )
{
a[j] = a[j - 1];
}
a[j] = tmp;
}
}
}
int main()
{
int array1[] ={5, 3, 1, 9, 8, 2, 4, 7};
for ( const auto &item : array1 )
{
std::cout << item << ' ';
}
std::cout << '\n';
InsertionSort( array1, std::size( array1 ) );
for ( const auto &item : array1 )
{
std::cout << item << ' ';
}
std::cout << '\n';
}
The program output is
5 3 1 9 8 2 4 7
1 2 3 4 5 7 8 9
I am new to programming, and I have been learning about Merge Sort Algorithm, I wrote the following code:
#include <iostream>
using namespace std;
void Merge(int *arr1, int i, int m, int n, int j)
{
int sizeOfNewArray = j - i + 1;
int sizeOfFirstArray = m - i + 1;
int sizeOfSecondArray = j - n + 1;
int *finalArray = new int[sizeOfNewArray];
int *k = &finalArray[i];
int *ptr1 = &arr1[i];
int *ptr2 = &arr1[n];
while (i < sizeOfFirstArray && j < sizeOfSecondArray)
{
if (*ptr1 >= *ptr2)
{
*k = *ptr1;
i++;
k++;
}
else if (*ptr1 < *ptr2)
{
*k = *ptr2;
j++;
k++;
}
}
while (i < sizeOfFirstArray)
{
*k = *ptr1;
i++;
k++;
}
while (j < sizeOfSecondArray)
{
*k = *ptr2;
j++;
k++;
}
}
void MergeSort(int *arr1, int i, int j)
{
if (i != j)
{ //i represnts first index of array, j represents last index of array
int m = (i + j) / 2;
MergeSort(arr1, i, m);
MergeSort(arr1, m + 1, j);
Merge(arr1, i, m, m + 1, j);
}
if (i == j)
{
return;
}
}
int main()
{
int arr[] = {8, 6, 7, 1, 2, 4, 3, 5};
MergeSort(arr, 0, 7);
for (int i = 0; i < 8; i++)
{
cout << arr[i] << endl;
}
return 0;
}
According to me, this program should return the sorted array 1,2,3,4,5,6,7,8. However,on executing this code, it prints
8
6
7
1
2
4
3
5
I have tried debugging the code, but I am not able to find out what the error is. Can someone please have a look at the code, and tell me where is the error?
Apologies in advance for any silly error and thanks for taking out your time and concern.
Merge merges into the finalArray, which has nothing to do with arr1. Once Merge returns, finalArray ceases to exist (leaking memory), and arr1 remains untouched.
Before return, copy finalArray back to arr1, and delete[] it.
I made a quicksort in C++ but it doesn't work well. For example, if I have an array of {5, 3, 4, 6, 7}, the outcome will be {0, 3, 4, 5, 6}. I can't find the reason since I used the same method in Pascal before and that worked perfectly.
#include <iostream>
using namespace std;
void qsort(int (&ary)[10000], int l, int r){
int i = l, j = r, mid = ary[(l + r) / 2];
while (i <= j){
while (ary[i] < mid) i ++;
while (ary[j] > mid) j --;
if (i <= j){
int temp = ary[i];
ary[i] = ary[j];
ary[j] = temp;
i ++; j --;
}
}
if (i < r) qsort(ary, i, r);
if (l < j) qsort(ary, l, j);
}
int main(){
int n;
int a[10000];
cin >> n;
for (int i = 0; i < n; i ++){
cin >> a[i];
}
qsort(a, 0, n);
for (int i = 0; i < n; i ++){
cout << a[i] << ' ';
}
return 0;
}
line 27: should be
qsort(a, 0, n-1);
Hey i got this algorithm from my class called Bubble Sort. It uses two "for" one inside the other. But when i tried to do it with "while" it didnt work, aren't they equivalent ?
void bubbleSort(int v[], int n) { // void workingBubble(int v[], int n){
int fim = n - 1; // int i, fim;
int i = 0; // for(fim=n-1; fim>0; fim--){
int aux; // for(i=0; i<fim; i++){
while (fim > 0) { // if(v[i] > v[i+1]){
while (i < fim) { // int temp = v[i];
if (v[i] > v[i + 1]) { // v[i] = v[i+1];
aux = v[i]; // v[i+1] = temp;
v[i] = v[i + 1]; // }
v[i + 1] = aux; // }
} // }
i++; // }
} //
fim--; //
}}
I commented the one that worked next to the other so i could compare, i thought it was the same but with while instead of for
Array = {10, 2, 8, 11, 5, 3, 27, 1}
Array after bubble sort = {2, 8, 10, 5, 3, 11, 1, 27}
Reset i to 0 each time before the inner loop:
void bubbleSort(int v[], int n) {
int fim = n - 1;
int i;
int aux;
while (fim > 0) {
i = 0;
while (i < fim) {
if (v[i] > v[i + 1]) {
aux = v[i];
v[i] = v[i + 1];
v[i + 1] = aux;
}
i++;
}
fim--;
}
}
I am working on a quicksort algorithm implementation in c++ and I have not been able to get it to work as it should. I have researched several sources and my code looks flawless, but the array is not sorting as it should.
Here is my code:
#include <iostream>
using namespace std;
void quicksort(int[],int, int);
int partition(int[], int, int);
int main()
{
int a[] = {5, 1, 9, 3, 8, 4, 1, 2, 6, 7};
for (int i = 0; i < 10; i++)
{
cout << a[i] << " ";
}
cout << endl;
quicksort(a, 0, 9);
for (int i = 0; i < 10; i++)
{
cout << a[i] << " ";
}
return 0;
}
void quicksort(int a[], int p, int r)
{
if (p < r)
{
int q = partition(a, p, r);
quicksort(a, p, q - 1);
quicksort(a, q + 1, r);
}
}
int partition(int a[], int p, int r)
{
int x = a[r];
int i = (p - 1);
for (int j = p; j <= r-1; j++)
{
if (a[j] <= x)
{
i++;
int tmp = a[i];
a[i] = a[j];
a[j] = tmp;
}
}
int tmp = a[i+1];
a[i+1] = a[r];
a[r] = a[tmp];
return (i + 1);
}
When I run this code the following is displayed:
5 1 9 3 8 4 1 2 6 7
1 1 2 4 4 4 6 7 7 7
I am not sure what I am doing wrong here. Thanks for your help.
In the second to last line of your partition function you should have:
a[r] = tmp;
instead of:
a[r] = a[tmp];
You are overwriting parts of your array with other members instead of completing the third step of your swap.