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


    这个算是捏软柿子了哇。

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

    快排的核心就是:

    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

  • 相关阅读:
    ATM
    Python不同目录间模块调用
    Python跨目录调程序
    Python软件目录结构规范
    进程的创建-multiprocessing
    进程
    多任务版udp聊天器
    死锁
    互斥锁
    同步
  • 原文地址:https://www.cnblogs.com/danxi/p/6440835.html
Copyright © 2020-2023  润新知