快速排序 Quick sort

Posted Nchusoftacm

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了快速排序 Quick sort相关的知识,希望对你有一定的参考价值。

来由

快速排序由C. A. R. Hoare在1962年提出。之后又有许多人做了进一步的优化。如果你对快速排序感兴趣可以去看看东尼霍尔1962年在Computer Journal发表的论文“Quicksort”以及《算法导论》的第七章。快速排序算法仅仅是东尼霍尔在计算机领域才能的第一次显露,后来他受到了老板的赏识和重用,公司希望他为新机器设计一个新的高级语言。你要知道当时还没有PASCAL或者C语言这些高级的东东。后来东尼霍尔参加了由Edsger Wybe Dijkstra(1972年图灵奖得主,这个大神我们后面还会遇到的到时候再细聊)举办的“ALGOL 60”培训班,他觉得自己与其没有把握去设计一个新的语言,还不如对现有的“ALGOL 60”进行改进,使之能在公司的新机器上使用。于是他便设计了“ALGOL 60”的一个子集版本。这个版本在执行效率和可靠性上都在当时“ALGOL 60”的各种版本中首屈一指,因此东尼霍尔受到了国际学术界的重视。后来他在“ALGOL X”的设计中还发明了大家熟知的“case”语句,后来也被各种高级语言广泛采用,比如PASCALCJava语言等等。当然,东尼霍尔在计算机领域的贡献还有很多很多,他在1980年获得了图灵奖。它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。

算法

设要排序的数组是A[0]……A[N-1],首先任意选取一个数据(通常选用数组的第一个数)作为关键数据,然后将所有比它小的数都放到它前面,所有比它大的数都放到它后面,这个过程称为一趟快速排序。值得注意的是,快速排序不是一种稳定的排序算法,也就是说,多个相同的值的相对位置也许会在算法结束时产生变动。
一趟快速排序的算法是:
   1.设置两个变量ij,排序开始的时候:i=0j=N-1
   2.以第一个数组元素作为关键数据,赋值给temp,即temp=A[0]
   3.从 j 开始向前搜索,即由后开始向前搜索,若a[j]>=temp,且i<j,则j - -;
   4.从 i 开始向后搜索,即由前开始向后搜索,若a[i]<=temp,且i<j,则i++ ;
   5.重复第3、4步,直到i=j

例子

我们以对6个数据排序为例给大家讲解一下这种算法。

待排数组| 6 | 2 | 7 | 3 | 9 | 8 |
下标 | 0 | 1 | 2 | 3 | 4 | 5 |

创建变量i=0(指向第一个数据), j=5(指向最后一个数据), temp=6(赋值为第一个数据的值)。我们要把所有比temp小的数移动到temp的左面,所以我们可以开始寻找比6小的数,从j开始,从右往左找,不断递减变量j的值,我们找到第一个下标3的数据比6小,然后开始找比6大的数,从i开始,从左往右找,不断递增i的值,我们找到第一个下标2的数据比6大,然后将下标为i的数据与下标为j的数据交换,此时数据状态变成下表(此时i=2,j=3

待排数组| 6 | 2 | 3 | 7 | 9 | 8 |
下标 | 0 | 1 | 2 | 3 | 4 | 5 |

由于此时 i ! = j,所以继续循环, 开始第二次比较,从j开始,从右往左找,不断递减变量j的值,当j=2时,i=j=2,不满足i<j,所以将下标为2的值与下标为0的值交换,此时数据状态变成下表(此时i=j=2

待排数组| 3 | 2 | 6 | 7 | 9 | 8 |
下标 | 0 | 1 | 2 | 3 | 4 | 5 |

由于i=j,跳出循环,第一次循环结束,经过第一次循环,我们发现在temp值左边的元素都比temp值要小,在temp值右边的元素都比temp值要大,可以理解为原序列已经被我们以6为分界点拆分成了两个序列,左边的序列是“3  2”,右边的序列是“7  9  8”。接下来还需要分别处理这两个序列。因为6左边和右边的序列目前都还是很混乱的。不过不要紧,我们已经掌握了方法,接下来只要模拟刚才的方法分别处理6左边和右边的序列即可,在这里,笔者只为大家讲解第一次循环,有兴趣的同学不如自己动手试试看。

代码

include<stdio.h> 
int a[101],n;//定义全局变量,这两个变量需要在子函数中使用
void quicksort(int left,int right)
{
   int i,j,t,temp;
   if(left>right)
   return;
   temp=a[left]; //temp中存的就是基准数
   i=left;
   j=right;
   while(i!=j)
   {
       /*顺序很重要,要先从右边开始找 ,读者不妨
       想想为什么一定要先从右边开始找*/

       while(a[j]>=temp && i<j)
           j--;
       while(a[i]<=temp && i<j)
           i++;
       //此处一定要注意加上i<j
       //交换两个数在数组中的位置
       if(i<j)
       {
           t=a[i];
           a[i]=a[j];
           a[j]=t;
       }
   }
   //最终将基准数归位
   a[left]=a[i];
   a[i]=temp;                              
   quicksort(left,i-1);//继续处理左边的,这里是一个递归的过程
   quicksort(i+1,right);//继续处理右边的 ,这里是一个递归的过程
}
int main()
{
   int i,j,t;
   scanf("%d",&n);
   for(i=1;i<=n;i++)
   scanf("%d",&a[i]);
   quicksort(1,n); //快速排序调用
   for(i=1;i<=n;i++)
   printf("%d ",a[i]);
   return 0;
}



DEV C++运行结果:

软件学院ACM队,我们一直在努力


阅读原文可查看更多关于快排算法的信息。


以上是关于快速排序 Quick sort的主要内容,如果未能解决你的问题,请参考以下文章

快速排序算法回顾 --冒泡排序Bubble Sort和快速排序Quick Sort(Python实现)

Quick Sort(快速排序)

交换排序—快速排序(Quick Sort)

快速排序 Quick sort

排序:快速排序Quick Sort

算法之排序算法 -- 快速排序 Quick sort