算法笔记--快速排序

简介: 快速排序是交换排序的一种,算法效率高,需要额外的辅助空间 1. 算法思想           从待排序序列中选取一个元素,以其值作为中间值,把比其小的元素放到左边,比起大的元素放到右边;然后递归地对左、右部分排序,直至每一部分元素个数为1,整个序列有序。

快速排序是交换排序的一种,算法效率高,需要额外的辅助空间


1. 算法思想

          从待排序序列中选取一个元素,以其值作为中间值,把比其小的元素放到左边,比起大的元素放到右边;然后递归地对左、右部分排序,直至每一部分元素个数为1,整个序列有序。

2. 时间复杂度

          用递归树的思想,每次划分操作的元素总数都是n,因此每次划分的时间复杂度都是O(n),接下来只需考虑划分次数:

          最好情况 O(nlogn):每次都将序列等分为两部分,因此划分次数为logn

          最坏情况 O(n^2):每次都有一部分只分出一个元素,因此划分次数为n

3. 空间复杂度 O(logn)

          递归调用,考虑递归栈的空间消耗

4. 稳定性

          不稳定。划分时要跨中轴交换元素,不相邻交换不稳定

5. 代码实现(C语言)

          划分时有两类方法:

          一种是挖坑法,将A[0]作为中轴值保存到value中,A[0]空出一个坑;先从后往前遍历,遇到不大于value的数A[j],则将A[j]填到A[0]中,A[j]空出一个坑;再从前往后遍历,遇到不小于value的数A[i],则将A[i]填到A[j]中,A[i]空出一个坑。如此循环,直至i、j重合,将value填到这个坑中。

          另一种是交换法,同时从后往前找小于value的A[j],从前往后找不小于value的A[i],然后交换A[i]、A[j];循环直至i、j重合。这种方法在保证重合处的值A[i]小于value,因此递归划分时前半部分要包括A[i]。但是将等于value的值都放到后半部分了,对于有大量相同元素的序列,会因为划分不均匀而导致效率偏低,因此整体看来稍逊一筹。

          为了使中轴值取得更有效,这里采用取序列首、尾、中间元素的中值的方法,代码如下:

int Adjust(int *A, int low, int high)
{
	int ind;
	int mid = (low + high) / 2;
	int value = A[low];

	if (A[low] <= A[mid])
	{
		ind = A[mid] <= A[high] ?
			mid : (A[low] <= A[high] ? high : low);
	}
	else
	{
		ind = A[low] <= A[high] ?
			mid : (A[mid] <= A[high] ? high : mid);
	}

	if (ind != low)
	{
		value = A[ind];
		A[ind] = A[low];
		A[low] = value;
	}

	return value;
}
          另外为了接口一致,增加了一个入口函数:

void QuickSort(int *A, int n)
{
	QSort(A, 0, n - 1);
}

          接下来是快排函数,首先是挖坑版:

void QSort(int *A, int low, int high)
{
	int i, j, value;

	if (low >= high)
	{
		return;
	}

	i = low;
	j = high;
	value = Adjust(A, low, high);

	while(i < j)
	{			
		while (i < j && A[j] > value)
		{
			--j;
		}
		
		if (i < j)
		{
			A[i++] = A[j];
		}

		while (i < j && A[i] < value)
		{
			++i;
		}

		if (i < j)
		{
			A[j--] = A[i];
		}
	}
	
	A[i] = value;
	QSort(A, low, i - 1);
	QSort(A, i + 1, high);
}

 
          再看一下交换版: 

void QSort(int *A, int low, int high)
{
	int i, j;
	int tmp, value;

	if (low >= high)
	{
		return;
	}

	i = low;
	j = high;
	value = Adjust(A, low, high);

	while (i < j)
	{
		while (i < j && A[j] >= value)
		{
			--j;
		}

		while (i < j && A[i] < value)
		{
			++i;
		}

		if (i < j)
		{
			tmp = A[i];
			A[i] = A[j];
			A[j] = tmp;
		}
	}

	QSort(A, low, i);
	QSort(A, i + 1, high);
}

目录
相关文章
|
27天前
|
搜索推荐 C语言
【排序算法】快速排序升级版--三路快排详解 + 实现(c语言)
本文介绍了快速排序的升级版——三路快排。传统快速排序在处理大量相同元素时效率较低,而三路快排通过将数组分为三部分(小于、等于、大于基准值)来优化这一问题。文章详细讲解了三路快排的实现步骤,并提供了完整的代码示例。
50 4
|
2月前
|
算法
【❤️算法笔记❤️】-每日一刷-19、删除链表的倒数第 N个结点
【❤️算法笔记❤️】-每日一刷-19、删除链表的倒数第 N个结点
69 1
|
2月前
|
算法 索引
❤️算法笔记❤️-(每日一刷-141、环形链表)
❤️算法笔记❤️-(每日一刷-141、环形链表)
50 0
|
2月前
|
算法
【❤️算法笔记❤️】-(每日一刷-876、单链表的中点)
【❤️算法笔记❤️】-(每日一刷-876、单链表的中点)
44 0
|
2月前
|
算法
【❤️算法笔记❤️】-每日一刷-23、合并 K 个升序链表
【❤️算法笔记❤️】-每日一刷-23、合并 K 个升序链表
32 0
|
2月前
|
算法 API 计算机视觉
人脸识别笔记(一):通过yuface调包(参数量54K更快更小更准的算法) 来实现人脸识别
本文介绍了YuNet系列人脸检测算法的优化和使用,包括YuNet-s和YuNet-n,以及通过yuface库和onnx在不同场景下实现人脸检测的方法。
63 1
|
2月前
|
JSON 算法 数据可视化
测试专项笔记(一): 通过算法能力接口返回的检测结果完成相关指标的计算(目标检测)
这篇文章是关于如何通过算法接口返回的目标检测结果来计算性能指标的笔记。它涵盖了任务描述、指标分析(包括TP、FP、FN、TN、精准率和召回率),接口处理,数据集处理,以及如何使用实用工具进行文件操作和数据可视化。文章还提供了一些Python代码示例,用于处理图像文件、转换数据格式以及计算目标检测的性能指标。
70 0
测试专项笔记(一): 通过算法能力接口返回的检测结果完成相关指标的计算(目标检测)
|
2月前
|
算法
❤️算法笔记❤️-(每日一刷-160、相交链表)
❤️算法笔记❤️-(每日一刷-160、相交链表)
18 1
|
2月前
|
数据可视化 搜索推荐 Python
Leecode 刷题笔记之可视化六大排序算法:冒泡、快速、归并、插入、选择、桶排序
这篇文章是关于LeetCode刷题笔记,主要介绍了六大排序算法(冒泡、快速、归并、插入、选择、桶排序)的Python实现及其可视化过程。
17 0
|
2月前
|
算法
❤️算法笔记❤️-(每日一刷-83、删除排序链表中的重复项)
❤️算法笔记❤️-(每日一刷-83、删除排序链表中的重复项)
32 0