moved partition function into common; combined partition magic and fixed randomizedSelect for HoarePartitioning

This commit is contained in:
incredibleLeitman 2020-10-18 01:30:06 +02:00
parent 5ac57571eb
commit 0cfd9e66ec
3 changed files with 101 additions and 134 deletions

View File

@ -1,40 +1,26 @@
#pragma once
uint32_t pivotPartition(std::vector<uint32_t>& values, uint32_t left, uint32_t right) {
uint32_t pivotIndex = left + (right - left) / 2;
uint32_t pivotValue = values[pivotIndex];
int i = left;
int j = right;
while (i <= j) {
while (values[i] < pivotValue)
{
i++;
}
while (values[j] > pivotValue)
{
j--;
}
if (i <= j) {
swap(&values[i], &values[j]);
i++;
j--;
}
}
return i;
int pivotPartition(std::vector<uint32_t>& a, int p, int r) {
return partition(a, p, r);
}
void quicksort(std::vector<uint32_t>& values, uint32_t left, uint32_t right)
void quicksort(std::vector<uint32_t>& a, int p, int r)
{
if (left < right) {
uint32_t pivotIndex = pivotPartition(values, left, right);
quicksort(values, left, pivotIndex - 1);
quicksort(values, pivotIndex, right);
if (p < r) {
int i = pivotPartition(a, p, r);
#ifdef PARTITION_TYPE_LOMUTO
quicksort(a, p, i - 1);
#elif defined PARTITION_TYPE_HOARE
quicksort(a, p, i);
#endif
quicksort(a, i + 1, r);
}
}
uint32_t getQuicksortMedian(std::vector<uint32_t> values, uint32_t i)
uint32_t getQuicksortMedian(std::vector<uint32_t> a, int i)
{
//std::qsort(numbers); // only takes array param -> custom implementation with vector
quicksort(values, 0, values.size() - 1);
return values[i];
quicksort(a, 0, a.size() - 1);
return a[i];
}

View File

@ -1,120 +1,49 @@
#pragma once
#include <vector>
// Lomuto Partitioning
int randomizedPartition(std::vector<uint32_t>& values, int p, int r)
int randomizedPartition(std::vector<uint32_t>& a, int p, int r)
{
int i = p + rand() % (r - p); // generate a random number in {p, ..., r}
swap(&values[i], &values[r]);
uint32_t pivotValue = values[r];
i = p - 1;
for (int j = p; j < r; j++)
{
if (values[j] <= pivotValue)
{
i++;
swap(&values[i], &values[j]);
}
}
swap(&values[i + 1], &values[r]);
return (i + 1);
// generate a random number in {p, ..., r} to swap
#ifdef PARTITION_TYPE_LOMUTO
int i = p + rand() % (r - p);
swap(&a[i], &a[r]);
#elif defined PARTITION_TYPE_HOARE
int i = rand() % (r - p + 1);
swap(&a[p + i], &a[r]);
#endif
return partition(a, p, r);
}
// TODO: Hoare Partitioning
// https://www.geeksforgeeks.org/quicksort-using-random-pivoting/
int randomizedPartition2(std::vector<uint32_t>& values, int low, int high)
uint32_t randomizedSelect(std::vector<uint32_t>& a, int p, int r, int i)
{
int i = low + rand() % (high - low); // generate a random number in {p, ..., r}
swap(&values[i], &values[low]);
uint32_t pivotValue = values[low];
i = low - 1;
int j = high + 1;
while (true) {
// Find leftmost element greater than
// or equal to pivot
do {
i++;
} while (values[i] < pivotValue);
// Find rightmost element smaller than
// or equal to pivot
do {
j--;
} while (values[j] > pivotValue);
// If two pointers met
if (i >= j)
return j;
swap(&values[i], &values[j]);
}
}
int randomizedPartition3(std::vector<uint32_t>& values, int l, int r)
{
int i = rand() % (r - l + 1);
swap(&values[l + i], &values[r]);
uint32_t pivotValue = values[r];
i = l;
for (int j = l; j <= r - 1; j++)
{
if (values[j] <= pivotValue)
{
swap(&values[i], &values[j]);
i++;
}
}
swap(&values[i], &values[r]);
return i;
}
uint32_t randomizedSelect(std::vector<uint32_t>& values, int p, int r, int i)
{
/*
// Partition the array around a random element and
// get position of pivot element in sorted array
int pos = randomizedPartition(values, p, r);
// If position is same as k
if (pos - p == i - 1)
return values[pos];
if (pos - p > i - 1) // If position is more, recur for left subarray
return randomizedSelect(values, p, pos - 1, i);
// Else recur for right subarray
return randomizedSelect(values, pos + 1, r, i - pos + p - 1);
*/
// -----------------------------------------------------------
// Pseudo code Alux Nimmervoll, Algo vo3
// Anmerkung: code funktioniert!
/*
RANDOMIZED-SELECT(A,p,r,i)
if (p==r) then return A[p]
q=RANDOMIZED_PARTITION(A,p,r) //Pivot Element A[q]
k=q-p+1 //Anzahl Elemente A[p..q]
if (i==k) then return A[q] //Pivot ist das gesuchte
elseif (i<k)
then return RANDOMIZED-SELECT(A,p,q-1,i)
else return RANDOMIZED-SELECT(A,q+1,r,i-k)
*/
//
// RANDOMIZED-SELECT(A,p,r,i)
// if (p==r) then return A[p]
// q=RANDOMIZED_PARTITION(A,p,r) //Pivot Element A[q]
// k=q-p+1 //Anzahl Elemente A[p..q]
// if (i==k) then return A[q] //Pivot ist das gesuchte
// elseif (i<k)
// then return RANDOMIZED-SELECT(A,p,q-1,i)
// else return RANDOMIZED-SELECT(A,q+1,r,i-k)
// -----------------------------------------------------------
if (p == r) return values[p];
if (p == r) return a[p];
int q = randomizedPartition(values, p, r); // Pivot Element A[q]
//int q = randomizedPartition2(values, p, r); // Pivot Element A[q]
//int q = randomizedPartition3(values, p, r); // Pivot Element A[q]
int q = randomizedPartition(a, p, r); // Pivot Element A[q]
int k = q - p + 1; // Anzahl Elemente A[p..q]
if (i == k) return values[q]; // Pivot ist das gesuchte
if (i == k) return a[q]; // Pivot ist das gesuchte
else if (i < k)
return randomizedSelect(values, p, q - 1, i);
else return randomizedSelect(values, q + 1, r, i - k);
#ifdef PARTITION_TYPE_LOMUTO
return randomizedSelect(a, p, q - 1, i);
#elif defined PARTITION_TYPE_HOARE
return randomizedSelect(a, p, q, i);
#endif
else return randomizedSelect(a, q + 1, r, i - k);
}
uint32_t getRandomizedSelectMedian(std::vector<uint32_t> values, int p, int r, int i)
uint32_t getRandomizedSelectMedian(std::vector<uint32_t> a, int p, int r, int i)
{
return randomizedSelect(values, p, r, i);
return randomizedSelect(a, p, r, i);
}

View File

@ -1,4 +1,5 @@
#pragma once
#include <vector>
// custom swap function for just pointer swapping (check difference)
void swap(uint32_t* a, uint32_t* b)
@ -20,4 +21,55 @@ int compare(const void* a, const void* b)
if (arg1 < arg2) return -1;
if (arg1 > arg2) return 1;
return 0;
}
}
#define PARTITION_TYPE_LOMUTO
//#define PARTITION_TYPE_HOARE
#ifdef PARTITION_TYPE_LOMUTO
// Lomuto Partitioning
int partition(std::vector<uint32_t>& a, int p, int r)
{
uint32_t pivotValue = a[r];
/*int i = p - 1;
for (int j = p; j < r; j++)
{
if (a[j] <= pivotValue)
{
i++;
swap(&a[i], &a[j]);
}
}
swap(&a[i + 1], &a[r]);
return (i + 1);*/
int i = p;
for (int j = p; j < r; j++)
{
if (a[j] <= pivotValue)
{
swap(&a[i], &a[j]);
i++;
}
}
swap(&a[i], &a[r]);
return i;
}
#elif defined PARTITION_TYPE_HOARE
// Hoare Partitioning
int partition(std::vector<uint32_t>& a, int p, int r)
{
uint32_t pivotValue = a[p];
int i = p - 1;
int j = r + 1;
while (true)
{
do { i++; } while (a[i] < pivotValue);
do { j--; } while (a[j] > pivotValue);
if (i >= j) return j;
swap(&a[i], &a[j]);
}
}
#endif