数据结构 ——— 快速排序的时间复杂度以及规避最坏情况的方法

目录

前言

快速排序的时间复杂度

快速排序时间效率最坏的情况

规避快速排序最坏情况的方法

三数取中法

将三数取中放在快速排序算法中(以前后指针版本举例)


前言

在前几章学习了快速排序不同版本的实现,他们的时间效率都是差不多一样的
数据结构 --------- 快速排序算法的实现(前后指针法版本)-CSDN博客
数据结构 --------- 快速排序算法的实现(挖坑法版本)-CSDN博客
数据结构 --------- 快速排序算法的实现(hoare版本)-CSDN博客

接下来要学习的是快速排序的时间复杂度

以及如何规避快速排序中最坏情况(也就是会导致时间效率最低情况)的方法


快速排序的时间复杂度

通过递归分治的思想,每次把 n 都一分为二,分到最后都为 1 时,排序也就完成了

得出快速排序的时间复杂度为(大O渐进表示法):N * longN


快速排序时间效率最坏的情况

当数组有序或者接近有序时,快速排序的时间效率最低

低到时间复杂度为:O(N^2) 的程度

因为每次选择的 key 是最左边的值,那么就拿升序来说

因为升序,所以 key 每次都是最小的值,那么此区间的左边几乎不存在,也就是又要在 n-1 个值中选出 key ,同样是递归分治的思想,但是因为每次排序只能让 key 停留在最终位置

所以要排完整个数组,那么就是一个等差数列,时间复杂度也就是:O(N^2)


规避快速排序最坏情况的方法

三数取中法

方法思维:

选取当前区间中左中右三个值,把它们比较出来,选中间值作为 key

但是不能改变快速排序的整体逻辑,所以选出中间值后,和最左边的值交换,这样既没有改变快速排序本身的逻辑,也规避了数组是有序或者接近有序的情况

方法代码:

复制代码
int GetMidIndex(int* a, int left, int right)
{
	int midi = (left + right) / 2;

	// 找出中间值
	if (a[midi] < a[left])
	{
		if (a[midi] > a[right]) //[right midi left]
		{
			return midi;
		}
		else if (a[right] > a[left]) //[midi left right]
		{
			return left;
		}
		else //[midi right left]
		{
			return right;
		}
	}
	else
	{
		if (a[midi] < a[right]) //[left midi right]
		{
			return midi;
		}
		else if (a[right] < a[left]) //[right left midi]
		{
			return left;
		}
		else //[left right midi]
		{
			return right;
		}
	}
}

注意:是要返回中间值的下标,才能方便和最左边的值交换


将三数取中放在快速排序算法中(以前后指针版本举例)

代码演示:

复制代码
int PartSort_Pointer(int* a, int left, int right)
{
	// 三数取中
	int midi = GetMidIndex(a, left, right);
	Swap(&a[midi], &a[left]);

	int prev = left;
	int cur = prev + 1;
	int keyi = left;

	while (cur <= right)
	{
		if (a[cur] < a[keyi] && ++prev != cur)
		{
			Swap(&a[prev], &a[cur]);
		}

		cur++;
	}

	// 把 key 放在最终位置
	Swap(&a[prev], &a[keyi]);

	return prev;
}

void QuickSort(int* a, int begin, int end)
{
	// 前后指针法
	if (begin >= end)	
	{
		return;
	}

	int key = PartSort_Pointer(a, begin, end);

	// [begin,key-1] key [key+1,end]

	QuickSort(a, begin, key - 1);
	QuickSort(a, key + 1, end);
}

得到中间值的下标后,直接和最左边的值进行交换,然后其他的逻辑都不变

代码验证:

相关推荐
wzdark6 小时前
基于启发式搜索的最优路径规划算法研究4
算法
动词ing6 小时前
【学习笔记】数据结构栈与队列(栈先进后出+队列先进先出+括号匹配+消消乐模型)
数据结构·笔记·学习
l1t6 小时前
用superpi、tinypi、tpi等工具计算圆周率的比较
c语言·算法
a187927218316 小时前
【算法】链表(二):链表上的双指针——变速、异链与定距,和一份路程账本
数据结构·算法·leetcode·链表·go·指针·环形链表
2601_958352908 小时前
还要写 AEC 算法?0 代码 + 6 个引脚,F-18 让通话清晰度提升 300%
人工智能·算法·降噪消回音
happyprince8 小时前
03-regmix-深刻观-哲学与升华
算法
zcmodeltech8 小时前
火电厂模型能演示冷态启动和故障处理吗?——基于STM32与Modbus RTU的集控实训控制系统设计
数据结构·stm32·单片机·嵌入式硬件·能源
一路向阳~负责的男人8 小时前
运动控制算法收录
算法
czt_java8 小时前
5个核心位运算公式
算法
Doubbbbbbble云8 小时前
区间合并问题的常见算法模式与优化思路4
java·数据结构·算法