快速排序(参考《算法导论》,核心代码只有18行)

序言

一般提到快速排序,都会说是一种高级的插入排序,但是很多网上的方法虽然容易理解,但是很难看出和基本插入排序的共同点,最近看了看《算法导论》,对快速排序有了一些新的理解。

算法思路

基本思路:
和网上大部分流传的方法差不多,找到轴值(最终用start标记),并根据轴值位置将数组分为两半,递归的去排序。

这里主要强调的是找轴值的方法。

举个栗子

通过p指针的移动来实现p左边的数组都已经保证start左边的都小于轴值,start右边到p为止都大于轴值,移动p到end,就保证了待排序数组都满足条件start左边的都小于轴值,start右边到p为止都大于轴值,p的移动就像插入排序那样,是不是一下子感觉好理解了。

在这里插入图片描述

以第一轮找轴值为例:
一. 初始状态,轴值为7

数组796104
start指针start
p指针p
end指针end
k指针k

二. 因为9>7,所以只需要将p++

数组796104
start指针start
p指针p
end指针end
k指针k

三. 因为6<7,所以需要将data[start]和data[p]进行交换后在分别对start和p进行加1,且因为待交换的两个数里面有轴值,所以k也会改变.

数组697104
start指针start
p指针p
end指针end
k指针k

四. 因为10>7,所以p++

数组697104
start指针start
p指针p
end指针end
k指针k

五. 因为4<7,所以需要将data[start]和data[p]进行交换后在分别对start和p进行加1,因为待交换的两个数里面无轴值,所以k不改变

数组647109
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;
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值