快速排序实现(递归+非递归)
2016-04-06 22:12
211 查看
快速排序代码
首先是划分算法,假设每次都以第一个元素作为枢轴值,进行一趟划分:
int Partition(int A[], int low, int high)
{
int pivot = A[low];
while (low < high)
{
while (low < high && A[high] >= pivot)
--high;
A[low] = A[high]; //将比枢轴值小的元素移到左边
while (low < high && A[low] <= pivot)
++low;
A[high] = A[low]; //将比枢轴值小的元素移到右边
}
A[low] = pivot; //将枢轴值元素置于最终位置
return low;
}
第一个while循环里的代码还可以采用如下形式:
while (low < high && A[high] >= pivot)
--high;
while (low < high && A[low] <= pivot)
++low;
if(low < high)
{
swap(A[low],A[high])
++low;
--high;
}
递归调用快速排序算法的划分操作,如下: |
1 2 3 4 5 6 7 8 9 10 11 12 | void QuickSort( int A[], int low, int high) { if (low < high) //递归跳出条件 { //Partition就是上面的划分操作 int pivot = Partition(A,low,high); //划分 QuickSort(A,low,pivot-1); //左半部分递归 QuickSort(A, pivot + 1, high); //右半部分递归 } } |
时间效率:
快速排序的运行时间与划分是否对称有关,而后者又与具体使用的划分算法有关。快速排序的最坏情况发生在划分时两个区域分别包含n-1和0个元素时,这种最大程度的不对称性多发生在每一层递归上,亦即对应于初始排序表基本有序或基本逆序时,就得到最坏的情况下的复杂度,为O(n^2)。
在快速排序中,并不产生有序子序列,但每一趟排序后都将一个元素置于最终位置。
快速排序优化成最坏O(NlogN):
采用media-of-three选择枢轴值可以比较好的避免划分恶化的情况,另外因为快排函数在函数尾部有两次递归操作,我们可以对其使用尾递归优化。其中第二次递归可以用迭代代替。(如果可以结合其他的排序方法的话,还可以结合堆排序,很多库中的排序算法都是混合排序的,根据数据的情况和规模大小采用不同的排序方法,并把它们组合起来。比如STL中的sort排序算法,结合了插入排序、快速排序、堆排序)
快速排序的非递归实现:
其实就是手动利用栈来存储每次分块快排的起始点,栈非空时循环获取中轴入栈
相关文章推荐
- 书评:《算法之美( Algorithms to Live By )》
- 动易2006序列号破解算法公布
- Ruby实现的矩阵连乘算法
- C#插入法排序算法实例分析
- 超大数据量存储常用数据库分表分库算法总结
- C#数据结构与算法揭秘二
- C#冒泡法排序算法实例分析
- 算法练习之从String.indexOf的模拟实现开始
- C#算法之关于大牛生小牛的问题
- C#实现的算24点游戏算法实例分析
- c语言实现的带通配符匹配算法
- 浅析STL中的常用算法
- 算法之排列算法与组合算法详解
- C++实现一维向量旋转算法
- Ruby实现的合并排序算法
- C#折半插入排序算法实现方法
- 基于C++实现的各种内部排序算法汇总
- C++线性时间的排序算法分析
- C++实现汉诺塔算法经典实例
- PHP实现克鲁斯卡尔算法实例解析