19#ifndef Smoothsort_Included
20#define Smoothsort_Included
32template <
typename RandomIterator>
33void Smoothsort(RandomIterator begin, RandomIterator end);
42template <
typename RandomIterator,
typename Comparator>
43void Smoothsort(RandomIterator begin, RandomIterator end, Comparator comp);
46namespace smoothsort_detail {
51 const size_t kNumLeonardoNumbers = 46;
57 const size_t kLeonardoNumbers[kNumLeonardoNumbers] = {
58 1u, 1u, 3u, 5u, 9u, 15u, 25u, 41u, 67u, 109u, 177u, 287u, 465u, 753u,
59 1219u, 1973u, 3193u, 5167u, 8361u, 13529u, 21891u, 35421u, 57313u, 92735u,
60 150049u, 242785u, 392835u, 635621u, 1028457u, 1664079u, 2692537u,
61 4356617u, 7049155u, 11405773u, 18454929u, 29860703u, 48315633u, 78176337u,
62 126491971u, 204668309u, 331160281u, 535828591u, 866988873u, 1402817465u,
63 2269806339u, 3672623805u
72 std::bitset<kNumLeonardoNumbers> trees;
75 size_t smallestTreeSize;
85 template <
typename RandomIterator>
86 RandomIterator SecondChild(RandomIterator root) {
98 template <
typename RandomIterator>
99 RandomIterator FirstChild(RandomIterator root,
size_t size) {
103 return SecondChild(root) - kLeonardoNumbers[size - 2];
114 template <
typename RandomIterator,
typename Comparator>
115 RandomIterator LargerChild(RandomIterator root,
size_t size, Comparator comp) {
117 RandomIterator first = FirstChild(root, size);
118 RandomIterator second = SecondChild(root);
121 return comp(*first, *second)? second : first;
132 template <
typename RandomIterator,
typename Comparator>
133 void RebalanceSingleHeap(RandomIterator root,
size_t size, Comparator comp) {
139 RandomIterator first = FirstChild(root, size);
140 RandomIterator second = SecondChild(root);
143 RandomIterator largerChild;
145 if (comp(*first, *second)) {
146 largerChild = second;
147 childSize = size - 2;
150 childSize = size - 1;
154 if (!comp(*root, *largerChild))
158 std::iter_swap(root, largerChild);
174 template <
typename RandomIterator,
typename Comparator>
175 void LeonardoHeapRectify(RandomIterator begin, RandomIterator end,
176 HeapShape shape, Comparator comp) {
180 RandomIterator itr = end - 1;
193 lastHeapSize = shape.smallestTreeSize;
196 if (
size_t(std::distance(begin, itr)) == kLeonardoNumbers[lastHeapSize] - 1)
205 RandomIterator toCompare = itr;
210 if (shape.smallestTreeSize > 1) {
214 RandomIterator largeChild = LargerChild(itr, shape.smallestTreeSize,
218 if (comp(*toCompare, *largeChild))
219 toCompare = largeChild;
225 RandomIterator priorHeap = itr - kLeonardoNumbers[lastHeapSize];
231 if (!comp(*toCompare, *priorHeap))
235 std::iter_swap(itr, priorHeap);
244 ++shape.smallestTreeSize;
245 }
while (!shape.trees[0]);
249 RebalanceSingleHeap(itr, lastHeapSize, comp);
261 template <
typename RandomIterator,
typename Comparator>
262 void LeonardoHeapAdd(RandomIterator begin, RandomIterator end,
263 RandomIterator heapEnd,
264 HeapShape& shape, Comparator comp) {
280 if (!shape.trees[0]) {
281 shape.trees[0] =
true;
282 shape.smallestTreeSize = 1;
287 else if (shape.trees[1] && shape.trees[0]) {
294 shape.trees[0] =
true;
299 shape.smallestTreeSize += 2;
302 else if (shape.smallestTreeSize == 1) {
305 shape.smallestTreeSize = 0;
308 shape.trees[0] =
true;
316 shape.trees <<= shape.smallestTreeSize - 1;
317 shape.trees[0] =
true;
322 shape.smallestTreeSize = 1;
330 switch (shape.smallestTreeSize) {
335 if (end + 1 == heapEnd)
344 if (end + 1 == heapEnd || (end + 2 == heapEnd && !shape.trees[1]))
352 if (
size_t(std::distance(end + 1, heapEnd)) < kLeonardoNumbers[shape.smallestTreeSize - 1] + 1)
359 RebalanceSingleHeap(end, shape.smallestTreeSize, comp);
362 LeonardoHeapRectify(begin, end + 1, shape, comp);
374 template <
typename RandomIterator,
typename Comparator>
375 void LeonardoHeapRemove(RandomIterator begin, RandomIterator end,
376 HeapShape& shape, Comparator comp) {
387 if (shape.smallestTreeSize <= 1) {
391 ++shape.smallestTreeSize;
392 }
while (shape.trees.any() && !shape.trees[0]);
400 const size_t heapOrder = shape.smallestTreeSize;
401 shape.trees[0] =
false;
403 shape.trees[1] = shape.trees[0] =
true;
404 shape.smallestTreeSize -= 2;
411 RandomIterator leftHeap = FirstChild(end - 1, heapOrder);
412 RandomIterator rightHeap = SecondChild(end - 1);
418 HeapShape allButLast = shape;
419 ++allButLast.smallestTreeSize;
420 allButLast.trees >>= 1;
426 LeonardoHeapRectify(begin, leftHeap + 1, allButLast, comp);
427 LeonardoHeapRectify(begin, rightHeap + 1, shape, comp);
432template <
typename RandomIterator,
typename Comparator>
433void Smoothsort(RandomIterator begin, RandomIterator end, Comparator comp) {
435 if (begin == end || begin + 1 == end)
return;
439 shape.smallestTreeSize = 0;
442 for (RandomIterator itr = begin; itr != end; ++itr)
443 smoothsort_detail::LeonardoHeapAdd(begin, itr, end, shape, comp);
448 for (RandomIterator itr = end; itr != begin; --itr)
449 smoothsort_detail::LeonardoHeapRemove(begin, itr, shape, comp);
453template <
typename RandomIterator>
454void Smoothsort(RandomIterator begin, RandomIterator end) {
455 Smoothsort(begin, end,
456 std::less<
typename std::iterator_traits<RandomIterator>::value_type>());
Definition: SmoothSort.h:70