Skip to content

Instantly share code, notes, and snippets.

@PanagiotisPtr
Last active December 31, 2018 19:31
Show Gist options
  • Save PanagiotisPtr/4510a094be1e9872be9533dcc504f23c to your computer and use it in GitHub Desktop.
Save PanagiotisPtr/4510a094be1e9872be9533dcc504f23c to your computer and use it in GitHub Desktop.
parallel and serialized versions of mergesort in C++
#ifndef SORT_H
#define SORT_H
#include <algorithm>
#include <list>
#include <iterator>
#include <future>
#include <iostream>
namespace Palgos {
static const size_t CHUCK_SIZE = 100000;
class Sort {
public:
template<
typename RandomIt,
typename Compare = std::less<typename std::iterator_traits<RandomIt>::value_type>
>
static void parallel_quick_sort(RandomIt first, RandomIt last, Compare comp = {}){
if(std::distance(first, last) <= CHUCK_SIZE){
quick_sort(first, last, comp);
return;
}
RandomIt pivot = partition(first, last, comp);
std::future<void> left(
std::async(&parallel_quick_sort<RandomIt, Compare>, first, pivot, comp)
);
pivot++;
parallel_quick_sort(pivot, last, comp);
left.get();
}
template<
typename RandomIt,
typename Compare = std::less<typename std::iterator_traits<RandomIt>::value_type>
>
static void quick_sort(RandomIt first, RandomIt last, Compare comp = {}){
typedef typename std::iterator_traits<RandomIt>::value_type value_type;
if(distance(first, last) <= 1)
return;
// partition
RandomIt pivot = partition(first, last, comp);
quick_sort(first, pivot, comp);
pivot++;
quick_sort(pivot, last, comp);
}
template<
typename RandomIt,
typename Compare = std::less<typename std::iterator_traits<RandomIt>::value_type>
>
static void parallel_merge_sort(RandomIt first, RandomIt last, Compare comp = {}){
if(std::distance(first, last) <= CHUCK_SIZE){
merge_sort(first, last, comp);
return;
}
RandomIt mid = first;
std::advance(mid, std::distance(first, last)/2);
std::future<void> left(std::async(&parallel_merge_sort<RandomIt, Compare>, first, mid, comp));
parallel_merge_sort(mid, last, comp);
left.get();
merge(first, mid, last, comp);
}
template<
typename RandomIt,
typename Compare = std::less<typename std::iterator_traits<RandomIt>::value_type>
>
static void merge_sort(RandomIt first, RandomIt last, Compare comp = {}){
if(std::distance(first, last) <= 1)
return;
RandomIt mid = first;
std::advance(mid, std::distance(first, last)/2);
merge_sort(first, mid, comp);
merge_sort(mid, last, comp);
merge(first, mid, last, comp);
}
private:
template<
typename RandomIt,
typename Compare = std::less<typename std::iterator_traits<RandomIt>::value_type>
>
static RandomIt partition(RandomIt first, RandomIt last, Compare comp = {}){
RandomIt front = first+1;
RandomIt back = first+1;
for(front; front != last; front++){
if(comp(*front, *first)){
std::swap(*back, *front);
back++;
}
}
back--;
std::swap(*first, *back);
return back;
}
template<
typename RandomIt,
typename Compare = std::less<typename std::iterator_traits<RandomIt>::value_type>,
typename Container = std::list<typename std::iterator_traits<RandomIt>::value_type>
>
static void merge(RandomIt first, RandomIt mid, RandomIt last, Compare comp = {}){
typedef typename std::iterator_traits<RandomIt>::value_type value_type;
RandomIt i = first;
RandomIt j = mid;
Container res;
std::back_insert_iterator<Container> it(res);
while(i != mid && j != last){
if(comp(*i, *j))
*it++ = *i++;
else
*it++ = *j++;
}
while(i != mid)
*it++ = *i++;
while(j != last)
*it++ = *j++;
std::copy(std::begin(res), std::end(res), first);
}
};
}
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment