diff --git a/MedianOfMedians.h b/MedianOfMedians.h index 2255f92..66bcbd6 100644 --- a/MedianOfMedians.h +++ b/MedianOfMedians.h @@ -1,6 +1,9 @@ #pragma once // https://en.wikipedia.org/wiki/Median_of_medians +// 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) { size_t median; size_t size = values.size(); @@ -56,4 +59,93 @@ size_t getMedianOfMedians(const std::vector values, size_t k) { return getMedianOfMedians(L2, k - ((int)L1.size()) - 1); } return m; -} \ No newline at end of file +} + +// 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. +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. +int partition(size_t arr[], int l, int r, int x) +{ + // Search for x in arr[l..r] and move it to end + int i; + for (i = l; i < r; i++) + if (arr[i] == x) + break; + swap(&arr[i], &arr[r]); + + // Standard partition algorithm + i = l; + for (int j = l; j <= r - 1; j++) + { + if (arr[j] <= x) + { + swap(&arr[i], &arr[j]); + i++; + } + } + swap(&arr[i], &arr[r]); + return i; +} + +// Returns k'th smallest element in arr[l..r] in worst case +// linear time. ASSUMPTION: ALL ELEMENTS IN ARR[] ARE DISTINCT +//int getMedianOfMedians(int arr[], int l, int r, int k) +size_t getMedianOfMedians(size_t* arr, int l, int r, int k) +{ + // If k is smaller than number of elements in array + if (k > 0 && k <= r - l + 1) + { + int n = r - l + 1; // Number of elements in arr[l..r] + + // Divide arr[] in groups of size 5, calculate median + // of every group and store it in median[] array. + // There will be floor((n + 4) / 5) groups; + //int median[(n + 4) / 5]; // non VS compliant! + size_t* median = new size_t[(n + 4) / 5]; + int i = 0; + for (i = 0; i < n / 5; i++) + median[i] = findMedian(arr + l + i * 5, 5); + if (i * 5 < n) //For last group with less than 5 elements + { + median[i] = findMedian(arr + l + i * 5, n % 5); + i++; + } + + // Find median of all medians using recursive call. + // If median[] has only one element, then no need + // of recursive call + int medOfMed = (i == 1) ? median[i - 1] : + getMedianOfMedians(median, 0, i - 1, i / 2); + + // Partition the array around a random element and + // get position of pivot element in sorted array + int pos = partition(arr, l, r, medOfMed); + + // If position is same as k + if (pos - l == k - 1) + return arr[pos]; + if (pos - l > k - 1) // If position is more, recur for left + return getMedianOfMedians(arr, l, pos - 1, k); + + // Else recur for right subarray + return getMedianOfMedians(arr, pos + 1, r, k - pos + l - 1); + } + + // If k is more than number of elements in array + return SIZE_MAX; +} diff --git a/main.cpp b/main.cpp index f0659f2..d052da8 100644 --- a/main.cpp +++ b/main.cpp @@ -69,10 +69,16 @@ int main(int argc, char** argv) { std::cout << "randomized select: " << randomizedSelect(numbers, 0, numbers.size() - 1, idxMed) << std::endl; Timing::getInstance()->stopRecord("randomized select"); - // ein weiterer Median - Algorithmus aus der Literatur - Timing::getInstance()->startRecord("median of medians"); - std::cout << "median of medians: " << getMedianOfMedians(numbers, idxMed) << std::endl; - Timing::getInstance()->stopRecord("median of medians"); + // ein weiterer Median - Algorithmus aus der Literatur - implemented with std::vector + Timing::getInstance()->startRecord("vector median of medians"); + std::cout << "vector median of medians: " << getMedianOfMedians(numbers, idxMed) << std::endl; + Timing::getInstance()->stopRecord("vector median of medians"); + + // ein weiterer Median - Algorithmus aus der Literatur - realized with array + std::copy(numbers.begin(), numbers.end(), array); + Timing::getInstance()->startRecord("array median of medians"); + std::cout << "array median of medians: " << getMedianOfMedians(array, 0, numbers.size() - 1, idxMed) << std::endl; + Timing::getInstance()->stopRecord("array median of medians"); // noch ein ein weiterer Median - Algorithmus weil wir so cool sind Timing::getInstance()->startRecord("wirth");