一、问题描述
桶排序占用空间大,冒泡排序时间复杂度大。
快速排序既不浪费空间,在时间上也是快一点的。
现在对6,1,2,7,9,3,4,5,10,8这10个数字进行排序。
那么快速排序的第一点就是找一个基准数。
二、思路解析及快速排序
基准数就是一个用来参照的数。为了方便,选择6作为基准数。
1.分别从初始数列两端探测。
先从右向左找一个小于6的数,再从左往右找一个大于6的数,然后交换它们。术语叫哨兵i和哨兵j.
那么第一趟的结果如下:6,1,2,5,9,3,4,7,10,8(交换了7和5的结果)
第二趟结果:6,1,2,5,4,3,9,7,10,8(交换了4和9的结果)
第三趟结果:3,1,2,5,4,6,9,7,10,8(交换了6和3的结果)
上边就是一个大的分队列的结束。这时候是以6为中,左边的都比6小,右边的都比6大。
2.对左边和右边的数列分别进行上边的步骤。
左边:3,1,2,5,4(以3位基准)
第一趟:2,1,3,5,4(交换了2和3的结果)
左边的左边:2,1(以2为基准)
第一趟:1,2
左边的右边:5.4,
第一趟:4,5
所以左边:1,2,3,4,5
右边:9,7,10,8(以9为基准)
第一趟:8,7,10,9(交换10和8的结果)
第一趟:8,7,10,9(交换10和8的结果)
第二趟:8,7,9,10(交换9和10的结果)
右边的左边:8,7(以8为基准)
第一趟:7,8
所以是7,8,9,10
3.所以全部排序是1,2,3,4,5,6,7,8,9,10
三、代码复现
//快速排序
#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){
//当哨兵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);//继续处理右边的,这是一个递归的过程
}
int main(){
int i,j,t;
//读入数据
scanf("%d",&n);
for(i=1;i<=n;i++){
scanf("%d",&a[i]);
}
quicksort(1,n);//快速排序调用
//输出排序后结果
for(i=1;i<=n;i++){
printf("%d ",a[i]);
}
getchar(); getchar();
return 0;
}
四、时间复杂度分析
平均时间复杂度是O(NlogN)
经典的使用二分思想
快速排序之所以快,就是因为相比于冒泡排序,每次交换都是跳跃式的。每次排序的时候设置一个基准点,将小于基准点的全部放在基准点的左边,将大于基准点的全部放于基准点右边。这样每次交换的时候就不会像冒泡排序一样只能在相邻的两个数之间进行交换了,交换的距离就大多了。因此总的比较次数和交换次数就少了,速度自然就提高了。
最差的情况就是依然是两个相邻的数之间进行交换,因此快速排序的最差时间度和冒泡排序是一样的是O(N的平方)。