快速排序(递归版)
来源:互联网 发布:免费标签打印软件 编辑:程序博客网 时间:2024/06/07 10:42
快速排序是最经典的排序算法,它用途广泛,效率很高,也经常被拿来检验coder的基本功底。
此篇作为快排的学习笔记。
快排的基本思想
快速排序是典型的分治算法,理解了快排的思想,很容易写出递归版的代码。
快排分以下三个步骤.
- Choose a pivot value. 选择一个元素作为轴(pivot),这里我一般选择数组的中间值作为轴。
- Partition.将当前数组划分。划分遵循这样的规则,所有小于轴的元素,放在轴的左边,大于轴的元素,放在轴的右边,等于轴的元素放在哪边都可以。这样相当于将一个数组划分成了两个部分。
- Sort both parts。对划分后的数组不断重复1,2过程,直到数组有序。
这样为什么可以得到有序的数组呢?
每次划分操作都将数组划分为两部分。
左半部分的任何元素都将<=右半部分的任何元素。
所以递归的重复以上过程,最终得到的数组一定是有序的。
下面给出这个递归过程的伪代码
QuickSort(array,low,high) if(low < high) : //满足递归条件 pivotIndex = Partition(array,low,high) QuickSort(array,low,pivotIndex - 1) QuickSort(array,pivotIndex + 1,high);
这个思想十分简单明了,难点在于如何编写Partiton()
函数。
实际上,也并不难理解
Partition的编写与过程分析
我们重述一下Partation函数的作用。
划分:在数组中挑选一个轴作为划分标准,所有小于轴的元素放到轴的左边,大于轴的元素放到轴的右边。然后Partation函数会返回这个轴最终的位置(同时也是轴在最终有序数列中的位置)
WiKi的伪代码:
partition(A, lo, hi) pivotIndex := choosePivot(A, lo, hi) pivotValue := A[pivotIndex] // put the chosen pivot at A[hi] swap A[pivotIndex] and A[hi] storeIndex := lo // Compare remaining array elements against pivotValue = A[hi] for currIndex from lo to hi−1, inclusive if A[currIndex] < pivotValue swap A[currIndex] and A[storeIndex] storeIndex := storeIndex + 1 swap A[storeIndex] and A[hi] // Move pivot to its final place return storeIndex
分析 : 上述伪代码中有两个重要的变量。
- storeIndex : 这个变量指示的是pivot经过一次划分后的最终坐标位置,初始化为low。
- currIndex : 顾名思义指示的是当前的循环位置
Q:为什么要将pivot和A[high]预先交换?
A : 首先pivotIndex的选取是没有什么规定的,所以这里以一个函数choosePivot
代替。为了实现算法,我们必须将除了pivot之外的所有元素与pivot比较,如果pivot是A[high]那么循环写起来会很方便,否则就将pivot与A[high]交换。
Q:for循环的作用是什么?
A:循环体内依次遍历除pivot的所有元素,将所有小于pivot的元素放到pivot最终位置(storeIndex)的左边。(详细用图示解释)
Q:为何循环完毕后还要交换一次?
A:循环完毕只是将所有小于pivot的元素放到了storeIndex(pivot最终位置)的左边,而pivot还是在A[high]位置上,因此要交换。
值得注意的是,这里不可以写成swap(A[storeIndex],pivot)
,虽然还是把pivot放到了最终位置上,但是这样做并没有改变A[high]的值(A[high]还是pivot),所以最后一步是必不可少的。
下面给出一个图示详细说明一下 :
青绿色表示所有小于pivot的元素
(3 < pivot,因为curr和store开始指向同一元素,3和3自身交换,s++,c++)
(7 > pivot,c++)
(4 < pivot,4 和 7 交换,c++,s++)
(2 < pivot,2 和 8 交换,c++, s++)
(1 < pivot,1 和 7 交换,c++,s++)
(循环结束)
(最后,swap A[storeIndex] and A[hi]
)
C++代码
int QuickSort(int array[],int low,int high){ if(low < high){ int pivotIndex = Partition(array,low,high);//如果可以划分 QuickSort(array,low,pivotIndex - 1); QuickSort(array,pivotIndex + 1,high); }}
int Partition(int array[],int low,int high){ int pivotIndex = (low + high) / 2; int pivot = array[pivotIndex]; int storeIndex = low;//pivot所在的最终位置 //put the chosen pivot at array[high] swap(array[pivotIndex],array[high]); //put the chosen pivot at array[high] for(int currIndex = low ; currIndex < high ; ++currIndex){ if(array[currIndex] <= pivot){//也可以写<= swap(array[currIndex],array[storeIndex]); storeIndex++; } } swap(array[storeIndex],array[high]);//move pivot to its final position //you can never write swap(array[storeIndex],pivot] //cause if you use this form,you can not change the value of array[high] //that's wrong return storeIndex;}
- 快速排序(递归版)
- 快速排序【递归版】
- 递归版快速排序
- 快速排序(递归)
- 快速排序(递归)
- 快速排序(递归)
- 快速排序(递归调用版)
- 排序--递归排序(快速排序)
- 快速排序(递归和非递归)
- 快速排序(递归和非递归)
- 快速排序实现(递归+非递归)
- 快速排序(递归+非递归)
- 快速排序(递归版本)
- 快速排序(非递归)
- 快速排序(递归版本)
- 快速排序(递归实现)
- 快速排序(递归算法)
- 快速排序算法(递归)
- dialog
- 杨辉三角
- WWDC总结:开发者需要知道的iOS 9 SDK新特性
- 百度地图显示空白(只有格子)的解决方法
- 制作U盘启动 CDLinux--破解路由器必备工具
- 快速排序(递归版)
- Android 中的拿来主义(编译,反编译,AXMLPrinter2,smali,baksmali)!
- 彻底解决Ubuntu 14.04 重启后DNS配置丢失的问题
- centos下nginx + php 安装及配置
- leetcode题目难度及面试频率
- 解析Qt中QThread使用方法
- mysql常用汇总
- 多对多 hibernate映射
- LintCode Merge Sorted ArrayII 合并排序数组 II