快速排序 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
”语句,后来也被各种高级语言广泛采用,比如PASCAL
、C
、Java
语言等等。当然,东尼霍尔在计算机领域的贡献还有很多很多,他在1980年获得了图灵奖。它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
算法
设要排序的数组是A[0]……A[N-1]
,首先任意选取一个数据(通常选用数组的第一个数)作为关键数据,然后将所有比它小的数都放到它前面,所有比它大的数都放到它后面,这个过程称为一趟快速排序。值得注意的是,快速排序不是一种稳定的排序算法,也就是说,多个相同的值的相对位置也许会在算法结束时产生变动。
一趟快速排序的算法是:
1.设置两个变量i
、j
,排序开始的时候:i=0
,j=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的主要内容,如果未能解决你的问题,请参考以下文章