Merge branch 'main' of https://github.com/kb173/median-comparison into main
This commit is contained in:
commit
be69fb41be
3
.gitignore
vendored
3
.gitignore
vendored
@ -34,6 +34,8 @@
|
||||
# visual studio build folder
|
||||
Debug/*
|
||||
Release/*
|
||||
x64/Debug/*
|
||||
x64/Release/*
|
||||
|
||||
# visual studio project files
|
||||
.vs/*
|
||||
@ -41,3 +43,4 @@ median-comparison.sln
|
||||
median-comparison.vcxproj
|
||||
median-comparison.vcxproj.filters
|
||||
median-comparison.vcxproj.user
|
||||
enc_temp_folder/*
|
||||
|
@ -4,32 +4,29 @@
|
||||
// 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<size_t> values)
|
||||
uint32_t findMedian(std::vector<uint32_t> values)
|
||||
{
|
||||
size_t median;
|
||||
size_t size = values.size();
|
||||
median = values[(size / 2)];
|
||||
return median;
|
||||
return values[(values.size() / 2)];
|
||||
}
|
||||
|
||||
int findMedianOfMedians(std::vector<std::vector<size_t> > values)
|
||||
uint32_t findMedianOfMedians(std::vector<std::vector<uint32_t> > values)
|
||||
{
|
||||
std::vector<size_t> medians;
|
||||
std::vector<uint32_t> medians;
|
||||
for (size_t i = 0; i < values.size(); i++) {
|
||||
size_t m = findMedian(values[i]);
|
||||
uint32_t m = findMedian(values[i]);
|
||||
medians.push_back(m);
|
||||
}
|
||||
return findMedian(medians);
|
||||
}
|
||||
|
||||
size_t getMedianOfMedians(const std::vector<size_t> values, size_t k)
|
||||
uint32_t getMedianOfMedians(const std::vector<uint32_t> values, uint32_t k)
|
||||
{
|
||||
// Divide the list into n/5 lists of 5 elements each
|
||||
std::vector<std::vector<size_t> > vec2D;
|
||||
std::vector<std::vector<uint32_t> > vec2D;
|
||||
size_t count = 0;
|
||||
while (count != values.size()) {
|
||||
size_t countRow = 0;
|
||||
std::vector<size_t> row;
|
||||
std::vector<uint32_t> row;
|
||||
while ((countRow < 5) && (count < values.size()))
|
||||
{
|
||||
row.push_back(values[count]);
|
||||
@ -40,10 +37,10 @@ size_t getMedianOfMedians(const std::vector<size_t> values, size_t k)
|
||||
}
|
||||
|
||||
// Calculating a new pivot for making splits
|
||||
size_t m = findMedianOfMedians(vec2D);
|
||||
uint32_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;
|
||||
std::vector<uint32_t> L1, L2;
|
||||
|
||||
for (size_t i = 0; i < vec2D.size(); i++)
|
||||
{
|
||||
@ -73,19 +70,19 @@ size_t getMedianOfMedians(const std::vector<size_t> values, size_t k)
|
||||
|
||||
// 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)
|
||||
uint32_t findMedian(uint32_t arr[], int n)
|
||||
{
|
||||
std::sort(arr, arr + n); // Sort the array
|
||||
return arr[n / 2]; // Return middle element
|
||||
}
|
||||
|
||||
// searches for x in arr[l..r], and partitions the array around x
|
||||
int partition(size_t arr[], int l, int r, int x)
|
||||
int partition(uint32_t arr[], int l, int r, uint32_t pivotValue)
|
||||
{
|
||||
// Search for x in arr[l..r] and move it to end
|
||||
int i;
|
||||
for (i = l; i < r; i++)
|
||||
if (arr[i] == x)
|
||||
if (arr[i] == pivotValue)
|
||||
break;
|
||||
swap(&arr[i], &arr[r]);
|
||||
|
||||
@ -93,7 +90,7 @@ int partition(size_t arr[], int l, int r, int x)
|
||||
i = l;
|
||||
for (int j = l; j < r; j++)
|
||||
{
|
||||
if (arr[j] <= x)
|
||||
if (arr[j] <= pivotValue)
|
||||
{
|
||||
i++;
|
||||
swap(&arr[i], &arr[j]);
|
||||
@ -106,10 +103,7 @@ int partition(size_t arr[], int l, int r, int x)
|
||||
// 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)
|
||||
uint32_t getMedianOfMedians(uint32_t* arr, int l, int r, int k)
|
||||
{
|
||||
int n = r - l + 1; // Number of elements in arr[l..r]
|
||||
|
||||
@ -117,7 +111,7 @@ size_t getMedianOfMedians(size_t* arr, int l, int r, int k)
|
||||
// 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];
|
||||
uint32_t* median = new uint32_t[(n + 4) / 5];
|
||||
int i = 0;
|
||||
for (i = 0; i < n / 5; i++)
|
||||
median[i] = findMedian(arr + l + i * 5, 5);
|
||||
@ -128,25 +122,15 @@ size_t getMedianOfMedians(size_t* arr, int l, int r, int k)
|
||||
}
|
||||
|
||||
// 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);
|
||||
// If median[] has only one element, then no need for recursive call
|
||||
uint32_t medOfMed = (i == 1) ? median[0] : 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
|
||||
if (pos - l == k - 1) return arr[pos];
|
||||
else if (pos - l > k - 1)
|
||||
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;
|
||||
else return getMedianOfMedians(arr, pos + 1, r, k - pos + l - 1);
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
size_t pivotPartition(std::vector<size_t>& values, size_t left, size_t right) {
|
||||
size_t pivotIndex = left + (right - left) / 2;
|
||||
size_t pivotValue = values[pivotIndex];
|
||||
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) {
|
||||
@ -15,7 +15,7 @@ size_t pivotPartition(std::vector<size_t>& values, size_t left, size_t right) {
|
||||
j--;
|
||||
}
|
||||
if (i <= j) {
|
||||
std::swap(values[i], values[j]);
|
||||
swap(&values[i], &values[j]);
|
||||
i++;
|
||||
j--;
|
||||
}
|
||||
@ -23,16 +23,16 @@ size_t pivotPartition(std::vector<size_t>& values, size_t left, size_t right) {
|
||||
return i;
|
||||
}
|
||||
|
||||
void quicksort(std::vector<size_t>& values, size_t left, size_t right)
|
||||
void quicksort(std::vector<uint32_t>& values, uint32_t left, uint32_t right)
|
||||
{
|
||||
if (left < right) {
|
||||
size_t pivotIndex = pivotPartition(values, left, right);
|
||||
uint32_t pivotIndex = pivotPartition(values, left, right);
|
||||
quicksort(values, left, pivotIndex - 1);
|
||||
quicksort(values, pivotIndex, right);
|
||||
}
|
||||
}
|
||||
|
||||
size_t getQuicksortMedian(std::vector<size_t> values, size_t i)
|
||||
uint32_t getQuicksortMedian(std::vector<uint32_t> values, uint32_t i)
|
||||
{
|
||||
//std::qsort(numbers); // only takes array param -> custom implementation with vector
|
||||
quicksort(values, 0, values.size() - 1);
|
||||
|
@ -3,12 +3,12 @@
|
||||
#include <vector>
|
||||
|
||||
// Lomuto Partitioning
|
||||
int randomizedPartition(std::vector<size_t>& values, int p, int r)
|
||||
int randomizedPartition(std::vector<uint32_t>& values, int p, int r)
|
||||
{
|
||||
int i = p + rand() % (r - p); // generate a random number in {p, ..., r}
|
||||
swap(&values[i], &values[r]);
|
||||
|
||||
int pivotValue = values[r];
|
||||
uint32_t pivotValue = values[r];
|
||||
i = p - 1;
|
||||
for (int j = p; j < r; j++)
|
||||
{
|
||||
@ -24,12 +24,12 @@ int randomizedPartition(std::vector<size_t>& values, int p, int r)
|
||||
|
||||
// TODO: Hoare Partitioning
|
||||
// https://www.geeksforgeeks.org/quicksort-using-random-pivoting/
|
||||
int randomizedPartition2(std::vector<size_t>& values, int low, int high)
|
||||
int randomizedPartition2(std::vector<uint32_t>& values, int low, int high)
|
||||
{
|
||||
int i = low + rand() % (high - low); // generate a random number in {p, ..., r}
|
||||
std::swap(values[i], values[low]);
|
||||
swap(&values[i], &values[low]);
|
||||
|
||||
int pivot = values[low];
|
||||
uint32_t pivotValue = values[low];
|
||||
i = low - 1;
|
||||
int j = high + 1;
|
||||
while (true) {
|
||||
@ -37,42 +37,42 @@ int randomizedPartition2(std::vector<size_t>& values, int low, int high)
|
||||
// or equal to pivot
|
||||
do {
|
||||
i++;
|
||||
} while (values[i] < pivot);
|
||||
} while (values[i] < pivotValue);
|
||||
|
||||
// Find rightmost element smaller than
|
||||
// or equal to pivot
|
||||
do {
|
||||
j--;
|
||||
} while (values[j] > pivot);
|
||||
} while (values[j] > pivotValue);
|
||||
|
||||
// If two pointers met
|
||||
if (i >= j)
|
||||
return j;
|
||||
|
||||
std::swap(values[i], values[j]);
|
||||
swap(&values[i], &values[j]);
|
||||
}
|
||||
}
|
||||
|
||||
int randomizedPartition3(std::vector<size_t>& values, int l, int r)
|
||||
int randomizedPartition3(std::vector<uint32_t>& values, int l, int r)
|
||||
{
|
||||
int n = r - l + 1;
|
||||
int pivot = rand() % n;
|
||||
std::swap(values[l + pivot], values[r]);
|
||||
int i = rand() % (r - l + 1);
|
||||
swap(&values[l + i], &values[r]);
|
||||
|
||||
int x = values[r], i = l;
|
||||
uint32_t pivotValue = values[r];
|
||||
i = l;
|
||||
for (int j = l; j <= r - 1; j++)
|
||||
{
|
||||
if (values[j] <= x)
|
||||
if (values[j] <= pivotValue)
|
||||
{
|
||||
std::swap(values[i], values[j]);
|
||||
swap(&values[i], &values[j]);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
std::swap(values[i], values[r]);
|
||||
swap(&values[i], &values[r]);
|
||||
return i;
|
||||
}
|
||||
|
||||
int randomizedSelect(std::vector<size_t> values, int p, int r, int i)
|
||||
uint32_t randomizedSelect(std::vector<uint32_t>& values, int p, int r, int i)
|
||||
{
|
||||
/*
|
||||
// Partition the array around a random element and
|
||||
@ -104,12 +104,17 @@ int randomizedSelect(std::vector<size_t> values, int p, int r, int i)
|
||||
|
||||
if (p == r) return values[p];
|
||||
|
||||
//int q = randomizedPartition(values, p, r); // Pivot Element A[q]
|
||||
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 = randomizedPartition3(values, 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
|
||||
else if (i < k)
|
||||
return randomizedSelect(values, p, q - 1, i);
|
||||
else return randomizedSelect(values, q + 1, r, i - k);
|
||||
}
|
||||
|
||||
uint32_t getRandomizedSelectMedian(std::vector<uint32_t> values, int p, int r, int i)
|
||||
{
|
||||
return randomizedSelect(values, p, r, i);
|
||||
}
|
18
common.h
18
common.h
@ -1,9 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
// custom swap function
|
||||
void swap(size_t* a, size_t* b)
|
||||
void swap(uint32_t* a, uint32_t* b)
|
||||
{
|
||||
size_t temp = *a;
|
||||
uint32_t temp = *a;
|
||||
*a = *b;
|
||||
*b = temp;
|
||||
}
|
||||
|
||||
// comparator function used by qsort
|
||||
int compare(const void* a, const void* b)
|
||||
{
|
||||
// TODO: check why this does not return the same results???
|
||||
//return (*(uint32_t*)a - *(uint32_t*)b);
|
||||
//return (int)(*(int*)a - *(int*)b);
|
||||
//return (int)(*(const int*)a - *(const int*)b);
|
||||
uint32_t arg1 = *static_cast<const uint32_t*>(a);
|
||||
uint32_t arg2 = *static_cast<const uint32_t*>(b);
|
||||
if (arg1 < arg2) return -1;
|
||||
if (arg1 > arg2) return 1;
|
||||
return 0;
|
||||
}
|
@ -5,27 +5,27 @@
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
|
||||
std::vector<size_t> readFromFile(const char* filePath)
|
||||
std::vector<uint32_t > readFromFile(const char* filePath)
|
||||
{
|
||||
std::vector<size_t> numbers;
|
||||
std::vector<uint32_t > numbers;
|
||||
std::cout << "read file: " << filePath << "..." << std::endl;
|
||||
std::ifstream in(filePath);
|
||||
if (in.is_open())
|
||||
{
|
||||
std::string line;
|
||||
std::getline(in, line);
|
||||
size_t count = std::stoi(line);
|
||||
int count = std::stoi(line);
|
||||
|
||||
std::cout << "total: " << count << " elems" << std::endl;
|
||||
|
||||
size_t idx = 0;
|
||||
int idx = 0;
|
||||
while (in.good() && idx < count) {
|
||||
std::getline(in, line);
|
||||
//long val = std::stol(line);
|
||||
//std::cout << "as long: " << val << std::endl;
|
||||
unsigned long ulval = std::stoul(line);
|
||||
//std::cout << "as unsigned long: " << ulval << std::endl;
|
||||
numbers.push_back((size_t)ulval); // auto cast to uint
|
||||
numbers.push_back((uint32_t)ulval); // auto cast to uint
|
||||
idx++;
|
||||
}
|
||||
}
|
||||
|
26
main.cpp
26
main.cpp
@ -16,25 +16,11 @@
|
||||
// - fix randomized select
|
||||
// - use custom swap for just pointer swapping (check difference)
|
||||
|
||||
// comparator function used by qsort
|
||||
int compare(const void* a, const void* b)
|
||||
{
|
||||
// TODO: check why this does not return the same results???
|
||||
//return (*(size_t*)a - *(size_t*)b);
|
||||
//return (int)(*(int*)a - *(int*)b);
|
||||
//return (int)(*(const int*)a - *(const int*)b);
|
||||
size_t arg1 = *static_cast<const size_t*>(a);
|
||||
size_t arg2 = *static_cast<const size_t*>(b);
|
||||
if (arg1 < arg2) return -1;
|
||||
if (arg1 > arg2) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
// read test values from input file
|
||||
Timing::getInstance()->startRecord("init");
|
||||
std::vector<size_t> numbers = readFromFile("testdata");
|
||||
std::vector<uint32_t > numbers = readFromFile("testdata");
|
||||
std::cout << "just read " << numbers.size() << " values" << std::endl;
|
||||
Timing::getInstance()->stopRecord("init");
|
||||
|
||||
@ -46,7 +32,7 @@ int main(int argc, char** argv)
|
||||
return 1;
|
||||
}
|
||||
|
||||
size_t idxMed = (numbers.size() - 1) / 2;
|
||||
uint32_t idxMed = (numbers.size() - 1) / 2;
|
||||
std::cout << "idx median = " << idxMed << " of " << numbers.size() << std::endl;
|
||||
|
||||
// vollst<73>ndige Sortierung mit Quicksort und Ausgabe des mittleren Elements
|
||||
@ -61,7 +47,7 @@ int main(int argc, char** argv)
|
||||
//size_t* array[numbers.size()]; // invalid c++ -> non-constant expression!
|
||||
//std::copy(numbers.begin(), numbers.end(), array);
|
||||
//size_t* tmp = numbers.data(); // c++11 returns pointer to first elem
|
||||
size_t* array = new size_t[999999]; // create and fill new array
|
||||
uint32_t* array = new uint32_t[999999]; // create and fill new array
|
||||
std::copy(numbers.begin(), numbers.end(), array);
|
||||
Timing::getInstance()->startRecord("array quicksort");
|
||||
std::qsort(array, numbers.size(), sizeof(size_t), compare);
|
||||
@ -77,7 +63,7 @@ int main(int argc, char** argv)
|
||||
|
||||
// vorgestellter Randomzized - Select rekursiv implementiert
|
||||
Timing::getInstance()->startRecord("randomized select");
|
||||
std::cout << "randomized select: " << randomizedSelect(numbers, 0, numbers.size() - 1, idxMed + 1) << std::endl;
|
||||
std::cout << "randomized select: " << getRandomizedSelectMedian(numbers, 0, numbers.size() - 1, idxMed + 1) << std::endl;
|
||||
Timing::getInstance()->stopRecord("randomized select");
|
||||
|
||||
// ein weiterer Median - Algorithmus aus der Literatur - implemented with std::vector
|
||||
@ -86,10 +72,10 @@ int main(int argc, char** argv)
|
||||
Timing::getInstance()->stopRecord("vector median of medians");
|
||||
|
||||
// ein weiterer Median - Algorithmus aus der Literatur - realized with array
|
||||
std::copy(numbers.begin(), numbers.end(), 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 + 1) << std::endl;
|
||||
Timing::getInstance()->stopRecord("array median of medians");
|
||||
Timing::getInstance()->stopRecord("array median of medians");*/
|
||||
|
||||
// noch ein ein weiterer Median - Algorithmus weil wir so cool sind
|
||||
std::vector<size_t> numbers_wirth(numbers); // Copy because wirth works in-place
|
||||
|
Loading…
x
Reference in New Issue
Block a user