快速排序分治函数过程总结

  假设我们已经知道快速排序的算法框架时,我们已经可以从宏观地去掌握快速排序算法的思想。但是快速排序算法的关键还是在于划分操纵,同时快速排序的性能主要取决于划分操作的好坏。快速排序分治partition过程有两种方法:

  1)两个下标分别从首、尾向中间扫描的方法

  2)两个指针索引一前一后逐步向后扫描的方法

  因为我常用第一种,因此,我拿第一种来进行分析,就以下这段代码分析:

 1 int Partition(ElemType R[],int low,int high)
 2  {
 3     ElemType pivot = R[low];//保存枢轴
 4      while(low<high)
 5      {
 6           while(low<high&&R[high]>=pivot)//从右边寻找小于枢轴的值
 7              --high;
 8           R[low]=R[high];
 9           while(low<high&&R[low]<=pivot)//从左边寻找大于枢轴的值
10              ++low;
11          R[high]=R[low];
12      }
13      A[low]=pivot;//基准记录已被最后定位
14      return low;//return high也是可以
15 }

每次调用一次快速排序,都要进行划分。而每次划分时候,在划分函数中将发生以下事情:

1、从传进函数的数组中,取一个数作为枢轴(假设是low下标指向的元素),同时声明一个变量来保存枢轴,我们可以认为我们已经从数组中抽掉一个元素。此时,数组中low位置认为为空。这就给下面的循环创造条件。

对应函数中的语句:

ElemType pivot = R[low];//保存枢轴

2、这是一个循环体(循环(1)(2)),直到不满足low<high跳出:

  (1)因为我们假设枢轴元素为low,那么首次就先从high开始向前面扫描,寻找一个小于枢轴 pivot 的元素。当找到的时候,将high指向的元素调到low处空位子,此时high的位置视为空位子。

while(low<high&&R[high]>=pivot)//从右边寻找小于枢轴的值
             --high;
        R[low]=R[high];//填补low位上的空缺

  (2)然后,从左向右扫描,寻找大于枢轴 pivot的元素。当找到时候,将low指向的元素调到(1)留下的空位high。此时low处为空。

while(low<high&&R[low]<=pivot)//从左边寻找大于枢轴的值
             ++low;
        R[high]=R[low];//填充high处空缺

3、当上述循环结束后,原来程序试图填补那个空缺最后还是没填上,有一种捉襟见肘的感觉。而这个时候,在中间的那个空位置,左边的数全部小于右边的数。这个空位子理所当然就是枢轴所属,因此完成了一次划分,枢轴元素在本次划分中排在了自己最终的位置上。

4、此时,high与low都指向pivot位置,因此返回给快排函数,最为快排算法中递归调用的新的边界。

     A[low]=pivot;//基准记录已被最后定位
     return low;//return high也是可以

还有,我们在划分的过程中,所有与枢轴相同的元素不会移动。

第二种方法有待总结。

原文地址:https://www.cnblogs.com/houjun/p/4888127.html