PageRenderTime 37ms CodeModel.GetById 8ms app.highlight 26ms RepoModel.GetById 1ms app.codeStats 0ms

/mergesort.hpp

https://bitbucket.org/mild1/sorting
C++ Header | 170 lines | 156 code | 14 blank | 0 comment | 44 complexity | 382d3625152af3d22ecf0a035dffbd1f MD5 | raw file
  1#define USE_PREFIX//prefix increment faster than postfix even for size_t
  2template <typename T> inline void smerge(const T* src, T* dst, size_t middle, size_t right)
  3{
  4    size_t i = 0;
  5    size_t j = middle;
  6    size_t k = 0;
  7#ifdef USE_PREFIX
  8    while(i < middle && j < right)
  9    {
 10        if(src[i] < src[j])
 11        {
 12            dst[k] = src[i];
 13            ++i;
 14        }
 15        else
 16        {
 17            dst[k] = src[j];
 18            ++j;
 19        }
 20        ++k;
 21    }
 22#else
 23    while(i < middle && j < right)
 24    {
 25        if(src[i] < src[j])
 26            dst[k++] = src[i++];
 27        else
 28            dst[k++] = src[j++];
 29    }
 30#endif
 31    if(i < middle)
 32        memcpy(dst + k, src + i, sizeof(T)*(middle - i));
 33    else if(j < right)
 34        memcpy(dst + k, src + j, sizeof(T)*(right - j));
 35}
 36
 37template <typename Iter, typename DestinationIter> inline void merge(Iter& first, const Iter& end, DestinationIter& dst, size_t width)
 38{
 39    size_t actualSize = end - first;
 40    if(actualSize < width)
 41    {
 42        for(;first != end; ++first, ++dst)
 43            *dst = *first;
 44        return;
 45    }
 46    Iter first2(first + width);
 47    const Iter end1(first2);
 48    const Iter end2(first2 + tMin(width, actualSize - width));
 49    
 50    while(first != end1 || first2 != end2)
 51    {
 52        if(first2 == end2)
 53        {
 54            *dst = *first;
 55            ++first;
 56        }
 57        else if(first == end1)
 58        {
 59            *dst = *first2;
 60            ++first2;
 61        }
 62        else if(*first2 < *first)
 63        {
 64            *dst = *first2;
 65            ++first2;
 66        }
 67        else
 68        {
 69            *dst = *first;
 70            ++first;
 71        }
 72        ++dst;
 73    }
 74    first = first2;
 75}
 76
 77template <typename Vec> void mergesort_vector_memcpy(Vec& a)
 78{
 79    typedef typename Vec::value_type T;
 80
 81    const size_t size = a.size();
 82    if(size < 2)
 83        return;
 84    const size_t PresortSize = 2;
 85    T* src = &a[0];
 86    for (size_t i = 0; i < size - 1; i += 2)
 87    {
 88        size_t next = i + 1;
 89        if(src[next] < src[i])
 90            mswap(src[next], src[i]);
 91    }
 92
 93    Vec buf(size);
 94
 95    T* dst = &buf[0];
 96    for(size_t width = PresortSize; width < size; width <<= 1)
 97    {
 98        size_t doubleWidth = width << 1;
 99        for(size_t i = 0; i < size; i += doubleWidth)
100            smerge(src + i, dst + i, tMin(width, size - i), tMin(doubleWidth, size - i));
101        std::swap(src, dst);
102    }
103    if(dst == &a[0])
104        memcpy(&a[0], &buf[0], size*sizeof(T));
105}
106
107template <typename Iter> void mergesort(const Iter& begin, const Iter& end)
108{
109    const size_t size = end - begin;
110    if(size < 2)
111        return;
112
113    typedef typename std::iterator_traits<Iter>::value_type T;
114
115    const size_t PresortSize = 2;
116    Iter last = end - 1;
117    for (Iter i = begin; i < last; i += 2)
118    {
119        Iter next = i + 1;
120        if(*next < *i)
121            mswap(*next, *i);
122    }
123
124    std::vector<T> buf(size);
125
126    T* b2 = &buf[0];
127    T* e2 = b2 + buf.size();
128
129    size_t iterationsCounter = 0;
130    for(size_t width = PresortSize; width < size; width <<= 1, ++iterationsCounter)
131    {
132        if(iterationsCounter%2)
133        {
134            Iter dst(begin);
135            T* first = b2;
136            while (first != e2)
137                merge<T*, Iter>(first, e2, dst, width);
138        }
139        else
140        {
141            Iter first(begin);
142            T* dst = b2;
143            while (first != end)
144                merge<Iter, T*>(first, end, dst, width);
145        }
146    }
147
148    if(iterationsCounter%2)
149    {
150        typename std::vector<T>::iterator j = buf.begin();
151        for(Iter i = begin; i != end; ++i, ++j)
152            *i = *j;
153    }
154}
155
156template <typename Container> void mergesort_through_vec(Container& l)
157{
158    size_t size = l.size();
159    if(size < 2)
160        return;
161    typedef typename Container::value_type T;
162    std::vector<T> buf(size);
163    size_t i = 0;
164    for(typename Container::const_iterator it = l.begin(), e = l.end(); it != e; ++it, ++i)
165        buf[i] = *it;
166    mergesort(&buf[0], &buf[0] + size);
167    i = 0;
168    for(typename Container::iterator it = l.begin(), e = l.end(); it != e; ++it, ++i)
169        *it = buf[i];
170}