二路归并
如果内存充足,可以考虑使用非原地的归并排序获得更快的速度。非原地的归并排序算法空间复杂度为O(n),时间复杂度O(nlogn)。它的核心是归并,下面看看归并的基本实现过程。
待排序序列:
52, 50, 50, 74, 61, 46, 84, 85, 73, 23, 94, 53, 97, 98, 65, 87, 29, 13, 61, 58, 19
可以把上面的无序序列分成四段并对各段进行插入排序,得到四个有序子序列:
46, 50, 50, 52, 61, 74, 84, 23, 73, 85, 94, 13, 29, 53, 65, 87, 97, 98, 19, 58, 61
两两归并成一段,得到两个有序子序列:
23, 46, 50, 50, 52, 61, 73, 74, 84, 85, 94, 13, 19, 29, 53, 58, 61, 65, 87, 97, 98
归并成一个有序序列,排序完成。
13, 19, 23, 29, 46, 50, 50, 52, 53, 58, 61, 61, 65, 73, 74, 84, 85, 87, 94, 97, 98
1 template <typename InputIterator, typename OutputIterator, typename Compare>
2 OutputIterator merge(InputIterator first1, InputIterator last1, InputIterator first2,
3 InputIterator last2, OutputIterator result, Compare cmp)
4 {
5 while(first1 != last1 && first2 != last2)
6 {
7 if(cmp(*first2, *first1))
8 {
9 *result = *first2;
10 ++first2;
11 }
12 else
13 {
14 *result = *first1;
15 ++first1;
16 }
17 ++result;
18 }
19 return copy(first2, last2, copy(first1, last1, result));
20 }
21
22 template <typename RandomIterator, typename Compare>
23 void merge_sort_loop(RandomIterator first, RandomIterator last,
24 RandomIterator result, int step_size, Compare cmp)
25 {
26 int two_steps = step_size << 1;
27 while(last - first >= two_steps)
28 {
29 result = merge(first, first + step_size, first + step_size,
30 first + two_steps, result, cmp);
31 first += two_steps;
32 }
33 if(last - first < step_size)
34 step_size = last - first;
35 merge(first, first + step_size, first + step_size, last, result, cmp);
36 }
37
38 template <typename RandomIterator, typename Compare>
39 void chunk_insertion(RandomIterator first, RandomIterator last,
40 int chunk_size, Compare cmp)
41 {
42 while(last - first >= chunk_size)
43 {
44 insertion_sort(first, first + chunk_size, cmp);
45 first += chunk_size;
46 }
47 insertion_sort(first, last, cmp);
48 }
49
50 template <typename RandomIterator, typename Compare>
51 void merge_with_buffer(RandomIterator first, RandomIterator last,
52 RandomIterator buffer, Compare cmp)
53 {
54 int len = last - first;
55 RandomIterator buffer_last = buffer + len;
56 int step_size = 7;
57 chunk_insertion(first, last, step_size, cmp);
58 while(step_size < len)
59 {
60 merge_sort_loop(first, last, buffer, step_size, cmp);
61 step_size <<= 1;
62 merge_sort_loop(buffer, buffer_last, first, step_size, cmp);
63 step_size <<= 1;
64 }
65 }
66
67 template <typename RandomIterator, typename Compare>
68 RandomIterator merge_backward(RandomIterator first1, RandomIterator last1,
69 RandomIterator first2, RandomIterator last2,
70 RandomIterator result, Compare cmp)
71 {
72 if(first1 == last1)
73 return copy_backward(first2, last2, result);
74 if(first2 == last2)
75 return copy_backward(first1, last1, result);
76 --last1, --last2;
77 while(true)
78 if(cmp(*last2, *last1))
79 {
80 *--result = *last1;
81 if(first1 == last1)
82 return copy_backward(first2, ++last2, result);
83 --last1;
84 }
85 else
86 {
87 *--result = *last2;
88 if(first2 == last2)
89 return copy_backward(first1, ++last1, result);
90 --last2;
91 }
92 }
93
94 template <typename RandomIterator, typename Compare>
95 inline void buffered_merge_sort_adaptive(RandomIterator first, RandomIterator last,
96 RandomIterator buffer, Compare cmp)
97 {
98 RandomIterator middle = first + ((last - first + 1) >> 1);
99 merge_with_buffer(first, middle, buffer, cmp);
100 merge_with_buffer(middle, last, buffer, cmp);
101 int len1 = middle - first, len2 = last - middle;
102 if(len1 <= len2)
103 {
104 RandomIterator buffer_end = copy(first, middle, buffer);
105 merge(buffer, buffer_end, middle, last, first, cmp);
106 }
107 else
108 {
109 RandomIterator buffer_end = copy(middle, last, buffer);
110 merge_backward(first, middle, buffer, buffer_end, last, cmp);
111 }
112 }
113
114 template <typename RandomIterator, typename T, typename Compare>
115 inline void buffered_merge_sort_aux(RandomIterator first, RandomIterator last, Compare cmp, T)
116 {
117 T* buf = new(std::nothrow)T[last - first];
118 if(0 != buf)
119 buffered_merge_sort_adaptive(first, last, buf, cmp);
120 delete [] buf;
121 }
122
123 template <typename RandomIterator, typename Compare>
124 inline void buffered_merge_sort(RandomIterator first, RandomIterator last, Compare cmp)
125 {
126 if(last - first > 1)
127 buffered_merge_sort_aux(first, last, cmp, *first);
128 }
以上代码实现中用到了直接插入排序和拷贝算法,直接插入排序见本主页快排的介绍,拷贝算法见标准库,本主页暂无介绍(以后也许会加上)。