You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/Original-research.md
+2-2Lines changed: 2 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -14,7 +14,7 @@ Now, those observations/claims are there to be challenged: if you know a stable
14
14
15
15
### Vergesort
16
16
17
-
The vergesort is a new sorting algorithm which combines merge operations on almost sorted data, and falls back to another sorting algorithm when the data is not sorted enough. Somehow it can be considered as a cheap preprocessing step to take advantage of almost-sorted data when possible. Just like TimSort, it achieves linear time on some patterns, generally for almost sorted data, and should never be worse than O(n log n log log n) in the worst case - though no in-depth formal analysis has been performed.
17
+
Vergesort is a sorting algorithm which combines merge operations on almost sorted data, and falls back to another sorting algorithm when the data is not sorted enough. Somehow it can be considered as a cheap preprocessing step to take advantage of almost-sorted data when possible. Just like TimSort, it achieves linear time on some patterns, generally for almost sorted data, and should never be worse than O(n log n log log n) in the worst case - though no in-depth formal analysis has been performed.
18
18
19
19
Best Average Worst Memory Stable
20
20
n n log n n log n log log n n No
@@ -24,7 +24,7 @@ The two variations in space and time complexity depend on whether enough memory
24
24
25
25
While vergesort has been designed to work with random-access iterators, there also exists a version that works with bidirectional iterators. The algorithm is slightly different and a bit slower because it can't as easily jump through the collection. The complexity of that bidirectional iterators algorithm can get down to the same time as the random-access one when `quick_merge_sort` is used as the fallback algorithm.
26
26
27
-
The actual complexity of the algorithm is O(n log n log log n), but interestingly it is only reached in one of its paths that is among the fastest in practice. It is also possible to make vergesort stable but tweaking its reverse runs detection algorithm and making it fallback to a stable sorting algorithm.
27
+
The actual complexity of the algorithm is O(n log n log log n), but interestingly it is only reached in one of its paths that is among the fastest in practice. It is also possible to make vergesort stable by tweaking its reverse runs detection algorithm and making it fallback to a stable sorting algorithm.
28
28
29
29
This sorting algorithm also exists as a [standalone repository][vergesort].
Copy file name to clipboardExpand all lines: docs/Sorter-adapters.md
+7-3Lines changed: 7 additions & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -283,7 +283,6 @@ struct stable_adapter;
283
283
`stable_adapter` is the main customization point of those stable sorting facilities, and as such can be specialized to provide stable versions of your own unstable sorters or adapters. **cpp-sort** itself provides `stable_adapter` specializations for the following components:
284
284
285
285
*[`std_sorter`][std-sorter] (calls [`std::stable_sort`][std-stable-sort] instead of [`std::sort`][std-sort])
286
-
*[`verge_sorter`][verge-sorter]
287
286
*[`hybrid_adapter`][hybrid-adapter]
288
287
*[`self_sort_adapter`][self-sort-adapter]
289
288
*`stable_adapter` itself (automatic unnesting)
@@ -318,13 +317,19 @@ This little dance sometimes allows to reduce the nesting of function calls and t
318
317
#include<cpp-sort/adapters/verge_adapter.h>
319
318
```
320
319
321
-
The complexity analysis is a bit too complicated to be included in this documentation. Additionally, the space and time complexity changes depending on whether the merging algorithm has enough space to run in O(n) time or whether it needs to fall back to an O(n log n) algorithm. Assuming that the *adapted sorter* works in O(n log n) time and O(1) space, the complexity of the *resulting sorter* is as follows:
320
+
Vergesort is a [*Mono*-adaptive][probe-mono] algorithm as long as the size of those runs is greater than *n / log n*; when the runs are smaller, it falls back to the *adapted sorted* to sort them.
321
+
322
+
The space and time complexities of this adapter change depending on whether the merging algorithm has enough space to run in O(n) time or whether it needs to fall back to an O(n log n) algorithm for merging. Assuming that the *adapted sorter* works in O(n log n) time and O(1) space, the complexity of the *resulting sorter* is as follows:
322
323
323
324
| Best | Average | Worst | Memory | Stable | Iterators |
| n | n log n | n log n log log n | n | No | Bidirectional |
326
327
| n | n log n | n log n | log n | No | Bidirectional |
327
328
329
+
We can understand that complexity as being bound by either the vergesort optimization layer or, by the *adapted sorter*'s complexity:
330
+
* When vergesort doesn't find big enough runs, the complexity is bound by that of the *adapted sorter*.
331
+
* When it does find big enough runs, the complexity is bound by the merging phase of the optimization layer. In such a case, `inplace_merge` is used to merge the runs: it uses additional memory if any is available, in which case vergesort is O(n log n). If there isn't much extra memory available, it may still require O(log n) extra memory (and thus raise an `std::bad_alloc` if there isn't that much memory available) in which case the complexity falls to O(n log n log log n).
332
+
328
333
The *resulting sorter* is always unstable, no matter the stability of the *adapted sorter*. It accepts bidirectional ranges.
329
334
330
335
```cpp
@@ -367,5 +372,4 @@ When wrapped into [`stable_adapter`][stable-adapter], it has a slightly differen
| n | n log n | n log n log log n | n | No | Random-access |
394
-
| n | n log n | n log n | log n | No | Random-access |
395
-
| n | n log n | n log n log log n | n | No | Bidirectional |
396
-
| n | n log n | n log n | log² n | No | Bidirectional |
397
-
398
-
Vergesort is a [*Runs*-adaptive][probe-runs] algorithm (including descending runs) as long as the size of those runs is greater than *n / log n*; when the runs are smaller, it falls back to another sorting algorithm to sort them (pdqsort for random-access iterators, QuickMergesort otherwise).
399
-
400
-
Vergesort's complexity is bound either by its optimization layer or by the fallback sorter's complexity:
401
-
* When it doesn't find big runs, the complexity is bound by the fallback sorter: depending on the category of iterators you can refer to the tables of either `pdq_sorter` or `quick_merge_sorter`.
402
-
* When it does find big runs, vergesort's complexity is bound by the merging phase of its optimization layer. In such a case, `inplace_merge` is used to merge the runs: it will use additional memory if any is available, in which case vergesort is O(n log n). If there isn't much extra memory available, it may still require O(log n) extra memory (and thus raise an `std::bad_alloc` if there isn't that much memory available) in which case the complexity falls to O(n log n log log n). It should not happen that much, and the additional *log log n* factor is likely irrelevant for most real-world applications.
403
-
404
-
When wrapped into [`stable_adapter`][stable-adapter], it has a slightly different behaviour: it detects strictly descending runs instead of non-ascending ones, and wraps the fallback sorter with `stable_t`. This make the specialization stable, and faster than just using `make_stable`.
405
-
406
-
*Changed in version 1.6.0:* when sorting a collection made of bidirectional iterators, `verge_sorter` falls back to `quick_merge_sorter` instead of `quick_sorter`.
407
-
408
-
*New in version 1.9.0:* explicit specialization for `stable_adapter<verge_sorter>`.
0 commit comments