快速排序
1.大致的介绍:
快速排序(QuickSort)是一种有效的排序算法。虽然算法在最坏的情况下运行时间为O(n^2),但由于平均运行时间为O(nlogn),并且在内存使用、程序实现复杂性上表现优秀,尤其是对快速排序算法进行随机化的可能,使得快速排序在一般情况下是最实用的排序方法之一。
快速排序被认为是当前最优秀的内部排序方法。
2.实现
快速排序的实现基于分治法,具体分为三个步骤。假设待排序的序列为L[m..n]。
分解:序列L[m ..n]被划分成两个可能为空的子序列L[m.. pivot-1]和L[pivot+1 ..n],使L[m ..pivot-1]的每个元素均小于或等于L[pivot],同时L[pivot+1.. n]的每个元素均大于L[pivot]。其中L[pivot]称为这一趟分割中的主元(也称为枢轴、支点)。
解决:通过递归调用快速排序,对子序列L[m .. pivot-1]和L[pivot+1 .. r]排序。
合并:由于两个子序列是就地排序的,所以对它们的合并不需要操作,整个序列L[m .. n]已排好序。
3.性质
内部排序
快速排序是一种内部排序方法。也就是说快速排序的排序对象是读入内存的数据。
比较排序
快速排序确定元素位置的方法基于元素之间关键字大小的比较。
所有基于比较方法的排序方法的时间下界不会低于O(nlgn)。这个结论的具体证明,请参考有关算法的书籍,例如《算法导论》(第一版)第8章(第二版在第七章QuickSort)。
在理想情况下,能严格地达到O(nlgn)的下界。一般情况下,快速排序与随机化快速排序的平均情况性能都达到了O(nlgn)。
不稳定性
快速排序是一种不稳定的排序方法。简单地说,元素a1, a2的关键字有a1.key=a2.key,则不稳定的排序方法不能保证a1, a2在排序后维持原来的位置先后关系。
原地排序
在排序的具体操作过程中,除去程序运行实现的空间消费(例如递归栈),快速排序算法只需消耗确定数量的空间(即S(1),常数级空间)。
这个性质的意义,在于在内存空间受到限制的系统(例如MCU)中,快速排序也能够很好地工作。
4.时空复杂度
快速排序每次将待排序数组分为两个部分,在理想状况下,每一次都将待排序数组划分成等长两个部分,则需要logn次划分。
而在最坏情况下,即数组已经有序或大致有序的情况下,每次划分只能减少一个元素,快速排序将不幸退化为冒泡排序,所以快速排序时间复杂度下界为O(nlogn),最坏情况为O(n^2)。在实际应用中,快速排序的平均时间复杂度为O(nlogn)。
快速排序在对序列的操作过程中只需花费常数级的空间。空间复杂度S(1)。
但需要注意递归栈上需要花费最少logn 最多n的空间。
5.随机化算法
快速排序的最坏情况基于每次划分对主元的选择。基本的快速排序选取第一个元素作为主元。这样在数组已经有序的情况下,每次划分将得到最坏的结果。一种比较常见的优化方法是随机化算法,即随机选取一个元素作为主元。这种情况下虽然最坏情况仍然是O(n^2),但最坏情况不再依赖于输入数据,而是由于随机函数取值不佳。实际上,随机化快速排序得到理论最坏情况的可能性仅为1/(2^n)。所以随机化快速排序可以对于绝大多数输入数据达到O(nlogn)的期望时间复杂度。一位前辈做出了一个精辟的总结:“随机化快速排序可以满足一个人一辈子的人品需求。”
随机化快速排序的唯一缺点在于,一旦输入数据中有很多的相同数据,随机化的效果将直接减弱。对于极限情况,即对于n个相同的数排序,随机化快速排序的时间复杂度将毫无疑问的降低到O(n^2)。
6.减少递归栈使用的优化
快速排序的实现需要消耗递归栈的空间,而大多数情况下都会通过使用系统递归栈来完成递归求解。在元素数量较大时,对系统栈的频繁存取会影响到排序的效率。
一种常见的办法是设置一个阈值,在每次递归求解中,如果元素总数不足这个阈值,则放弃快速排序,调用一个简单的排序过程完成该子序列的排序。这样的方法减少了对系统递归栈的频繁存取,节省了时间的消费。
一般的经验表明,阈值取一个较小的值,排序算法采用选择、插入等紧凑、简洁的排序。一个可以参考的具体方案:阈值T=10,排序算法用选择排序。
阈值不要太大,否则省下的存取系统栈的时间,将会被简单排序算法较多的时间花费所抵消。
另一个可以参考的方法,是自行建栈模拟递归过程。但实际经验表明,收效明显不如设置阈值。
7.C语言代码实现如下,头文件中不要引用stdlib.h这个头文件,此中已经定义了qsort这个函数,编译会出错:
#include <stdio.h>
int partions(int l[],int low,int high)
{
int prvotkey=l[low];
l[0]=l[low];
while (low<high)
{
while (low<high&&l[high]>=prvotkey)
{
--high; //从右端开始,检索小于参照值得数据,若没有一次左移
}
l[low]=l[high]; //检测到后作交换
while (low<high&&l[low]<=prvotkey)
{
++low; //从左端低位开始,检索大于参照值得数据,若没有一次右移
}
l[high]=l[low];
}
l[low]=l[0];
return low;
}
void qsort(int l[],int low,int high)
{
int prvotloc;
if(low<high)
{
prvotloc=partions(l,low,high); //将第一次排序的结果作为枢轴
qsort(l,low,prvotloc-1); //递归调用排序 由low 到prvotloc-1
qsort(l,prvotloc+1,high); //递归调用排序 由 prvotloc+1到 high
}
}
void quicksort(int l[],int n)
{
qsort(l,1,n); //第一个作为枢轴 ,从第一个排到第n个
}
int main()
{
int a[11]= {0};
int d,b,c;
for(d=1;d<11;d++)
{
printf("Input : ");
scanf("%d",a+d);
}
for (b=1; b<11; b++)
{
printf("%3d",a[b]);
}
printf("\n");
quicksort(a,11);
for(c=1; c<11; c++)
{
printf("%3d",a[c]);
}
printf("\n");
return 0;
}
运行结果如下:
分享到:
相关推荐
PHP_基于php实现的快速排序算法_QuickSort
这事一个总结快速排序内涵和实现比较优秀的稿件,总重可以加深对排序的了解。具体代码可以在我的博客中找到(快速排序 thinking in quicksort)。
资源名:quicksort_matlab_快速排序 资源类型:matlab项目全套源码 源码说明: 全部项目源码都是经过测试校正后百分百成功运行的,如果您下载后不能运行可联系我进行指导或者更换。 适合人群:新手及有一定经验的...
日本程序员norahiko,写了一个排序算法的动画演示,非常有趣...目前,最常见的排序算法大概有七八种,其中"快速排序"(Quicksort)使用得最广泛,速度也较快。它是图灵奖得主C. A. R. Hoare(1934--)于1960时提出来的
快速排序(Quicksort)的Javascript实现
分治法的应用,快速排序是其中一种。注释便于读者明白。
void quicksort(int A[],int p,int r) { int q; if(p) { q=partition(A,p,r); quicksort(A,p,q-1); quicksort(A,q+1,r); } } /****************************************************/
分治法的另外一种排序算法,快速排序。有注释,便于阅读,因为交换时使用的引用,暂时归为C++,C语言版稍后奉上。
然后定义了quickSort函数来实现快速排序算法。在main函数中,我们定义了一个数组并对其进行快速排序,并打印排序后的结果。 快速排序是一种高效的排序算法,它的实现相对简单但性能优秀。希望这个示例能帮助你理解...
快速排序是由东尼·霍尔所发展的一种排序算法。在平均状况下,排序 n 个项目要Ο(n log n)次比较。在最坏状况下则需要Ο(n2)次比较,但这种状况并不常见。事实上,快速排序通常明显比其他Ο(n log n) 算法更快,因为...
快速排序源代码,采用C++编写,经测试未发现BUG,供大家参考
快速排序QuickSort.java
用分治的思想模拟快速排序的迭代过程,快速排序平均运行时间可以和Heapsort媲美
用MPICH实现的快速排序算法,可以在高性能计算机环境下运行,大家可以学习一下
快速排序 快速排序(Quicksort)是一种常见的、高效的排序算法,它基于分治(Divide and Conquer)的思想
排序算法 排序算法_基于C语言实现的排序算法之QuickSort实现
C# 快速排序源码, 包含调用方式和注释,QuickSort.cs ///调用方式 /// /// int[] arr = new int[] { 5,3,9,6,4,7,8,1,2}; /// QuickSort.quickSort(arr, 0, arr.Length - 1); /// ///
QuickSort快速排序的实现 [Qsort类] 使用C++模版,可实现自定义类型的排序方式 同时通过折半查找检索元素 附带控制台演示 欢迎指正和建议 程序详细描述可见:...
快速排序是20世纪十大算法之一,可见其精妙之处,相较于其他复杂度为O(n^2),可以提高到n*logn.一般我们研究快速排序基本采用内置类型,如int型数据,本类为了更通用,采用了模板类,具体数据对象类型可根据用户自己...
在VS 2008中,用C语言写的快速排序算法。不用多余的数组,直接对原数组进行排序(in place)。同时在递归调用中,对于【数组组就是数组首地址】的理解会更加通透。