diff --git a/MedianOfMedians.h b/MedianOfMedians.h index 66bcbd6..7f8da59 100644 --- a/MedianOfMedians.h +++ b/MedianOfMedians.h @@ -4,14 +4,16 @@ // https://oneraynyday.github.io/algorithms/2016/06/17/Median-Of-Medians/ // https://www.geeksforgeeks.org/kth-smallestlargest-element-unsorted-array-set-3-worst-case-linear-time/ -int findMedian(std::vector values) { +int findMedian(std::vector values) +{ size_t median; size_t size = values.size(); median = values[(size / 2)]; return median; } -int findMedianOfMedians(std::vector > values) { +int findMedianOfMedians(std::vector > values) +{ std::vector medians; for (size_t i = 0; i < values.size(); i++) { size_t m = findMedian(values[i]); @@ -20,14 +22,16 @@ int findMedianOfMedians(std::vector > values) { return findMedian(medians); } -size_t getMedianOfMedians(const std::vector values, size_t k) { +size_t getMedianOfMedians(const std::vector values, size_t k) +{ // Divide the list into n/5 lists of 5 elements each std::vector > vec2D; size_t count = 0; while (count != values.size()) { size_t countRow = 0; std::vector row; - while ((countRow < 5) && (count < values.size())) { + while ((countRow < 5) && (count < values.size())) + { row.push_back(values[count]); count++; countRow++; @@ -41,44 +45,41 @@ size_t getMedianOfMedians(const std::vector values, size_t k) { // Partition the list into unique elements larger than 'm' (call this sublist L1) and those smaller them 'm' (call this sublist L2) std::vector L1, L2; - for (size_t i = 0; i < vec2D.size(); i++) { - for (size_t j = 0; j < vec2D[i].size(); j++) { - if (vec2D[i][j] > m) { + for (size_t i = 0; i < vec2D.size(); i++) + { + for (size_t j = 0; j < vec2D[i].size(); j++) + { + if (vec2D[i][j] > m) + { L1.push_back(vec2D[i][j]); } - else if (vec2D[i][j] < m) { + else if (vec2D[i][j] < m) + { L2.push_back(vec2D[i][j]); } } } - if (k <= L1.size()) { + if (k <= L1.size()) + { return getMedianOfMedians(L1, k); } - else if (k > (L1.size() + 1)) { + else if (k > (L1.size() + 1)) + { return getMedianOfMedians(L2, k - ((int)L1.size()) - 1); } return m; } -// custom swap function -void swap(size_t* a, size_t* b) -{ - size_t temp = *a; - *a = *b; - *b = temp; -} - -// A simple function to find median of arr[]. This is called -// only for an array of size 5 in this program. +// A simple function to find median of arr[]. +// This is called only for an array of size 5 in this program. int findMedian(size_t arr[], int n) { std::sort(arr, arr + n); // Sort the array return arr[n / 2]; // Return middle element } -// It searches for x in arr[l..r], and partitions the array -// around x. +// searches for x in arr[l..r], and partitions the array around x int partition(size_t arr[], int l, int r, int x) { // Search for x in arr[l..r] and move it to end @@ -90,12 +91,12 @@ int partition(size_t arr[], int l, int r, int x) // Standard partition algorithm i = l; - for (int j = l; j <= r - 1; j++) + for (int j = l; j < r; j++) { if (arr[j] <= x) { - swap(&arr[i], &arr[j]); i++; + swap(&arr[i], &arr[j]); } } swap(&arr[i], &arr[r]); diff --git a/MedianQuicksort.h b/MedianQuicksort.h index e743d19..93dc8d3 100644 --- a/MedianQuicksort.h +++ b/MedianQuicksort.h @@ -3,13 +3,15 @@ size_t pivotPartition(std::vector& values, size_t left, size_t right) { size_t pivotIndex = left + (right - left) / 2; size_t pivotValue = values[pivotIndex]; - size_t i = left; - size_t j = right; + int i = left; + int j = right; while (i <= j) { - while (values[i] < pivotValue) { + while (values[i] < pivotValue) + { i++; } - while (values[j] > pivotValue) { + while (values[j] > pivotValue) + { j--; } if (i <= j) { @@ -21,7 +23,8 @@ size_t pivotPartition(std::vector& values, size_t left, size_t right) { return i; } -void quicksort(std::vector& values, size_t left, size_t right) { +void quicksort(std::vector& values, size_t left, size_t right) +{ if (left < right) { size_t pivotIndex = pivotPartition(values, left, right); quicksort(values, left, pivotIndex - 1); @@ -29,7 +32,8 @@ void quicksort(std::vector& values, size_t left, size_t right) { } } -size_t getQuicksortMedian(std::vector values, size_t i) { +size_t getQuicksortMedian(std::vector values, size_t i) +{ //std::qsort(numbers); // only takes array param -> custom implementation with vector quicksort(values, 0, values.size() - 1); return values[i]; diff --git a/RandomizedSelect.h b/RandomizedSelect.h index b92c6d2..cbb0693 100644 --- a/RandomizedSelect.h +++ b/RandomizedSelect.h @@ -2,42 +2,112 @@ #include -/* -// Pseudo code Alux Nimmervoll, Algo vo3 -// Anmerkung: code funktioniert! +// Lomuto Partitioning +int randomizedPartition(std::vector& values, int p, int r) +{ + int i = p + rand() % (r - p); // generate a random number in {p, ..., r} + swap(&values[i], &values[r]); -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& values, size_t p, size_t r) { - size_t i = p + rand() % (r - p + 1); // generate a random number in {p, ..., r} - std::swap(values[i], values[r]); - - size_t pivotValue = values[r]; + int pivotValue = values[r]; i = p - 1; - for (size_t j = p; j < r; j++) { - if (values[j] <= pivotValue) { + for (int j = p; j < r; j++) + { + if (values[j] <= pivotValue) + { i++; - std::swap(values[i], values[j]); + swap(&values[i], &values[j]); } } - std::swap(values[i + 1], values[r]); - return i + 1; + swap(&values[i + 1], &values[r]); + return (i + 1); } -size_t randomizedSelect(std::vector values, size_t p, size_t r, size_t i) +// TODO: Hoare Partitioning +// https://www.geeksforgeeks.org/quicksort-using-random-pivoting/ +int randomizedPartition2(std::vector& values, int low, int high) { + int i = low + rand() % (high - low); // generate a random number in {p, ..., r} + std::swap(values[i], values[low]); + + int pivot = 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] < pivot); + + // Find rightmost element smaller than + // or equal to pivot + do { + j--; + } while (values[j] > pivot); + + // If two pointers met + if (i >= j) + return j; + + std::swap(values[i], values[j]); + } +} + +int randomizedPartition3(std::vector& values, int l, int r) +{ + int n = r - l + 1; + int pivot = rand() % n; + std::swap(values[l + pivot], values[r]); + + int x = values[r], i = l; + for (int j = l; j <= r - 1; j++) + { + if (values[j] <= x) + { + std::swap(values[i], values[j]); + i++; + } + } + std::swap(values[i], values[r]); + return i; +} + +int randomizedSelect(std::vector 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