added implementation for median of medians and randomized select

This commit is contained in:
incredibleLeitman 2020-10-06 16:28:09 +02:00
parent 90bb76cb3c
commit 1883659921
2 changed files with 89 additions and 2 deletions

View File

@ -1,3 +1,59 @@
#pragma once #pragma once
// https://en.wikipedia.org/wiki/Median_of_medians // https://en.wikipedia.org/wiki/Median_of_medians
int findMedian(std::vector<size_t> values) {
size_t median;
size_t size = values.size();
median = values[(size / 2)];
return median;
}
int findMedianOfMedians(std::vector<std::vector<size_t> > values) {
std::vector<size_t> medians;
for (size_t i = 0; i < values.size(); i++) {
size_t m = findMedian(values[i]);
medians.push_back(m);
}
return findMedian(medians);
}
size_t getMedianOfMedians(const std::vector<size_t> values, size_t k) {
// Divide the list into n/5 lists of 5 elements each
std::vector<std::vector<size_t> > vec2D;
size_t count = 0;
while (count != values.size()) {
size_t countRow = 0;
std::vector<size_t> row;
while ((countRow < 5) && (count < values.size())) {
row.push_back(values[count]);
count++;
countRow++;
}
vec2D.push_back(row);
}
// Calculating a new pivot for making splits
size_t m = findMedianOfMedians(vec2D);
// Partition the list into unique elements larger than 'm' (call this sublist L1) and those smaller them 'm' (call this sublist L2)
std::vector<size_t> 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) {
L1.push_back(vec2D[i][j]);
}
else if (vec2D[i][j] < m) {
L2.push_back(vec2D[i][j]);
}
}
}
if (k <= L1.size()) {
return getMedianOfMedians(L1, k);
}
else if (k > (L1.size() + 1)) {
return getMedianOfMedians(L2, k - ((int)L1.size()) - 1);
}
return m;
}

View File

@ -1,6 +1,9 @@
#pragma once #pragma once
#include <vector>
/* /*
// Pseudo code Alux Nimmervoll, Algo vo3
// Anmerkung: code funktioniert! // Anmerkung: code funktioniert!
RANDOMIZED-SELECT(A,p,r,i) RANDOMIZED-SELECT(A,p,r,i)
@ -11,4 +14,32 @@ RANDOMIZED-SELECT(A,p,r,i)
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)
*/ */
size_t randomizedPartition(std::vector<size_t>& 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];
i = p - 1;
for (size_t j = p; j < r; j++) {
if (values[j] <= pivotValue) {
i++;
std::swap(values[i], values[j]);
}
}
std::swap(values[i + 1], values[r]);
return i + 1;
}
size_t randomizedSelect(std::vector<size_t> values, size_t p, size_t r, size_t i)
{
if (p == r) return values[p];
size_t q = randomizedPartition(values, p, r); // Pivot Element A[q]
size_t k = q - p + 1; // Anzahl Elemente A[p..q]
if (i == k) return values[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);
}