Welcome, I have to code Quicksort Lomuto and Hoare variation in C++ using MinGW.
So, I have done it. Algorithms works fine for arrays[N] where N is small number like 5, 20, 100 but I need to do it on N = 200 000. And there is exception. I don't know why. Other algorithms(Insertion, Selection, Heapsort etc. works fine for N = 200 000).
Here is my code:
int PartitionLomuto(int A[], int p, int r)
{
int x = A[r],
i = p - 1,
temp;
for (int j = p; j <= r - 1; j++)
if (A[j] <= x) {
i++;
temp = A[i];
A[i] = A[j];
A[j] = temp;
}
temp = A[i + 1];
A[i + 1] = A[r];
A[r] = temp;
return i + 1;
}
void Lomuto (int A[], int p, int r)
{
if (p < r) {
int q = PartitionLomuto(A, p, r);
Lomuto(A, p, q - 1);
Lomuto(A, q + 1, r);
}
}
//* **************************************************
int PartitionHoare(int A[], int p, int r)
{
int x = A[p],
i = p,
j = r,
temp;
while(true) {
while(A[j] > x)
j--;
while(A[i] < x)
i++;
if(i < j) {
temp = A[i];
A[i] = A[j];
A[j] = temp;
i++;
j--;
}
else
return j;
}
}
void Hoare(int A[], int p, int r)
{
if(p < r) {
int q = PartitionHoare(A, p, r);
Hoare(A, p, q);
Hoare(A, q + 1, r);
}
}
I'm creating arrays in that way:
int const arraySize = 200000;
int *ascending = new int[arraySize],
*descending = new int[arraySize],
*random = new int[arraySize];
And call function in that way:
Hoare(random,0, arraySize - 1);
Exception is in Partition function.
I really don't know what is going. I think algorithm is written right.
Related
I've been having problems trying to figure out how to fix this code I wrote for Mergesort.
The intended result was to output a sorted array of inputs, but the void merge function contains errors that result in either an unsorted array or an array of really large or small numbers.
I've tried many times to fix them, but the result still doesn't come out perfectly.
Can you look it over and tell me what I've been doing wrong?
#include "pch.h"
#include <iostream>
using namespace std;
void merge(int* arr, int p, int q, int r) {
//copy A[p.q] into L
//and A[q+1.r] into R
int i, j, k;
int n1 = q - p + 1;
int n2 = r - q;
int* L = new int[n1+1];
int* R = new int[n2+1];
for (i = 1; i <= n1; i++) {
L[i] = arr[p+i-1];
}
for (j = 1; j <= n2; j++){
R[j] = arr[q+j];
}
L[n1+1] = 99999;
R[n2+1] = 99999; //represents infinity
i = j = 1;
for (k = p; k <= r; k++)
{
if (L[i] <= R[j]) {
arr[k] = L[i];
i = i + 1;
}
else {
arr[k] = R[j];
j = j + 1;
}
return;
}
}
void mergesort(int* arr, int p, int r) {
if (p < r) {
int q = floor((p + r) / 2);
mergesort(arr, p, q);
mergesort(arr, q + 1, r);
merge(arr, p, q, r);
}
return;
}
int main() {
int r;
cin >> r;
int* arr = new int[r];
for (int i = 0; i < r; i++) {
int num;
cin >> num;
arr[i] = num;
}
int p = 0;
//sortint function
mergesort(arr,p,r);
for (int i = 0; i < r; i++) {
cout << arr[i] << ";";
}
return 0;
}
Can someone please tell me why I am getting garbage value after sorting?
Initial call is (A,0,n) where n is the size of array? I want to sort the array using merge sort algorithm but without sentinel value.
void merge_sort(int A[], int l, int mid, int r)
{
int n1 = mid - l + 1;
int n2 = r - mid;
int L[n1], R[n2];
for (int i = 0; i < n1; i++)
{
L[i] = A[i];
}
for (int i = 0; i <= n2; i++)
{
R[i] = A[i + mid + 1];
}
cout << endl;
int j = 0, k = 0;
for (int i = l; i < r; i++)
{
if (j == n1 || k == n2)
{
if (j == n1 + 1)
{
A[i] = R[k];
k++;
}
else
{
A[i] = L[j];
j++;
}
}
else if (L[j] >= R[k])
{
A[i] = L[j];
j++;
}
else
{
A[i] = R[k];
k++;
}
}
}
void merge_divide(int A[], int l, int r)
{
if (l < r)
{
int mid = (l + r) / 2;
merge_divide(A, l, mid);
merge_divide(A, mid + 1, r);
merge_sort(A, l, mid, r);
}
}
There are a lot of moves in your logic that is hard to read. It is hard to distinguish where is an error or there is some intention here. But here it is how I see it with fixes. See inline comments.
void merge_sort(int A[], int l, int mid, int r) {
int n1 = mid - l;
int n2 = r - mid;
// this is C, but not C++, consider using vector instead
int L[n1], R[n2];
for (int i = 0; i < n1; i++) {
// need `l` here
L[i] = A[l + i];
}
for (int i = 0; i < n2; i++) {
// need to include `mid`
R[i] = A[i + mid];
}
int j = 0, k = 0;
for (int i = l; i < r; i++) {
if (j == n1) {
A[i] = R[k];
k++;
} else if (k == n2) {
A[i] = L[j];
j++;
} else if (L[j] >= R[k]) {
A[i] = L[j];
j++;
} else {
A[i] = R[k];
k++;
}
}
}
void merge_divide(int A[], int l, int r) {
// need properly compute `mid` here
int mid = r - l;
if (mid > 1) {
mid = l + mid / 2;
merge_divide(A, l, mid);
merge_divide(A, mid, r);
merge_sort(A, l, mid, r);
}
}
int main() {
int A[] = {2, 4, 3, 382, 2342334, 3, 42, 234};
int n = sizeof(A) / sizeof(int);
merge_divide(A, 0, n);
for (int i = 0; i < n; ++i)
cerr << A[i] << " ";
cout << endl;
}
I can't figure out what is wrong with my MergeSort function. This is my code:
void Merge(int* A, int p, int q, int r)
{
int B[100], i = 0, j = 0, k = 0;
i = p;
k = p;
j = q + 1;
while (i <= q && j <= r)
{
if (A[i] <= A[j])
{
B[k] = A[i];
k++;
i++;
}
else
{
B[k] = A[j];
k++;
j++;
}
}
while (i <= q)
{
B[k] = A[i];
k++;
i++;
}
while (j <= r)
{
B[k] = A[j];
k++;
j++;
}
for (i = p; i < r; i++)
{
A[i] = B[i];
}
}
void MergeSort(int A[], int p, int r)
{
int q;
if (p < r)
{
q = (p + r) / 2;
MergeSort(A, p, q);
MergeSort(A, q + 1, r);
Merge(A, p, q, r);
}
}
int main(void)
{
int N[10];
N[0] = 4;
N[1] = 5;
N[2] = 8;
N[3] = 12;
N[4] = 7;
N[5] = 3;
N[6] = 23;
N[7] = 1;
N[8] = 90;
N[9] = 26;
MergeSort(N, 0, 9);
for (int i = 0; i < 10; i++)
{
cout << N[i] << endl;
}
}
The output of program is: 1, 3, 1, 4, 5, 7, 7, 7, 26, 26, which is obviously wrong. However I just don't see what is wrong in code, to me everthing looks good. I googled some C++ codes of MargeSort and try to debug it but i can't find mistake. Anyone see it?
//you have just one err,in last for you missed = :
//err: for(i = p; i < r; i++)
//correct: for(i = p; i <= r; i++)
#include <iostream>
using namespace std;
void Merge(int* A, int p, int q, int r)
{
int B[100], i = 0, j = 0, k = 0;
i = p;
k = p;
j = q + 1;
while (i <= q && j <= r)
{
if (A[i] <= A[j])
{
B[k] = A[i];
k++;
i++;
}
else
{
B[k] = A[j];
k++;
j++;
}
}
while (i <= q)
{
B[k] = A[i];
k++;
i++;
}
while (j <= r)
{
B[k] = A[j];
k++;
j++;
}
for (i = p; i <= r; i++)
{
A[i] = B[i];
}
}
void MergeSort(int A[], int p, int r)
{
int q;
if (p < r)
{
q = (p + r) / 2;
MergeSort(A, p, q);
MergeSort(A, q + 1, r);
Merge(A, p, q, r);
}
}
int main(void)
{
int A[10]={9,8,7,6,5,4,3,2,1,0};
MergeSort(A,0,9);
for (int i = 0; i<10; i++)
{
cout<<A[i]<<",";
}
}
//this is cleaned version of your code:
#include <iostream>
using namespace std;
void Merge(int* A, int p, int q, int r)
{
int* B=new int[r-p+1];
int i = p;
int j = q + 1;
int k = 0;
while (i <= q && j <= r) B[k++] = (A[i] <= A[j])? A[i++] : A[j++];
while (i <= q) B[k++] = A[i++];
while (j <= r) B[k++] = A[j++];
for (i = p; i <= r; i++) A[i] = B[i-p];
delete B;
}
void MergeSort(int* A, int p, int r)
{
if (p >= r) return;
int q = (p + r) / 2;
MergeSort(A, p, q);
MergeSort(A, q + 1, r);
Merge(A, p, q, r);
}
int main(void)
{
int A[15]={10,11,12,13,14,0,8,7,6,5,4,3,2,1,9};
MergeSort(A,0,14);
for (int i = 0; i<15; i++) cout<<A[i]<<",";
}
//this is another answer:
#include <iostream>
#include <climits>
using namespace std;
static void Merge(int* A, int p, int q, int r)
{
int n1 = q - p + 1;// A[p..q]
int n2 = r - q;// A[q+1..r]
int* L = new int[n1 + 1];
int* R = new int[n2 + 1];
int i, j;
for (i = 0; i < n1; i++)
L[i] = A[p + i];
for (i = 0; i < n2; i++)
R[i] = A[q + i+1];
L[n1] = INT_MAX;
R[n2] = INT_MAX;
i = 0;
j = 0;
for (int k = p; k <= r; k++)
A[k] = L[i] <= R[j] ? L[i++] : R[j++];
delete L;
delete R;
}
static void Ascending(int* A, int p, int r)
{
if (p >= r) return;
int q = (p + r) / 2;
Ascending(A, p, q);
Ascending(A, q + 1, r);
Merge(A, p, q, r);
}
int main()
{
int A[10]={9,8,7,6,5,4,3,2,1,0};
Ascending(A,0,9);
for (int i = 0; i<10; i++)
{
cout<<A[i]<<",";
}
}
This implementation works reasonably quickly when threshold is set to 0 and it never uses insertion sort, however when i set threshold to seemingly any size 2 or greater it runs at the same speed as just insertion sort. Both sorting functions sort properly so i suspect there is something wrong with the implementation into c++ that is causing it to slow down significantly.
void insertion_sort(double* array, int l, int r)
{
for (int i = l; i <= r; i++)
{
double tmp = array[i];
int j = i;
while ((j >= 1) && (array[j - 1] > tmp))
{
array[j] = array[j - 1];
j--;
}
array[j] = tmp;
}
}
void merge(double* arr, double* temp, int l, int m, int r)
{
int i = l;
int j = m + 1;
int k = l;
while ((i <= m) && (j <= r))
{
if (arr[i] < arr[j])
{
temp[k] = arr[i];
i++;
}
else
{
temp[k] = arr[j];
j++;
}
k++;
}
for (; j <= r; j++, k++)
temp[k] = arr[j];
for (; i <= m; i++, k++)
temp[k] = arr[i];
for (i = l; i <= r; i++)
arr[i] = temp[i];
}
void mergesort(double* arr, double* temp, int l, int r, int threshold)
{
if (l < r)
{
if ((r - l) <= threshold)
insertion_sort(arr, l, r);
else
{
int m = (l + r) / 2;
mergesort(arr, temp, l, m, threshold);
mergesort(arr, temp, m + 1, r, threshold);
merge(arr, temp, l, m, r);
}
}
}
int main()
{
double array[100];
for(int i = 0;i<100;i++)
array[i] = rand() % 100 +1;
double * temp = new double[100];
mergesort(array,temp, 0, 99,10);
delete[] temp;
return 0;
}
the main function here doesn't have a large enough array to compare performance but the code used to test my merge sort is a bit to large to post here and pulls data from a text file and i wanted to provide an example of the initial function call.
The mistake is here:
while ((j >= 1) && (array[j - 1] > tmp))
Instead of J >= 1 it should be j > l (the letter l).
So i attempted to use insertion sort with quick sort to try to speed it up, but it isn't working for a reason i can't figure out. The sort operated correctly before i added the insertion sort part.
void QuickSort(int data[], int p, int r)
{
if (p < r)
{
if (r - p < 10)
{
InsertionSort(data, p, r);
return;
}
int pivotIndex = Partition(data, p, r);
QuickSort(data, p, pivotIndex - 1);
QuickSort(data, pivotIndex + 1, r);
}
}
void InsertionSort(int data[], int p,int r)
{
int i, j, temp;
for (i = p; i<(r-p)+1; i++)
{
temp = data[i];
for (j = i - 1; j >= 0 && data[j]>temp; j--)
data[j + 1] = data[j];
data[j + 1] = temp;
}
}
Full Source code here:-https://gist.github.com/anonymous/9856210
I'm wondering why you need to do
i < (r-p) + 1
I have my suspicious on that part.
void InsertionSort(int data[], int p,int r)
{
int i, j, temp;
for (i = p; i <= r; i++)
{
temp = data[i];
for (j = i - 1; j >= 0 && data[j]>temp; j--)
data[j + 1] = data[j];
data[j + 1] = temp;
}
}