排序-快速排序以及其复杂度的计算

基本思路:

在一个数组中,找一个数为基准数,将这个数中所有比基准数大的数放在该数的右边,比基准数小的数放在该数的左边。

例如"6 1 2 7 9 3 4 5 10 8"这个数组
以6作为基准数,将比6小的数放在6的组左边,比6大的数放在6的右边
得到:3 1 2 5 4 6 9 7 10 8
可以看出6的左边的数都比6小,而右边的数都比6大,此时6已经归位

具体步骤为:

  1. 先找一个基准数(一般为第一个),然后从右边开始向左找,找到第一个小于基准值的数,然后从左开始找,找到第一个小于基准值的数,然后进行交换,一直到左边和右边相遇时,则将基准数与找到的位置进行交换
  2. 以基准数为分界线,划分为左右2个数组,再以步骤1进行递归
  3. 当递归的数组中无法再继续递归时,循序则结束,此时的数组则已经完成了排序

代码如下:

void QuickSort(int *n, int left, int right)
{
	if (left > right)
		return ;
	int temp = n[left];					//temp中存的数为基准数
	int i = left, j = right;
	int t;
	while (i != j)
	{
		//一定要先从右向左找
		while (i < j && n[j] >= temp)
			j--;
		while (i < j && n[i] <= temp)
			i++;
		if (i < j)
		{
			t = n[i];
			n[i] = n[j];
			n[j] = t;
		}
	}
	n[left] = n[i];
	n[i] = temp;
	QuickSort(n, left, i - 1);			//处理左边的数
	QuickSort(n, i + 1, right);			//处理右边的数
}

注意:
一定要先从开始寻找再从左边开始寻找

在这里插入图片描述

假设当前的数组为 6 1 2 7 9
如果以6为基准数,且从左先开始寻找第一个大于6个数
那么此时找到的数为7,而接着从右向左寻找
当右边的数找到7时,发现和左边找到的数撞上了,那么就会停止寻找
此时基准数6就会和7交换
这时的数组就会变成 7 1 2 6 9,和我们的目标要求是不一致的
而如果从右边开始寻找,那么右边寻找的数会在2的位置停下,
最终是2 与 6交换,得到2 1 6 7 9

空间复杂度:logn
主要是由于递归造成的栈空间的使用,
最好的情况下其树的深度为:log2(n)
空间复杂度为 O(logn)
而最坏的情况下:需要n-1次调用,每2个数都需要交换,此时退化为冒泡排序
空间复杂度为 O(n)
平均时间复杂度为:O(logn)

时间复杂度:O(nlogn)
由于快速排序用到了递归调用,因此计算其时间复杂度也需要用到递归算法计算
递归算法的时间复杂度公式:T[n] = aT[n/b] + f(n)
**

最优情况下时间复杂度
快速排序最优的情况就是每一次取到的元素都刚好平分整个数组
此时的时间复杂度公式则为:T[n] = 2T[n/2] + f(n);T[n/2]为平分后的子数组的时间复杂度,f[n] 为平分这个数组时所花的时间
第一次递归:
T[n] = 2T[n/2] + n;
第二次递归:
令 n = n/2
= 2^2 T[ n/ (2^2) ] + 2n
第三次递归:
令:n = n/(2^2)
= 2^3 T[ n/ (2^3) ] + 3n

第m次递归:
令:n = n/( 2^(m-1) )
= 2^m T[1] + mn

当最后平分的不能再平分时,也就是说把公式一直往下跌倒,到最后得到T[1]时,说明这个公式已经迭代完了(T[1]是常量了)。
得到:T[n/ (2^m) ] = T[1] ===>> n = 2^m ====>> m = logn;
T[n] = 2^m T[1] + mn ;其中m = logn;
T[n] = 2^(logn)T[1]+lognn = n +nlogn
又因为当n >= 2时:nlogn >= n (也就是logn > 1),所以取后面的 nlogn;

综上所述:快速排序最优的情况下时间复杂度为:O( nlogn )

最差情况下时间复杂度
最差的情况就是每一次取到的元素就是数组中最小/最大的,这种情况其实就是冒泡排序了(每一次都排好一个元素的顺序)
此时的时间复杂度为:T[n] = n * (n-1) = n^2 + n;
综上所述:快速排序最差的情况下时间复杂度为:O( n^2 )

平均时间复杂度
快速排序的平均时间复杂度也是:O(nlogn)

参考:
https://blog.csdn.net/not_in_mountain/article/details/77976743

(黄帝!yyds!)

  • 4
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值