算法导论第三版--快速排序

这个算是捏软柿子了哇。

不过用模板来实现也是非常有趣。

 

快排的核心就是:

1、在数组中选择一个参考值X,再设置2个索引,一个用来记录比这个X小的位置i,一个用来记录比这个X大的位置j

2、比如是升序排序,就把大的值交换到小的值的位置,小的值交换到大的值的位置,如果是降序,就相反的交换,总而言之,就是交换一下值

3、如果没有找到满足比较条件的值,比如升序,没有找到比参考值X小的值,就将索引j加1,继续找,找到了,就将小的值的索引i加1,然后交换

4、如此,到循环结束,比如升序,将最后索引i所在位置的值与X所在位置的值交换,这个i就把数组分开成2半了,然后对左右的2半进行同样如上几步操作,即递归完成了排序。

所以参考值X的选择非常重要,运气差的话,就分不均匀,可能达到O(n^2)的复杂度了,也就出现随机分断的版本,这是看人品嘛。

 

补充了尾递归的实现。

下面是俺的练手之作:

 1 #include <iostream>
 2 #include <vector>
 3 #include <functional>
 4 #include <cassert>
 5 #include <cmath>
 6 #include <ctime>
 7 #include <cstdlib>
 8 #include <random>
 9 
10 using namespace std;
11 
12 template<typename _InIt, typename _Func>
13 _InIt __partition(_InIt first, _InIt last, _Func& Func) {
14     typedef typename  iterator_traits<_InIt>::value_type _ValueType;
15 
16     _ValueType val = *(last);
17     _InIt _Ite = first-1;
18 
19     for (_InIt it = first; (last-it)>=1; ++it) {
20         if (Func(*it, val)) {
21             _Ite++;
22             iter_swap(_Ite, it);
23         }
24     }
25 
26     iter_swap(++_Ite, last);
27     return _Ite;
28 }
29 
30 template<typename _InIt, typename _Func>
31 _InIt randomized_partition(_InIt first, _InIt last, _Func& Func) {
32     size_t offset = last - first;
33     assert((last - first)>0);
34 
35     random_device rd ;
36     default_random_engine e(rd());
37     uniform_int_distribution <> u(0, offset);
38 
39     iter_swap(last, first+u(e));
40     return __partition(first, last, Func);
41 }
42 
43 template<typename _InIt, typename _Func>
44 void __quick_sort(_InIt first, _InIt last, _Func& Func) {
45     if (last - first > 0) {
46         _InIt it = randomized_partition(first, last, Func);
47         __quick_sort(first, it-1, Func);
48         __quick_sort(it+1, last, Func);
49     }
50 }
51 
52 template<typename _InIt, typename _Func>
53 void quick_sort(_InIt first, _InIt last, _Func& Func) {
54     __quick_sort(first, --last, Func);
55 }
56 
57 int main() {
58     int lst[] = {2,8,7,1,3,5,6,4};
59     vector<int> v(lst, lst+8);
60 
61     //greater_equal<int> cmp;
62     less_equal<int> cmp;
63     quick_sort(v.begin(), v.end(), cmp);
64 
65     for(vector<int>::iterator it=v.begin(); it != v.end(); it++)
66        cout << *it << " ";
67     cout << endl;
68 
69     return 0;
70 }

 

 这里补充一个模拟尾递归的实现(可以说是迭代啦):

1 template<typename _InIt, typename _Func>
2 void tail_rescursive_quick_sort(_InIt first, _InIt last, _Func& Func) {
3     while (last - first > 0) {
4         _InIt it = __partition(first, last, Func);
5         tail_rescursive_quick_sort(first, it-1, Func);
6         first = it + 1;
7     }
8 }

对于上面的quick_sort,它的区别在于通过循环不断将数组从左边向右边逼近,每次不用开启更多的函数调用栈,可以避免过度递归调用栈溢出。

可以形象的想象上面非尾递归它的栈就像一个二叉树(坏的情况下是一个完全平衡的二叉树的话),随着树的高度越高会比尾递归的栈多出非常多。

 

参考C++11的随机数:

http://www.cnblogs.com/egmkang/archive/2012/09/06/2673253.html

posted @ 2017-02-25 02:50  丹西  阅读(440)  评论(0编辑  收藏  举报