• 快速排序


    【1】快速排序

    快速排序是由托尼。霍尔(英文名C. A. R. Hoare,英国人,计算机领域爵士,同时是文科生获图灵奖者之一)于1962年提出的一种划分交换排序。

    快速排序采用的是一种分治策略。快速排序经典之处在于它的排序思想。

    所谓分治就是分而治之,从字面意思即可理解为:复杂问题简单化,简单问题重复化,重复问题高效化。所以,相比其它排序算法更快速。

    而书面解释为:将原问题分解为若干个规模更小但结构与原问题相似的子问题。递归地处理这些子问题,然后将这些子问题的解组合为原问题的解。

    快速排序是一种不稳定的排序(参见随笔《常用排序算法稳定性分析》)。

    快速排序是时间复杂度是O(nlogn)。

    【2】排序逻辑

    设要排序的数组是A[0]~A[N-1]。(下面的例子中A[0]所为哨兵位,所谓哨兵位,即就是临时寄存关键数据位置)

    首先任意选取一个数据(通常选用第一个数据,在示例中从A[1]开始)作为关键数据,然后将所有比它大的数都放到它后面,所有比它小的数都放到它前面,这个过程称为一趟快速排序。

    一趟快速排序的算法是:

    <1>设置两个变量i, j,排序开始的时候:i = 1, j = N-1;

    <2>以第一个数组元素(示例中即A[1])作为关键数据,赋值给A[0];

    <3>从j开始向前搜索,即由后开始向前搜索(--j),找到第一个小于关键数据A[0]的值A[j], A[i] = A[j];

    <4>从i开始向后搜索,即由前开始向后搜索(++i),找到第一个大于关键数据A[0]的值A[i], A[j] = A[i];

    <5>重复3,4,5步,直到 i == j;

    (注意:只有当i == j时,才可以完全确定当前关键数据可以插入的位置,即就是满足比关键数据小的值全部置于其前,比关键数据大的值全部置于其后。)

    【3】排序图解(借用百度图片)

    该图片很形象,全神贯注,仔细观察:

    【4】C++实现排序代码

    (1)C++实现排序详细测试过程示例代码:

      1 #include<iostream>
      2 using namespace std;
      3 #define   MAXSIZE   10
      4 
      5 void PrintArr(int ar[],int n)
      6 {
      7     for(int i = 0; i < n; ++i)
      8     {
      9         cout<<ar[i]<<" ";
     10     }
     11     cout<<endl;
     12 }
     13 
     14 int nCount = 0;
     15 
     16 int Partition(int br[], const int left, const int right)
     17 {
     18     ++nCount;
     19     cout<<""<<nCount<<"趟排序过程如下:"<<endl;
     20     int i = left, j = right;  
     21     cout<<"left = "<<left<<endl;
     22      br[0] = br[left];    //注意哨兵位的作用:暂存本趟排序的关键数据
     23     cout<<"关键字:"<<br[0]<<endl;
     24     cout<<"调整前顺序:"<<endl;
     25     PrintArr(br, MAXSIZE);
     26     while(i < j)
     27     {
     28         while(i < j && br[j] > br[0])   //从末尾开始
     29         {
     30             --j;      //前移一位
     31         }
     32         br[i] = br[j];  //比关键字小的前置
     33         cout<<"比当前关键字大者调整结果:"<<endl;
     34         PrintArr(br, MAXSIZE);
     35         while(i < j && br[i] <= br[0])  //从前端开始
     36         {
     37             ++i;    //后移一位
     38         }
     39         br[j] = br[i];  //比关键字大的后置
     40         cout<<"比当前关键字小者调整结果:"<<endl;
     41         PrintArr(br, MAXSIZE);
     42     } 
     43     br[i] = br[0];  //插入关键字
     44     PrintArr(br, MAXSIZE);
     45     cout<<"i = "<<i<<endl;
     46     cout<<"本趟结束"<<endl;
     47     return i;
     48     
     49 }
     50 
     51 void Quicksort(int br[],const int left,const int right)
     52 {
     53     if(left < right)
     54     {
     55         int mid = Partition(br, left, right);
     56         Quicksort(br,left,mid-1);
     57         Quicksort(br,mid+1,right);
     58     }
     59 }
     60 
     61 void Quicksort(int br[],int n)
     62 {
     63     Quicksort(br, 1, n);
     64 } 
     65 
     66 void  main()
     67 {
     68     int ar[MAXSIZE] = {0, 14, 2, 58, 69, 100, 50, 26, 65, 97}; 
     69     cout<<"排序前原数组"<<endl;
     70     PrintArr(ar, MAXSIZE);   
     71     Quicksort(ar, MAXSIZE-1);   
     72     cout<<"排序后数组排序"<<endl;
     73     PrintArr(ar, MAXSIZE);
     74 
     75 }
     76 /*
     77 排序前原数组
     78 0 14 2 58 69 100 50 26 65 97
     79 第1趟排序过程如下:
     80 left = 1
     81 关键字:14
     82 调整前顺序:
     83 14 14 2 58 69 100 50 26 65 97
     84 比当前关键字大者调整结果:
     85 14 2 2 58 69 100 50 26 65 97
     86 比当前关键字小者调整结果:
     87 14 2 2 58 69 100 50 26 65 97
     88 14 2 14 58 69 100 50 26 65 97
     89 i = 2
     90 本趟结束
     91 第2趟排序过程如下:
     92 left = 3
     93 关键字:58
     94 调整前顺序:
     95 58 2 14 58 69 100 50 26 65 97
     96 比当前关键字大者调整结果:
     97 58 2 14 26 69 100 50 26 65 97
     98 比当前关键字小者调整结果:
     99 58 2 14 26 69 100 50 69 65 97
    100 比当前关键字大者调整结果:
    101 58 2 14 26 50 100 50 69 65 97
    102 比当前关键字小者调整结果:
    103 58 2 14 26 50 100 100 69 65 97
    104 比当前关键字大者调整结果:
    105 58 2 14 26 50 100 100 69 65 97
    106 比当前关键字小者调整结果:
    107 58 2 14 26 50 100 100 69 65 97
    108 58 2 14 26 50 58 100 69 65 97
    109 i = 5
    110 本趟结束
    111 第3趟排序过程如下:
    112 left = 3
    113 关键字:26
    114 调整前顺序:
    115 26 2 14 26 50 58 100 69 65 97
    116 比当前关键字大者调整结果:
    117 26 2 14 26 50 58 100 69 65 97
    118 比当前关键字小者调整结果:
    119 26 2 14 26 50 58 100 69 65 97
    120 26 2 14 26 50 58 100 69 65 97
    121 i = 3
    122 本趟结束
    123 第4趟排序过程如下:
    124 left = 6
    125 关键字:100
    126 调整前顺序:
    127 100 2 14 26 50 58 100 69 65 97
    128 比当前关键字大者调整结果:
    129 100 2 14 26 50 58 97 69 65 97
    130 比当前关键字小者调整结果:
    131 100 2 14 26 50 58 97 69 65 97
    132 100 2 14 26 50 58 97 69 65 100
    133 i = 9
    134 本趟结束
    135 第5趟排序过程如下:
    136 left = 6
    137 关键字:97
    138 调整前顺序:
    139 97 2 14 26 50 58 97 69 65 100
    140 比当前关键字大者调整结果:
    141 97 2 14 26 50 58 65 69 65 100
    142 比当前关键字小者调整结果:
    143 97 2 14 26 50 58 65 69 65 100
    144 97 2 14 26 50 58 65 69 97 100
    145 i = 8
    146 本趟结束
    147 第6趟排序过程如下:
    148 left = 6
    149 关键字:65
    150 调整前顺序:
    151 65 2 14 26 50 58 65 69 97 100
    152 比当前关键字大者调整结果:
    153 65 2 14 26 50 58 65 69 97 100
    154 比当前关键字小者调整结果:
    155 65 2 14 26 50 58 65 69 97 100
    156 65 2 14 26 50 58 65 69 97 100
    157 i = 6
    158 本趟结束
    159 排序后数组排序
    160 65 2 14 26 50 58 65 69 97 100
    161 */

    【2】中分析逻辑的第五条也就是为什么while(i < j ) 而不是 if(i <j )的原因提醒(也可以从上面的测试程序第二趟排序结果分析原因。)。

    (2)完整快速排序实现代码:

     1 int Partition(int br[], const int left, const int right)
     2 {
     3     int i = left, j = right;  
     4      br[0] = br[left];   
     5     while(i < j)
     6     {
     7         while(i < j && br[j] > br[0])   
     8         {
     9             --j;      
    10         }
    11         br[i] = br[j];  
    12         while(i < j && br[i] <= br[0])  
    13         {
    14             ++i;   
    15         }
    16         br[j] = br[i]; 
    17     } 
    18     br[i] = br[0];  
    19     return i;
    20     
    21 }
    22 
    23 void Quicksort(int br[],const int left,const int right)
    24 {
    25     if(left < right)
    26     {
    27         int mid = Partition(br, left, right);
    28         Quicksort(br,left,mid-1);
    29         Quicksort(br,mid+1,right);
    30     }
    31 }
    32 
    33 void Quicksort(int br[],int n)
    34 {
    35     Quicksort(br, 1, n);
    36 } 

    关于快速排序的代码,可以有很多种写法,个人认为,此种写法比较好理解,并且易于阅读。

     

    Good Good Study, Day Day Up.

    顺序  选择  循环  坚持  总结

    作者:kaizen
    声明:本文版权归作者和博客园共有,欢迎转载。但未经作者同意必须保留此声明,且在文章明显位置给出本文链接,否则保留追究法律责任的权利。
    签名:顺序 选择 循环
  • 相关阅读:
    编写一个截取字符串的函数,输入为一个字符串和字节数,输出为按字节截取的字符串。 但是要保证汉字不被截半个,如“我ABC”4,应该截为“我AB”,输入“我ABC汉DEF”,6,应该输出为“我ABC”而不是“我ABC+汉的半个”。
    Java基础——数据类型之间的转换
    Spring 事物机制总结
    Spring 3.0 注解注入详解
    Spring 注解 @Resource和@Autowired
    从jsp向servlet传送数据的两种方式
    文本输入框,只能显示内容而不能修改
    myeclipse 中项目名出现红色感叹号解决方法
    在servlet中使用split()截取以反斜杠‘’分割的字符串
    jsp页面跳转方式
  • 原文地址:https://www.cnblogs.com/Braveliu/p/2857222.html
Copyright © 2020-2023  润新知