声明
相关知识
1.快速排序的平均时间复杂度为Θ(nlogn)。
2.采用了分治策略。
思想
①先从数列中选取一个数作为基准数;
②分区过程:将(>基准数)的数放到其右边;将(≤基准数)的数放到其左边;
③再对基准数的左右区间重复第二步,直到各区间只有一个数为止。
分析
以数组(arr)为例:
序号 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
---|---|---|---|---|---|---|---|---|---|---|
值 | 9 | 5 | 1 | 2 | 3 | 4 | 6 | 7 | 0 | 8 |
①默认将arr[0]=9 作为基准数,另外保存起来:temp=arr[0]。这样,可以把arr[0]位置当作空。
②分区过程:
temp=9
序号 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
---|---|---|---|---|---|---|---|---|---|---|
值 | 5 | 1 | 2 | 3 | 4 | 6 | 7 | 0 | 8 |
(1) 参考上图。先从后向前遍历,找到第一个小于9的数为止,但要注意:最多只能遍历到空位置后面一位(arr[9]~~arr[1])。 因arr[9]=8, 此时将arr[9]->arr[0]。arr[9]的值已经 复制到了arr[0]中,故此时将arr[9]视为空。
temp=9
序号 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
---|---|---|---|---|---|---|---|---|---|---|
值 | 8 | 5 | 1 | 2 | 3 | 4 | 6 | 7 | 0 |
(2)参考上图。再从前向后遍历,找到第一个大于9的数为止,遍历范围为(arr[0]~~arr[8]即空位前)。 因没找到,便证明arr[9]位置左边的数都小于temp=9。所以将temp->arr[9],第一次分区结束。
(3)将arr[9]的左右分区分别重复(1)(2)操作,直到每个分区只有一个元素位置为止。(本例子右边部分没有了,所以在执行前要判断一下)
左边分区:
序号 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
---|---|---|---|---|---|---|---|---|---|
值 | 8 | 5 | 1 | 2 | 3 | 4 | 6 | 7 | 0 |
#include<iostream.h>
int Adjust(int arr[],int head,int tail)//参数head、tail分别为数组的第一和最后一个数的下标
{
int temp=arr[head];//基准数
while(head<tail)
{
//从后向前遍历,找到第一个小于基准值的数。
while(head<tail&&arr[tail]>temp)
--tail;
if(head<tail)
{
arr[head]=arr[tail];
++head;
}
//从前向后遍历,找到第一个大于基准值的数。
while(head<tail&&arr[head]<temp)
++head;
if(head<tail)
{
arr[tail]=arr[head];
--tail;
}
}
//结束的条件是head=tail,即遍历结束了,所有元素都被查看了一遍
arr[head]=temp;//将基准值赋给相应位置
return head;//返回基准值的位置
}
void Quickly_sort(int arr[],int head,int tail)
{
if(head<tail)//只有当分区内的元素个数>1个是,才继续下面操作。
{
int boundary=Adjust(arr,head,tail);
Quickly_sort(arr,head,boundary-1);
Quickly_sort(arr,boundary+1,tail);
}
}
void main()
{
int num[10]={9,5,1,2,3,4,6,7,0,8};
Quickly_sort(num,0,9);
for(int i=0;i<10;i++)
cout<<num[i]<<" ";
}