/mergesort.hpp
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}