Quicksort median of 3, 5, 7 elements problem - c++

I'am facing huge problem with quicksort alghoritm. I have to choose pivot with median of 3, 5 and 7 elements of array. I've done it for 3 elements but it is not working properly and I don't know how to remake this code alternatively to make it for median of 5 and 7 elemenets. How to choose pivot from median of more than 3 elemenets?
Please don't hate me im trying to learn.
Quicksort func:
void quickSort(int arr[], int low, int high)
{
if (low < high)
{
int pi = partition_3(arr, low , high);
quickSort(arr, low, pi);
quickSort(arr, pi + 1, high);
}
}
Partition:
int partition( int arr[], int low, int high)
{
int pivot = arr[low];
int i = low - 1, j = high + 1;
while (true) {
do {
i++;
} while (arr[i] < pivot);
do {
j--;
} while (arr[j] > pivot);
if (i >= j)
return j;
swap(arr[i], arr[j]);
}
}
Partition median of 3:
int partition_3(int arr[], int low, int high)
{
int tab[] = { low,(high -low) / 2,high };
sort(tab, tab + 3);
int ind = 3 / 2;
int mediana = tab[ind];
swap(arr[mediana], arr[low]);
return partition(arr, low, high);
}

Related

How does Hoare partitioning work in QuickSort?

Here is the pseudocode straight from the book (CORMEN):
Partition(A,p,r)
x=A[p]
i=p-1
j=r+1
while(TRUE)
repeat
j=j-1
until A[j]<=x
repeat
i=i+1
until A[i]>=x
if i<j
SWAP A[i] <=> A[j]
else return j
Here is code in C++:
#include<bits/stdc++.h>
using namespace std;
int partition(int a[], int low, int high)
{
int pivot = a[low];
int i = low - 1;
int j = high + 1;
while (1)
{
do {
i++;
} while (a[i] < pivot);
do {
j--;
} while (a[j] > pivot);
if (i >= j) {
cout<<j<<endl;
return j;
}
swap(a[i], a[j]);
}
}
/* The main function that implements QuickSort
arr[] --> Array to be sorted,
low --> Starting index,
high --> Ending index */
void quickSort(int arr[], int low, int high)
{
if (low < high)
{
/* pi is partitioning index, arr[p] is now
at right place*/
int pi = partition(arr, low, high);
// Separately sort elements before
// partition and after partition
quickSort(arr, low, pi - 1);
quickSort(arr, pi + 1, high);
}
}
/* Function to print an array */
void printArray(int arr[], int size)
{
int i;
for (i=0; i < size; i++)
printf("%d ", arr[i]);
printf("\n");
}
// Driver program to test above functions
int main()
{
int arr[] = {7,3,2,6,4,1,3,5};
int n = sizeof(arr)/sizeof(arr[0]);
cout<<"partition:\n";
partition(arr,0,7);
printArray(arr, n);
quickSort(arr, 0, n-1);
printf("Sorted array: \n");
printArray(arr, n);
return 0;
}
If I use this array in input:
[5,3,2,6,4,1,3,7]
everything works logically well because the array returned by the partitioning will be:
[3,3,2,1,4,6,5,7]
Termination i=5 and j=4 so my pivot is 4. And all elements to the left of 4 are minor and all to the right are major
Now if I use this array in input:
[7,3,2,6,4,1,3,5]
I will have this situation at the end of the partition
[5,3,2,6,4,1,3,7]
which will return to me as pivot j = 6 that is 3. Now the elements on the left of 3 are not all minor and on the right are major.
But how is it possible that this works? Shouldn't I have the elements to the left of the pivot minor and to the right major?
With Hoare partition the pivot and values equal to the pivot can end up anywhere. The returned index is not an index to the pivot, but just a separator. For the code above, when partition is done, then elements <= pivot will be at or to the left of j, and elements >= pivot will be to the right of j. After doing a partition step, the C++ code should be:
quickSort(arr, low, pi); // not pi - 1
quickSort(arr, pi + 1, high);
example code that includes testing of quicksort:
uint32_t Rnd32()
{
static uint32_t r = 0;
r = r*1664525 + 1013904223;
return r;
}
int Partition(int ar[], int lo, int hi)
{
int pv = ar[lo+(hi-lo)/2];
int i = lo - 1;
int j = hi + 1;
while(1){
while(ar[++i] < pv);
while(ar[--j] > pv);
if(i >= j)
return j;
std::swap(ar[i], ar[j]);
}
}
void QuickSort(int ar[], int lo, int hi)
{
while (lo < hi){
int pi = Partition(ar, lo, hi);
if((pi - lo) < (pi - hi)){
QuickSort(ar, lo, pi);
lo = pi + 1;
} else {
QuickSort(ar, pi + 1, hi);
hi = pi;
}
}
}
#define COUNT (16*1024*1024)
int main(int argc, char**argv)
{
size_t i;
int * ar = new int [COUNT];
for(i = 0; i < COUNT; i++){
ar[i] = Rnd32();
}
QuickSort(ar, 0, COUNT-1);
for(i = 1; i < COUNT; i++)
if(ar[i-1] > ar[i])
break;
if(i == COUNT)
std::cout << "passed" << std::endl;
else
std::cout << "failed" << std::endl;
delete[] ar;
return(0);
}

I can't see why Im getting segmentation fault error

I'm currently trying to learn Quick Sort, and here is my code:
#include<iostream>
#include<vector>
#include<cmath>
using namespace std;
void swap(int *a, int *b)
{
int t = *a;
*a = *b;
*b = t;
}
int partition(vector<int> &A, int low, int high)
{
int pivot = A[low];
int i = low;
int j = high;
while(i < j){
do
{
i++;
}while(A[i]>=pivot);
do
{
j--;
}while(A[j]<pivot);
if(i < j)
{
swap(A[i], A[j]);
}
}
swap(A[low], A[j]);
return j;
}
void QuickSort(vector<int> &A, int low, int high)
{
int j = partition(A, low, high);
QuickSort(A, low, j);
QuickSort(A, j+1, high);
}
int main()
{
vector<int> A{-7, 11, -3, 3, 2};
QuickSort(A, 0, A.size()-1);
for(int i:A)
{
cout << i << endl;
}
}
after the code ran, I keep getting Segmentation fault (core dumped), how do I fix this error.
also, could any one recommend a good c++ debugger. thank you so much
You have infinite recursion in your QuickSort function. Whenever it gets called, it'll call itself and there is no condition there to break the cycle.
Also, your swap function does not work. As it is written, the values in the A bins will be supplied to the function and interpreted as addresses. That should not compile. The only reason why it does compile is that you don't use that function in your program. You are using std::swap because you've done using namespace std;, so don't do that.
Your swap function should take the arguments by reference and you need to add a condition in the QuickSort function.
I wasn't sure exactly which partitioning scheme you tried implementing so I made some changes to make it work in accordance with the Hoare partition scheme.
#include <iostream>
#include <vector>
void swap(int& a, int& b) { // take arguments by reference
int t = a;
a = b;
b = t;
}
size_t partition(std::vector<int>& A, size_t low, size_t high) {
int pivot = A[(high + low) / 2];
size_t i = low;
size_t j = high;
while(true) {
while(A[i] < pivot) ++i;
while(A[j] > pivot) --j;
if(i >= j) return j;
swap(A[i], A[j]);
++i;
--j;
}
}
void QuickSort(std::vector<int>& A, size_t low, size_t high) {
if(low < high) { // added condition
size_t j = partition(A, low, high);
QuickSort(A, low, j);
QuickSort(A, j + 1, high);
}
}
int main() {
std::vector<int> A{-7, 11, -3, 3, 2};
QuickSort(A, 0, A.size() - 1);
for(int i : A) {
std::cout << i << '\n';
}
}

Iteration on Quick Sort

I was trying to implement quick sort now. But, i have some problem with the loop part below
for (int current = 0; current <= high - 1; current++)
When i initialize that 'current' statement with 0, it show nothing on the screen when i run it. Then, i try to replace it with 'low' argument like in the implementation provided and it was run appropriately.
What i want to ask is, why it doesn't work when i initialize the loop statement with 0, which was the same value assigned to 'low' parameter? I have tried initialize new variable with 0 and use that variable to the loop, but it give the same result like when i directly assign the loop statement with 0. Thanks for the answer.
Here the code:
int partition(int arr[], int low, int high)
{
int pivot = arr[high];
int index = (low - 1);
for (int current = low; current <= high - 1; current++)
{
if (arr[current] <= pivot)
{
index++;
swap(arr[index], arr[current]);
}
}
swap(arr[index+1], arr[high]);
return (index + 1);
}
void quicksort(int arr[], int low, int high)
{
if (low < high)
{
int pi = partition(arr, low, high);
quicksort(arr, low, pi - 1);
quicksort(arr, pi + 1, high);
}
}
int main()
{
int arr[] = { 3, 4, 2, 5, 1 };
int n = sizeof(arr)/sizeof(arr[0]);
quicksort(arr, 0, n-1);
for (int i = 0; i < n; i++)
{
cout << arr[i] << " ";
}
}
The result when i set the 'current' value with 0
low is only 0 in the first call to partition; it takes different values in other calls. Note that when quicksort calls itself the second time, low will get assigned pi + 1.
Print it out in the beginning of partition to observe this for some known not-too-large array - this should be a good educational exercise in general. I mean make the first line of partition:
cout << "low = " << low << "\n";

My mergesort function is spitting out 0's instead of ordering my list

I'm trying to make a Mergesort function and can't seem to understand why my list is printing out "00000100000". I have a feeling it might be my auxiliary array that i'm passing through, but i'd like to keep it in my code if possible. Here is my code:
void merge(int arr[], int aux[], int low, int mid, int high)
{
int leftStart = low;
int rightStart = mid+1;
int auxIndex = low;
int start = low;
while(leftStart<=mid && rightStart<= high)
{
if(arr[leftStart]>=arr[rightStart])
{
aux[auxIndex] = arr[rightStart];
auxIndex++;
rightStart++;
}
else
aux[auxIndex] = arr[leftStart];
auxIndex++;
leftStart++;
}
if(leftStart>mid)
{
for(;rightStart<=high; rightStart++)
{
aux[auxIndex] = arr[rightStart];
}
}
if(rightStart>high)
{
for(;leftStart<=high; leftStart++)
{
aux[auxIndex] = arr[rightStart];
}
}
for(; start <= high; start++)
arr[start]=aux[start];
}
void mergeSort(int arr[], int aux[], int low, int high)
{
int mid;
if(low<high)
{
mid=(low+high)/2;
mergeSort(arr, aux, low, mid);
mergeSort(arr, aux, mid+1, high);
merge(arr,aux, low, mid, high);
}
}
int main(int argc, char *argv[]) {
int arr[20]={6,4,3,2,1,7,8,9,5,6,7,5};
for(int i = 0; i<12; i++)
cout<<arr[i];
int aux[20];
mergeSort(arr, aux, 0, 12);
for(int i = 0; i<12; i++)
cout<<arr[i];
return 0;
}
Run your program under valgrind or an equivalent analysis tool. You will find that there are straightforward errors in your code related to array accesses.

C++ quick sort algorithm

I'm not looking to copy a qsort algorithm. I'm practicing writing qsort and this is what I've come up with and I'm interested in what part of my code is wrong. Please don't tell me that this is homework cause I could just use the code in the link below.
Reference: http://xoax.net/comp/sci/algorithms/Lesson4.php
When this runs I get this in the console:
Program loaded.
run
[Switching to process 10738]
Running…
Current language: auto; currently c++
Program received signal: “EXC_ARITHMETIC”.
void myQSort(int min, int max, int* myArray)
{
// Initially find a random pivot
int pivotIndex = rand() % max;
int pivot = myArray[pivotIndex];
int i = 0 , j = max-1;
// Pointer to begining of array and one to the end
int* begin = myArray;
int* end = &myArray[max-1];
// While begin < end
while( begin < end )
{
// Find the lowest bound number to swap
while( *begin < pivot )
{
begin++;
}
while( *end > pivot )
{
// Find the highest bound number to swap
end--;
}
// Do the swap
swap(begin,end);
}
// Partition left
myQSort(0, pivotIndex-1, myArray);
// Partiion right
myQSort(pivotIndex+1,max, myArray);
}
EDIT--
Code for Swap:
void swap(int* num, int* num2)
{
int temp = *num;
*num = *num2;
*num2 = temp;
}
// sort interval [begin, end)
void myQSort(int* begin, int* end)
{
if(end - begin < 2)
return;
int* l = begin;
int* r = end - 1;
// Initially find a random pivot
int* pivot = l + rand() % (r - l + 1);
while(l != r)
{
// Find the lowest bound number to swap
while(*l < *pivot) ++l;
while(*r >= *pivot && l < r) --r;
// Do the swap
if(pivot == l) { pivot = r; }
std::swap(*l, *r);
}
// Here l == r and numbers in the interval [begin, r) are lower and in the interval [l, end) are greater or equal than the pivot
// Move pivot to the position
std::swap(*pivot, *l);
// Sort left
myQSort(begin, l);
// Sort right
myQSort(l + 1, end);
}
You're not using the min parameter in your code, anywhere. You need to set begin and your pivot value using that.
I tried working out the codes above. But, they don't compile.
#Mihran: Your solution is correct algorithmically but the following line generates an error:
myQSort(min, begin - myArray, myArray);
This is because begin is of type int* and myArray is of type long, following which the compiler shows this error message:
implicit conversion loses integer precision
Here's a working solution in C++:
#include <iostream>
using namespace std;
void mySwap(int& num1, int& num2){
int temp = num1;
num1 = num2;
num2 = temp;
}
void myQsort(int myArray[], int min, int max){
int pivot = myArray[(min + max) / 2];
int left = min, right = max;
while (left < right) {
while (myArray[left] < pivot) {
left++;
}
while (myArray[right] > pivot) {
right--;
}
if (left <= right) {
mySwap(myArray[left], myArray[right]);
left++;
right--;
}
}
if (min < right) {
myQsort(myArray, min, right);
}
if (left < max) {
myQsort(myArray, left, max);
}
}
int main()
{
int myArray[] = {1, 12, -5, 260, 7, 14, 3, 7, 2};
int min = 0;
int max = sizeof(myArray) / sizeof(int);
myQsort(myArray, min, max-1);
for (int i = 0; i < max; i++) {
cout<<myArray[i]<<" ";
}
return 0;
}
Here's a clear C++ implementation, for reference:
#include <iostream>
#include <vector>
using namespace std;
int partition(std::vector<int>& arr, int low, int high) {
// set wall index
int wall_index = low;
int curr_index = low;
int pivot_elem = arr[high]; // taking last element as pivot_element
// loop through the entire received arr
for (int i = curr_index; i < high; ++i) {
// if element is less than or equal to pivot_elem
// swap the element with element on the right of the wall
// i.e swap arr[i] with arr[wall_index]
if (arr[i] <= pivot_elem) {
// swap
int temp = arr[wall_index];
arr[wall_index] = arr[i];
arr[i] = temp;
// move the wall one index to the right
wall_index++;
curr_index++;
} else {
// if the element is greater than the pivot_element
// then keep the wall at the same point and do nothing
curr_index++;
}
}
// need to swap the pivot_elem i.e arr[high] with the element right of the wall
int temp = arr[wall_index];
arr[wall_index] = arr[high];
arr[high] = temp;
return wall_index;
}
void quick_sort(std::vector<int>& arr, int low, int high) {
if (low < high) { // element with single arr always have low >= high
int split = partition(arr, low, high);
quick_sort(arr, low, split-1);
quick_sort(arr, split, high);
}
}
int main() {
std::vector<int> data = {6,13,8,4,2,7,16,3,8};
int N = data.size();
quick_sort(data, 0, N-1);
for (int i : data) {
cout << i << " ";
}
return 0;
}
I don't see a clean implementation of Quicksort on SO, so here is my easy to understand implementation
PLEASE DONT USE IN PRODUCTION CODE
This is only for your understanding
// Swap position a with b in an array of integer numbers
void swap(int *numbers, int a, int b){
int temp = numbers[a];
numbers[a] = numbers[b];
numbers[b] = temp;
}
static int partition(int *data, int low, int high) {
int left = low, right = high, pivot = data[low];
while (left < right) {
// Everthing on the left of pivot is lower than the pivot
while ((left <= right) && data[left] <= pivot) // <= is because left is the pivot initially
left++;
// Everything on the right of the pivot is greater than the pivot
while((left <= right) && data[right] > pivot)
right--;
if (left < right)
swap(data, left, right);
}
// Put the pivot in the 'rigthful' place
swap(data, low, right);
return right;
}
// Quicksort
static void quick_sort(int *numbers, int low, int high)
{
if (high > low) {
int p_index = partition(numbers, low, high);
quick_sort(numbers, low , p_index - 1);
quick_sort(numbers, p_index + 1, high);
}
}