【交换排序】快速排序
来源:互联网 发布:淘宝信誉刷钻平台 编辑:程序博客网 时间:2024/05/01 12:06
快速排序是由冒泡排序改进而得的。在冒泡排序过程中,只对相邻的两个记录进行比较,因此每次交换两个相邻记录时只能消除一个逆序。如果能通过两个(不相邻)记录的依次交换,消除多个逆序,则会大大加快排序的速度。快速排序方法中的一次交换可能消除多个逆序。
[算法思想]在待排序的n个记录中任取一个记录(通常取第一个记录)作为枢轴(或支点),设其关键字为pivotkey。经过一趟排序后,把所有关键字小于pivotkey的记录交换到前面,把所有关键字大于pivotkey的记录交换到后面,结果将待排序记录分成两个子表,最后将枢轴放置在分界处的位置。然后,分别对左、右子表重复上述过程,直至每一子表只有一个子记录时,排序完成。又是分治的思想,分解,解决,合并。
其中,一趟快速排序的具体做法如下。
1)附设两个指针low和high,初始时分别指向表的下界和上界,设枢轴记录的关键字为pivotkey(第一趟时,low=1;high=L.length;)
2)从表的最右侧位置,依次向左搜索找到第一个关键字小于pivotkey的记录和枢轴记录交换。具体操作是:当low<high时,若high所指的关键字大于等于pivotkey,则向左移动指针high,(执行操作--high);否则将high所指记录与枢轴记录交换。
3)然后再从表的最左侧位置,依次向右搜索找到第一个关键字大于pivotkey的记录和枢轴记录交换。具体操作是:当low<high时,若low所指的关键字小于等于pivotkey,则向右移动指针low(执行操作++low);否则将low所指记录与枢轴记录交换。
4)重复步骤(2)和步骤(3),直到low与high相等为止。此时low或high的位置即为枢轴在此趟排序中的最终位置,原表被分成两个子表。
在上述过程中,记录的交换都是与枢轴之间发生,每次交换都要移动3次记录,可以先将枢轴记录暂存在r[0]的位置上,排序过程中只移动要与枢轴交换的记录,即只做r[low]或r[high]的单向移动,直至一趟排序记录结束后再将枢轴记录移至正确的位置上。
例 已知待排序记录的关键字序列为{49,38,65,97,76,13,27,49},请给出快速排序法进行排序的过程。
每一趟快速排序过程如图(a)所示,整个快速排序的过程如图(b)所示。[算法描述]
int Partition(int L[],int low ,int high) {/*对顺序表L中的子表r[low..high]进行一趟排序,返回枢轴位置*/L[0]=L[low]; /*用子表的第一个记录做枢轴记录*/int pivotkey=L[low]; /*枢轴记录关键字保存在pivotkey中*/while(low < high) /*从表的两端交替地向中间扫描*/{ while(low<high && L[high]>=pivotkey) --high; L[low]=L[high]; while(low<high && L[low]<=pivotkey) ++low; L[high]=L[low];}L[low]=L[0]; /*枢轴记录到位*/return low; } void Qsort(int L[],int low,int high) {/*对顺序表L中的子序列L[low..high]做快速排序*/if(low<high) /*长度大于1*/{ int pivotloc=Partition(L,low,high); /*将L[low..high]一分为二,pivotloc是枢轴位置*/ Qsort(L,low,pivotloc-1); /*对左子表递归排序*/ Qsort(L,pivotloc+1,high); /*对右子表递归排序*/ } } void QuickSort(int L,int n) {Qsort(L,1,n); }
[算法分析]
1)时间复杂度
最好O(nlog2n);最坏O(n^2);平均O(nlog2n);
2)空间复杂度
快速排序是递归的,执行时需要一个栈来存放相应的数据。最大递归调用次数与递归树的深度一致,所以最好情况下的空间复杂度为O(log2n)最坏情况下为O(n).
[完整代码]#include<iostream> using namespace std; int Partition(int L[],int low ,int high) {/*对顺序表L中的子表r[low..high]进行一趟排序,返回枢轴位置*/L[0]=L[low]; /*用子表的第一个记录做枢轴记录*/int pivotkey=L[low]; /*枢轴记录关键字保存在pivotkey中*/while(low < high) /*从表的两端交替地向中间扫描*/{ while(low<high && L[high]>=pivotkey) --high; L[low]=L[high]; while(low<high && L[low]<=pivotkey) ++low; L[high]=L[low];}L[low]=L[0]; /*枢轴记录到位*/return low; } void Qsort(int L[],int low,int high) {/*对顺序表L中的子序列L[low..high]做快速排序*/if(low<high) /*长度大于1*/{ int pivotloc=Partition(L,low,high); /*将L[low..high]一分为二,pivotloc是枢轴位置*/ Qsort(L,low,pivotloc-1); /*对左子表递归排序*/ Qsort(L,pivotloc+1,high); /*对右子表递归排序*/ } } void QuickSort(int L[],int n) {Qsort(L,1,n); } int main() { int ans[9]={0,49,38,65,97,76,13,27,49}; QuickSort(ans,8); for(int i=1;i<=8;i++) cout<<ans[i]<<" "; return 0; }
[运行结果]
附:<啊哈!算法>里快排的实现
#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++;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); /*继续处理右边的,这是一个递归的过程*/return ; } int main() { int i,j; scanf_s("%d",&n); for(i=1;i<=n;i++) {scanf_s("%d",&a[i]); }quicksort(1,n);/*输出排序后的结果*/for(i=1;i<=n;i++){printf("%d ",a[i]);}getchar();return 0; }
- 交换排序--快速排序
- 交换排序:快速排序
- 交换排序-快速排序
- 交换排序-快速排序
- 交换排序------快速排序
- 【交换排序】快速排序
- 交换排序---快速排序
- 交换排序-快速排序
- 交换排序-快速排序
- 交换排序--快速排序
- 交换排序-快速排序
- 交换排序之----快速排序
- 交换排序之快速排序
- 交换排序:快速排序 学习
- 【交换排序】快速排序--Java
- 交换排序—快速排序
- 交换类排序-快速排序
- 交换排序_2.快速排序
- java异常——分析堆栈跟踪元素+使用异常机制的技巧
- ITOO项目实战——如何发布WCF和MVC服务?(一)
- 利用Travis CI 让你的github项目持续构建(Node.js为例)
- 【STL】滤波算法:使用vector容器
- windows网络命令汇总
- 【交换排序】快速排序
- OC语言 实例方法与类方法 & setter与getter & 便利初始化函数与便利构造器 & 属性(一)
- LaTeX 插图片
- js 翻页组件 pagination
- http://blog.csdn.net/xh16319/article/details/8271110
- 黑马程序员—java基础复习—异常
- oracle
- [bzoj3139][HNOI2013]比赛
- 04Redis入门指南笔记(内部编码规则简介)