快速排序
来源:互联网 发布:淘宝代理商怎么做 编辑:程序博客网 时间:2024/06/03 16:02
快速排序演示链接
排序思想
通过一趟排序,将待排序记录分割成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键字小,再分别对这两部分记录进行下一趟排序,以达到整个序列有序。
排序过程
设待排序的记录序列是R[s…t] ,在记录序列中任取一个记录(一般取R[s])作为参照(又称为基准或枢轴),以R[s].key为基准重新排列其余的所有记录,方法是:
◆所有关键字比基准小的放R[s]之前;
◆ 所有关键字比基准大的放R[s]之后。
以R[s].key最后所在位置i作为分界,将序列R[s…t]分割成两个子序列,称为一趟快速排序。
(1)一趟快速排序方法
排序思想
从序列的两端交替扫描各个记录,将关键字小于基准关键字的记录依次放置到序列的前边;而将关键字大于基准关键字的记录从序列的最后端起,依次放置到序列的后边,直到扫描完所有的记录。
设置指针low,high,初值为第1个和最后一个记录的位置。
设两个变量i,j,初始时令i=low,j=high,以R[low].key作为基准(将R[low]保存在tmp中) 。
① 从j所指位置向前搜索:将tmp.key与R[j].key进行比较:
◆ 若tmp.key≤R[j].key :令j=j-1,然后继续进行比较, 直到i=j或tmp.key>R[j].key为止;
◆ 若tmp.key>R[j].key :R[i]=R[j],腾空R[j]的位置, 且令i=i+1;
② 从i所指位置起向后搜索:将tmp.key与R[i].key进行比较:
◆ 若tmp.key≥R[i].key :令i=i+1,然后继续进行比较, 直到i=j或tmp.key<R[i].key为止;
◆ 若tmp.key<R[i].key :R[j]=R[i],腾空R[i]的位置, 且令j=j-1;
重复①、②,直至i=j为止,i就是tmp(基准)所应放置的位置。
一趟排序示例
设有6个待排序的记录,关键字分别为29, 38, 22, 45, 23, 67,一趟快速排序的过程如图1所示。
算法实现
int quick_one_pass(int value[], int low, int high){ int i=low, j=high; tmp = value[i]; /* tmp作为临时单元和哨兵 */ do { while(tmp<=value[j] && j>i) j--; if(j>i) { value[i] = value[j]; i++; } while(tmp>=value[i] && j>i) i++; if(j>i) { value[j] = value[i]; j--; } }while(i!=j); /* i=j时退出扫描 */ value[i] = tmp; return(i);}
(2)快速排序算法实现
当进行一趟快速排序后,采用同样方法分别对两个子序列快速排序,直到子序列记录个为1为止。
① 递归算法
void quick_Sort(int value[], int low, int high){ int k; if(low<high) /* 序列分为两部分后分别对每个子序列排序 */ { k = quick_one_pass(value, low, high); quick_Sort(value, low, k-1); quick_Sort(value, k+1, high); }}
② 非递归算法
#define MAX_STACK 100void quick_Sort(int value[], int low, int high){ int k, stack[MAX_STACK], top=0; do { while(low<high) { k=quick_one_pass(value, low, high); stack[++top]=high; stack[++top]=k+1; /* 第二个子序列的上,下界分别入栈 */ high=k-1; } if(top!=0) { low=stack[top--]; high=stack[top--]; } }while(top!=0 && low<high);}
算法分析
快速排序的主要时间是花费在划分上,对长度为k的记录序列进行划分时关键字的比较次数是k-1 。设长度为n的记录序列进行排序的比较次数为C(n),则C(n)=n-1+C(k)+C(n-k-1) 。
◆ 最好情况:每次划分得到的子序列大致相等,则
C(n)≤n+2×C(n/2)+C(n-k-1)
≤n+2×[n/2+ 2×C((n/2)/2)≤ 2n+4×C(n/4)
≤…
≤h×n+2h×C(n/2h) ,当n/2h=1时排序结束。
即C(n)≤n×㏒2n+n×C(1) ,C(1)看成常数因子,
即C(n)≤O(n×㏒2n) ;
◆ 最坏情况:每次划分得到的子序列中有一个为空,另一个子序列的长度为n-1。即每次划分所选择的基准是当前待排序序列中的最小(或最大)关键字。
比较次数:即C(n)=O(n2)
◆ 一般情况: 对n个记录进行快速排序所需的时间T(n)组成是:
① 对n个记录进行一趟划分所需的时间是:n×C ,C是常数;
② 对所得到的两个子序列进行快速排序的时间:
Tavg(n)=C(n)+Tavg(k-1)+Tavg(n-k) …… ⑴
若记录是随机排列的,k取值在1~n之间的概率相同,则:
只有1个记录的排序时间是一个常数,
∴ 快速排序的平均时间复杂度是:T(n)=O(n㏒2n)
从所需要的附加空间来看,快速排序算法是递归调用,系统内用堆栈保存递归参数,当每次划分比较均匀时,栈的最大深度为[㏒2n]+1 。
∴ 快速排序的空间复杂度是:S(n)=O(㏒2n)
从排序的稳定性来看,快速排序是不稳定的。
- 快速排序
- 快速排序
- 快速排序
- 快速排序!
- 快速排序
- 快速排序
- 快速排序
- 快速排序
- 快速排序
- 快速排序
- 快速排序
- 快速排序
- 快速排序
- 快速排序
- 快速排序
- 快速排序
- 快速排序
- 快速排序
- 窗口分割及消息响应
- 一篇关于串口的经典文章
- hibernate中一对多关系
- 写程序之余,笑一笑----程序员的一些幽默
- C#学习笔记
- 快速排序
- 超级幂分析
- Oracle Process Architecture - Oracle 进程结构篇2
- 呵呵,还是去试下吧。
- linux 学习url-very important
- Andengine 中可变文本 Text 使用中遇到的问题
- WF4.0 基础篇 (六) 数据的传递 Arguments 参数
- 电脑保护色rgb 199 237 204
- jsp乱码问题,求解