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 #pragma once
uint32_t pivotPartition(std::vector<uint32_t>& values, uint32_t left, uint32_t right) { int pivotPartition(std::vector<uint32_t>& a, int p, int r) {
uint32_t pivotIndex = left + (right - left) / 2;
uint32_t pivotValue = values[pivotIndex]; return partition(a, p, r);
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;
} }
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) { if (p < r) {
uint32_t pivotIndex = pivotPartition(values, left, right); int i = pivotPartition(a, p, r);
quicksort(values, left, pivotIndex - 1); #ifdef PARTITION_TYPE_LOMUTO
quicksort(values, pivotIndex, right); 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 //std::qsort(numbers); // only takes array param -> custom implementation with vector
quicksort(values, 0, values.size() - 1); quicksort(a, 0, a.size() - 1);
return values[i]; return a[i];
} }

View File

@ -1,120 +1,49 @@
#pragma once #pragma once
#include <vector> int randomizedPartition(std::vector<uint32_t>& a, int p, int r)
// Lomuto Partitioning
int randomizedPartition(std::vector<uint32_t>& values, int p, int r)
{ {
int i = p + rand() % (r - p); // generate a random number in {p, ..., r} // generate a random number in {p, ..., r} to swap
swap(&values[i], &values[r]); #ifdef PARTITION_TYPE_LOMUTO
int i = p + rand() % (r - p);
uint32_t pivotValue = values[r]; swap(&a[i], &a[r]);
i = p - 1; #elif defined PARTITION_TYPE_HOARE
for (int j = p; j < r; j++) int i = rand() % (r - p + 1);
{ swap(&a[p + i], &a[r]);
if (values[j] <= pivotValue) #endif
{ return partition(a, p, r);
i++;
swap(&values[i], &values[j]);
}
}
swap(&values[i + 1], &values[r]);
return (i + 1);
} }
// TODO: Hoare Partitioning uint32_t randomizedSelect(std::vector<uint32_t>& a, int p, int r, int i)
// https://www.geeksforgeeks.org/quicksort-using-random-pivoting/
int randomizedPartition2(std::vector<uint32_t>& values, int low, int high)
{ {
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 // Pseudo code Alux Nimmervoll, Algo vo3
// Anmerkung: code funktioniert! // Anmerkung: code funktioniert!
/* //
RANDOMIZED-SELECT(A,p,r,i) // RANDOMIZED-SELECT(A,p,r,i)
if (p==r) then return A[p] // if (p==r) then return A[p]
q=RANDOMIZED_PARTITION(A,p,r) //Pivot Element A[q] // q=RANDOMIZED_PARTITION(A,p,r) //Pivot Element A[q]
k=q-p+1 //Anzahl Elemente A[p..q] // k=q-p+1 //Anzahl Elemente A[p..q]
if (i==k) then return A[q] //Pivot ist das gesuchte // if (i==k) then return A[q] //Pivot ist das gesuchte
elseif (i<k) // elseif (i<k)
then return RANDOMIZED-SELECT(A,p,q-1,i) // then return RANDOMIZED-SELECT(A,p,q-1,i)
else return RANDOMIZED-SELECT(A,q+1,r,i-k) // 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 = randomizedPartition(a, 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 k = q - p + 1; // Anzahl Elemente A[p..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) else if (i < k)
return randomizedSelect(values, p, q - 1, i); #ifdef PARTITION_TYPE_LOMUTO
else return randomizedSelect(values, q + 1, r, i - k); 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 #pragma once
#include <vector>
// custom swap function for just pointer swapping (check difference) // custom swap function for just pointer swapping (check difference)
void swap(uint32_t* a, uint32_t* b) 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;
if (arg1 > arg2) return 1; if (arg1 > arg2) return 1;
return 0; 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