/mergesort.hpp
https://bitbucket.org/mild1/sorting · C++ Header · 170 lines · 156 code · 14 blank · 0 comment · 47 complexity · 382d3625152af3d22ecf0a035dffbd1f MD5 · raw file
- #define USE_PREFIX//prefix increment faster than postfix even for size_t
- template <typename T> inline void smerge(const T* src, T* dst, size_t middle, size_t right)
- {
- size_t i = 0;
- size_t j = middle;
- size_t k = 0;
- #ifdef USE_PREFIX
- while(i < middle && j < right)
- {
- if(src[i] < src[j])
- {
- dst[k] = src[i];
- ++i;
- }
- else
- {
- dst[k] = src[j];
- ++j;
- }
- ++k;
- }
- #else
- while(i < middle && j < right)
- {
- if(src[i] < src[j])
- dst[k++] = src[i++];
- else
- dst[k++] = src[j++];
- }
- #endif
- if(i < middle)
- memcpy(dst + k, src + i, sizeof(T)*(middle - i));
- else if(j < right)
- memcpy(dst + k, src + j, sizeof(T)*(right - j));
- }
- template <typename Iter, typename DestinationIter> inline void merge(Iter& first, const Iter& end, DestinationIter& dst, size_t width)
- {
- size_t actualSize = end - first;
- if(actualSize < width)
- {
- for(;first != end; ++first, ++dst)
- *dst = *first;
- return;
- }
- Iter first2(first + width);
- const Iter end1(first2);
- const Iter end2(first2 + tMin(width, actualSize - width));
-
- while(first != end1 || first2 != end2)
- {
- if(first2 == end2)
- {
- *dst = *first;
- ++first;
- }
- else if(first == end1)
- {
- *dst = *first2;
- ++first2;
- }
- else if(*first2 < *first)
- {
- *dst = *first2;
- ++first2;
- }
- else
- {
- *dst = *first;
- ++first;
- }
- ++dst;
- }
- first = first2;
- }
- template <typename Vec> void mergesort_vector_memcpy(Vec& a)
- {
- typedef typename Vec::value_type T;
- const size_t size = a.size();
- if(size < 2)
- return;
- const size_t PresortSize = 2;
- T* src = &a[0];
- for (size_t i = 0; i < size - 1; i += 2)
- {
- size_t next = i + 1;
- if(src[next] < src[i])
- mswap(src[next], src[i]);
- }
- Vec buf(size);
- T* dst = &buf[0];
- for(size_t width = PresortSize; width < size; width <<= 1)
- {
- size_t doubleWidth = width << 1;
- for(size_t i = 0; i < size; i += doubleWidth)
- smerge(src + i, dst + i, tMin(width, size - i), tMin(doubleWidth, size - i));
- std::swap(src, dst);
- }
- if(dst == &a[0])
- memcpy(&a[0], &buf[0], size*sizeof(T));
- }
- template <typename Iter> void mergesort(const Iter& begin, const Iter& end)
- {
- const size_t size = end - begin;
- if(size < 2)
- return;
- typedef typename std::iterator_traits<Iter>::value_type T;
- const size_t PresortSize = 2;
- Iter last = end - 1;
- for (Iter i = begin; i < last; i += 2)
- {
- Iter next = i + 1;
- if(*next < *i)
- mswap(*next, *i);
- }
- std::vector<T> buf(size);
- T* b2 = &buf[0];
- T* e2 = b2 + buf.size();
- size_t iterationsCounter = 0;
- for(size_t width = PresortSize; width < size; width <<= 1, ++iterationsCounter)
- {
- if(iterationsCounter%2)
- {
- Iter dst(begin);
- T* first = b2;
- while (first != e2)
- merge<T*, Iter>(first, e2, dst, width);
- }
- else
- {
- Iter first(begin);
- T* dst = b2;
- while (first != end)
- merge<Iter, T*>(first, end, dst, width);
- }
- }
- if(iterationsCounter%2)
- {
- typename std::vector<T>::iterator j = buf.begin();
- for(Iter i = begin; i != end; ++i, ++j)
- *i = *j;
- }
- }
- template <typename Container> void mergesort_through_vec(Container& l)
- {
- size_t size = l.size();
- if(size < 2)
- return;
- typedef typename Container::value_type T;
- std::vector<T> buf(size);
- size_t i = 0;
- for(typename Container::const_iterator it = l.begin(), e = l.end(); it != e; ++it, ++i)
- buf[i] = *it;
- mergesort(&buf[0], &buf[0] + size);
- i = 0;
- for(typename Container::iterator it = l.begin(), e = l.end(); it != e; ++it, ++i)
- *it = buf[i];
- }