【排序】快速排序

本文介绍了快速排序的基本思想,由Hoare在1962年提出,通过选择元素key进行分割并递归排序。讨论了快速排序在最好和最坏情况下的效率,并提出了优化方法,如三数取中法选取key和在小规模子区间使用插入排序。还列举了不同的划分区间方式,如hoare版本、挖坑法和前后指针版本。快速排序的时间复杂度为O(N*logN),空间复杂度为O(logN),但它是不稳定的排序算法。
快速排序

快速排序是Hoare于1962年提出的一种二叉树结构的交换排序方法,其基本思想为:在待排序元素序列中任取一个元素key,按照key将该序列分割成两子序列,左子序列中所有元素均小于key,右子序列中所有元素均大于key,然后最左右子序列重复该过程,直到所有元素都排列在相应位置上为止。
在这里插入图片描述
代码1(只在最好的情况下效率高)

int PartSort(int* a, int begin, int end)
{
	int key = begin;
	while (begin < end)
	{
		//end找小
		while (begin < end && a[end] >= a[key])
			--end;

		//begin找大
		while (begin < end && a[begin] <= a[key])
			++begin;

		Swap(&a[begin], &a[end]);
	}
	Swap(&a[key], &a[end]);
	return end;
}

void QuickSort(int* a, int left, int right)
{
	if (left >= right)
		return;

	int div = PartSort(a, left, right);
	QuickSort(a, left, div - 1);
	QuickSort(a, div + 1, right);
}

以上代码,如果每次选的数恰好都是中间数,快排最优;如果序列有序,每次选的数是最大或者最小,快排最坏。

快速排序优化

  1. 三数取中法选key
int GetMidIndex(int* a, int begin, int end)
{
	int mid = begin + ((end - begin) >> 1);
	if (a[begin] < a[mid])
	{
		if (a[mid] < a[end])
			return mid;
		else if (a[begin] > a[end])
			return begin;
		else
			return end;
	}
	else //a[begin] > a[mid]
	{
		if (a[mid] > a[end])
			return mid;
		else if (a[begin] < a[end])
			return begin;
		else
			return end;
	}
}
  1. 递归到小的子区间时,可以考虑使用插入排序
void QuickSort2(int* a, int left, int right)
{
	if (left >= right)
		return;

	//[left, div-1] [div+1, right]
	if (right - left > 10)
	{
		int div = PartSort3(a, left, right);
		QuickSort2(a, left, div - 1);
		QuickSort2(a, div + 1, right);
	}
	else
	{
		InsertSort(a + left, right - left + 1);
	}
}

划分区间的常见方式有:

  1. hoare版本
int PartSort1(int* a, int begin, int end)
{
	//三数取中法选key
	int mid = GetMidIndex(a, begin, end);
	Swap(&a[begin], &a[mid]);
	int key = begin;
	while (begin < end)
	{
		//end找小
		while (begin < end && a[end] >= a[key])
			--end;

		//begin找大
		while (begin < end && a[begin] <= a[key])
			++begin;

		Swap(&a[begin], &a[end]);
	}
	Swap(&a[key], &a[end]);
	return end;
}
  1. 挖坑法
int PartSort2(int*a, int begin, int end)
{
	int tmp = a[begin];
	while (begin < end)
	{
		//找小,填到左边的坑
		while (begin < end && a[end] >= tmp) //必须有等于,否则可能会陷入死循环
			--end;

		a[begin] = a[end];
		//找大,填到右边的坑
		while (begin < end && a[begin] <= tmp)
			++begin;

		a[end] = a[begin];
	}

	a[begin] = tmp;
}
  1. 前后指针版本
int PartSort3(int*a, int begin, int end)
{
	int key = begin;
	int prev = begin;
	int cur = begin + 1;
	while (cur <= end)
	{
		if (a[cur] < a[key] && ++prev != cur)
		{
			Swap(&a[prev], &a[cur]);
		}
		++cur;
	}
	Swap(&a[key], &a[prev]);
	return prev;
}

快速排序的特性总结:

  1. 快速排序整体的综合性能和使用场景都是比较好的,所以才敢叫快速排序
  2. 时间复杂度:O(N*logN)
  3. 空间复杂度:O(logN)
  4. 稳定性:不稳定
基于可靠性评估序贯蒙特卡洛模拟法的配电网可靠性评估研究(Matlab代码实现)内容概要:本文围绕“基于可靠性评估序贯蒙特卡洛模拟法的配电网可靠性评估研究”,介绍了利用Matlab代码实现配电网可靠性的仿真分析方法。重点采用序贯蒙特卡洛模拟法对配电网进行长时间段的状态抽样与统计,通过模拟系统元件的故障与修复过程,评估配电网的关键可靠性指标,如系统停电频率、停电持续时间、负荷点可靠性等。该方法能够有效处理复杂网络结构与设备时序特性,提升评估精度,适用于含分布式电源、电动汽车等新型负荷接入的现代配电网。文中提供了完整的Matlab实现代码与案例分析,便于复现和扩展应用。; 适合人群:具备电力系统基础知识和Matlab编程能力的高校研究生、科研人员及电力行业技术人员,尤其适合从事配电网规划、运行与可靠性分析相关工作的人员; 使用场景及目标:①掌握序贯蒙特卡洛模拟法在电力系统可靠性评估中的基本原理与实现流程;②学习如何通过Matlab构建配电网仿真模型并进行状态转移模拟;③应用于含新能源接入的复杂配电网可靠性定量评估与优化设计; 阅读建议:建议结合文中提供的Matlab代码逐段调试运行,理解状态抽样、故障判断、修复逻辑及指标统计的具体实现方式,同时可扩展至不同网络结构或加入更多不确定性因素进行深化研究。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值