序言
一般提到快速排序,都会说是一种高级的插入排序,但是很多网上的方法虽然容易理解,但是很难看出和基本插入排序的共同点,最近看了看《算法导论》,对快速排序有了一些新的理解。
算法思路
基本思路:
和网上大部分流传的方法差不多,找到轴值(最终用start标记),并根据轴值位置将数组分为两半,递归的去排序。
这里主要强调的是找轴值的方法。
举个栗子
通过p指针的移动来实现p左边的数组都已经保证start左边的都小于轴值,start右边到p为止都大于轴值,移动p到end,就保证了待排序数组都满足条件start左边的都小于轴值,start右边到p为止都大于轴值,p的移动就像插入排序那样,是不是一下子感觉好理解了。
以第一轮找轴值为例:
一. 初始状态,轴值为7
数组 | 7 | 9 | 6 | 10 | 4 |
---|---|---|---|---|---|
start指针 | start | ||||
p指针 | p | ||||
end指针 | end | ||||
k指针 | k |
二. 因为9>7,所以只需要将p++
数组 | 7 | 9 | 6 | 10 | 4 |
---|---|---|---|---|---|
start指针 | start | ||||
p指针 | p | ||||
end指针 | end | ||||
k指针 | k |
三. 因为6<7,所以需要将data[start]和data[p]进行交换后在分别对start和p进行加1,且因为待交换的两个数里面有轴值,所以k也会改变.
数组 | 6 | 9 | 7 | 10 | 4 |
---|---|---|---|---|---|
start指针 | start | ||||
p指针 | p | ||||
end指针 | end | ||||
k指针 | k |
四. 因为10>7,所以p++
数组 | 6 | 9 | 7 | 10 | 4 |
---|---|---|---|---|---|
start指针 | start | ||||
p指针 | p | ||||
end指针 | end | ||||
k指针 | k |
五. 因为4<7,所以需要将data[start]和data[p]进行交换后在分别对start和p进行加1,因为待交换的两个数里面无轴值,所以k不改变
数组 | 6 | 4 | 7 | 10 | 9 | |
---|---|---|---|---|---|---|
start指针 | start | |||||
p指针 | p | |||||
end指针 | end | |||||
k指针 | k |
剩下的同理,将数组按照轴值分为两份,在递归的对两份数组进行排序。
复杂度分析
又到了紧(ku)张(zao)刺(fa)激(wei)的复杂度分析环节了。
最坏时间复杂度:(轴值都在边界的情况,如待排序数组为{1,2,3,4,5},用快排从小到大排序)
O(n^2)
这个方法可以解决吗?暂时不行,但是可以用随机数来找轴值,这样就可以避免别人知道你用的快排,用一堆完全有序的数叫你排序来恶心你。可以关注我哦,具体方法我以后再讲。
平均时间复杂度:
快排比较神奇的地方来了,因为平均情况时间复杂度和最好时间复杂度是一样的,都是O(nlogn),具体证明方法可以画递归树去求证,你会发现无论是轴值取在1/10处还是1/2处,其实对算法的运行时间影响比较小,几乎没有影响,很神奇是不是。
代码
#include<stdio.h>
void Quick_sort(int start, int end, int* data);
int found(int start, int end, int* data);
void swap(int a, int b, int* data);
int main() {
int data[] = { 7,9,6,10,4 };
Quick_sort(0, 4, data);
for (int i = 0; i < 5; i++) {
printf("%d ", data[i]);
}
return 0;
}
void Quick_sort(int start,int end,int *data) {
int important;
if (start >= end)
return;
important = found(start,end,data);
Quick_sort(start,important-1,data);
Quick_sort(important+1,end,data);
}
int found(int start, int end, int* data) {
int p = start + 1,temp,x,k=start;//start作为中值
x = data[start];
while (p <= end) {
if (data[p] < x) {
if (data[start] == x) k = p;//标记轴值的下标
swap(p, start, data);
start++;
}
p++;
}
swap(k, start, data);
return start;
}
void swap(int a,int b,int *data) {
int temp;
temp = data[a];
data[a] = data[b];//交换datap[p]和data[start]
data[b] = temp;
}