算法:快速排序
2010-07-06 20:42
288 查看
快速排序是对冒泡排序的一种改进。它的基本思想是,通过一趟排序将待排序记录分割成独立的两部分,其中一部分记录的关键字均比另一部分的记录的关键字小,则可分别对这两部分记录继续进行排序,一达到整个序列有序。
假设待排序的序列存放于数组array中,首先任意选取一个记录(通常可选第一个记录)作为枢轴,然后按下述原则重新排列其余记录:将所有关键字较它小的记录都安置在它的位置之前,将所有关键字较它大的记录都安置在它的位置之后。由此将序列分割成两个子序列。这个过程成为一趟快速排序。
一趟快速排序的具体做法是:附设两个指针low和high,它们的初始位置分别为low和high,设枢轴记录的关键字为key,则首先从high所指的位置起向前搜索找到第一个关键字比key小的记录和枢轴记录相互交换,然后从low所指的位置起向后搜索,找到第一个关键字大于key的记录和枢轴记录相互交换,重复至这两步直至low=high为止。
这个快速排序的过程可递归进行。若待排序列中只有一个记录,显然已有序,否则进行一趟快速排序后再分别对分割所得的两个子序列进行快速排序。
算法实现如下:
具体实现上述算法时,每交换一对记录需进行3次记录移动赋值操作。而实际上,在排序过程中对枢轴记录的赋值是多余的,因为只有在一趟排序结束时,即low=high的位置才是枢轴的最后位置。由此可改写上述算法,先将枢轴记录暂存在key中,排序过程中只作array[low]或array[high]的单向移动,直至一趟排序结束后再将枢轴记录移至正确位置上。
算法实现如下:
快速排序的平均时间为T(n)=knlog(n),其中n为待排序序列中记录的个数,k为某个常数,经验表明,在所有同数量级的先进排序方法中,快速排序的常数因子k最小。因此就平均时间而言,快速排序是目前被认为是最好的一种内部排序方法。
通常,快速排序被认为是,在所有同数量级(O(nlog(n)))的排序方法中,其平均性能最好。但是,若初始记录序列按关键字有序或者基本有序时,快速排序将退化为冒泡排序,即其时间复杂度为O(n*n),为改进之,通常依据“三者取中”的法则来选取枢轴记录,即比较最地位,最高位和中间值,取三者中关键字取中值的记录为枢轴。经验表明,采取三者取中的规则可大大改善快速排序在最坏情况下的性能。
然而,即使如此,也不能是快速排序在待排序记录序列已经按关键字有序的情况下达到O(n)的时间复杂度。为此,可如下修改“一次划分”算法:在指针high减1和low增加1的同时进行起泡操作,即在相邻的两个记录处于逆序时进行交换,同时在算法中附设两个布尔型变量分别指示指针low和high在从两端向中间移动的过程中是否进行过交换记录的操作,若指针low在从低端向中间移动的过程中没有进行交换记录的操作,则不需要对低端记录子表尽进行排序。类似地,若指针high在从高端向中间移动的过程中没有进行交换记录的操作,则不需要对高端子表尽心排序。显然,如此划分将进一步该改善快速排序的平均性能。
假设待排序的序列存放于数组array中,首先任意选取一个记录(通常可选第一个记录)作为枢轴,然后按下述原则重新排列其余记录:将所有关键字较它小的记录都安置在它的位置之前,将所有关键字较它大的记录都安置在它的位置之后。由此将序列分割成两个子序列。这个过程成为一趟快速排序。
一趟快速排序的具体做法是:附设两个指针low和high,它们的初始位置分别为low和high,设枢轴记录的关键字为key,则首先从high所指的位置起向前搜索找到第一个关键字比key小的记录和枢轴记录相互交换,然后从low所指的位置起向后搜索,找到第一个关键字大于key的记录和枢轴记录相互交换,重复至这两步直至low=high为止。
这个快速排序的过程可递归进行。若待排序列中只有一个记录,显然已有序,否则进行一趟快速排序后再分别对分割所得的两个子序列进行快速排序。
算法实现如下:
具体实现上述算法时,每交换一对记录需进行3次记录移动赋值操作。而实际上,在排序过程中对枢轴记录的赋值是多余的,因为只有在一趟排序结束时,即low=high的位置才是枢轴的最后位置。由此可改写上述算法,先将枢轴记录暂存在key中,排序过程中只作array[low]或array[high]的单向移动,直至一趟排序结束后再将枢轴记录移至正确位置上。
算法实现如下:
快速排序的平均时间为T(n)=knlog(n),其中n为待排序序列中记录的个数,k为某个常数,经验表明,在所有同数量级的先进排序方法中,快速排序的常数因子k最小。因此就平均时间而言,快速排序是目前被认为是最好的一种内部排序方法。
通常,快速排序被认为是,在所有同数量级(O(nlog(n)))的排序方法中,其平均性能最好。但是,若初始记录序列按关键字有序或者基本有序时,快速排序将退化为冒泡排序,即其时间复杂度为O(n*n),为改进之,通常依据“三者取中”的法则来选取枢轴记录,即比较最地位,最高位和中间值,取三者中关键字取中值的记录为枢轴。经验表明,采取三者取中的规则可大大改善快速排序在最坏情况下的性能。
然而,即使如此,也不能是快速排序在待排序记录序列已经按关键字有序的情况下达到O(n)的时间复杂度。为此,可如下修改“一次划分”算法:在指针high减1和low增加1的同时进行起泡操作,即在相邻的两个记录处于逆序时进行交换,同时在算法中附设两个布尔型变量分别指示指针low和high在从两端向中间移动的过程中是否进行过交换记录的操作,若指针low在从低端向中间移动的过程中没有进行交换记录的操作,则不需要对低端记录子表尽进行排序。类似地,若指针high在从高端向中间移动的过程中没有进行交换记录的操作,则不需要对高端子表尽心排序。显然,如此划分将进一步该改善快速排序的平均性能。
相关文章推荐
- 《算法(第四版)》排序-----快速排序
- 快速排序的划分算法的总结和思考
- 算法系列之六:快速排序
- 基础算法之快速排序
- 啊哈!算法 - 桶排序,冒泡排序,快速排序 - PHP实现
- 简单算法--冒泡排序、快速排序、选择排序及二分法
- 选择排序、快速排序、希尔排序、堆排序不是稳定的排序算法, 冒泡排序、插入排序、归并排序和基数排序是稳定的排序算法。
- 算法学习之分治--快速排序
- 【排序及算法】冒泡/选择/插入/快速排序、顺序查找/折半查找算法
- 【算法学习】排序算法-快速排序
- 浅谈算法和数据结构: 四 快速排序
- 算法---快速排序
- 快速排序 -- 算法小结
- [转]【坐在马桶上看算法】算法3:最常用的排序——快速排序--作者:ahalei
- 算法实例-C#-快速排序-QuickSort
- 坐在马桶上看算法:快速排序
- 【数据结构与算法】快速排序
- 基础算法(二):堆排序,快速排序
- 【经典算法】:快速排序