快排(六大排序)

快速排序

快速排序是Hoare于1962年提出的一种二叉树结构的交换排序方法,其基本思想为:任取待排序元素序列中的某元素作为基准值,按照该排序码将待排序集合分割成两子序列,左子序列中所有元素均小于基准值,右子序列中所有元素均大于基准值,然后最左右子序列重复该过程,直到所有元素都排列在相应位置上为止。

上述为快速排序递归实现的主框架,发现与二叉树前序遍历规则非常像,

我们在写递归框架时可想想二叉树前序遍历规则即可快速写出来,后序只需分析如何按照基准值来对区间中数据进行划分的方式即可。

此动图演示的为hoare的版本标记点在最右侧为P,因此需要让左面的L先走

在代码实现中,我们将左侧为标记P,所以让右侧先走

将区间按照基准值划分为左右两半部分的常见方式有:

1. hoare版本

2. 挖坑法

3. 前后指针版本(用指针cur和prev裹挟着比key大的值向后移动)

快速排序优化

1. 三数取中法选key
2. 递归到小的子区间时,可以考虑使用插入排序

代码实现:

cs 复制代码
// 时间复杂度:O(N*logN)   
// 什么情况快排最坏:有序/接近有序 ->O(N^2)
// 但是如果加上随机选key或者三数取中选key,最坏情况不会出现,所以这里不看最坏
// 小区间优化
// 面试让你手撕快排,不要管三数取中和小区间优化
// Hoare
void QuickSort(int* a, int left, int right)
{
	if (left >= right)
		return;
	//小区间优化
	if (right - left + 1 < 10)
	{//是a+left
		InsertSort(a+left, right - left + 1);
	}
	else
	{
		// 100 200,注意的是left不一定是0
		// 选[left, right]区间中的随机数做key
		//int randi = rand() % (right - left + 1);
		//randi += left;
		//Swap(&a[left], &a[randi]);

		int mid = MidIndex(a, left, right);
		//交换
		Swap( &a[left], &a[mid]);
		int keyi = left;

		int begin = left;
		int end = right;
		while (left < right)
		{
			//右面先走,找比key小的值,确保最后值比key小
			while (left < right && a[right] >= a[keyi])
			{
				--right;
			}
			while (left < right && a[left] <= a[keyi])
			{
				++left;
			}
			Swap(&a[left], &a[right]);
		}
		Swap(&a[keyi], &a[right]);
		//千万别忘了
		keyi = right;

		//[begin  keyi-1] keyi [keyi+1    end]
		QuickSort(a, begin, keyi - 1);
		QuickSort(a, keyi + 1, end);
	}
}

void QuickSort2(int* a, int left, int right)
{
	if (left >= right)
		return;
	//小区间优化
	if (right - left + 1 < 10)
	{//是a+left
		InsertSort(a + left, right - left + 1);
	}
	else
	{
		int mid = MidIndex(a, left, right);
		//交换
		Swap(&a[mid], &a[left]);
		int keyi = left;
        //prev cur
		int cur = left + 1;
		int prev = left;
		while (cur <= right)
		{
			if (a[cur] < a[keyi])
			{
				++prev;
				Swap(&a[cur], &a[prev]);
			}
			++cur;
		}
		Swap(&a[keyi], &a[prev]);
		keyi = prev;

		//[left  keyi-1] keyi [keyi+1    right]
		QuickSort2(a, left, keyi - 1);
		QuickSort2(a, keyi + 1, right);
	}
}


#include"Stack.h"
void QuickSortNor(int* a, int left, int right)
{
	ST st;
	STInit(&st);
	//先进右,后进左
	STPush(&st,right);
	STPush(&st,left);

	while (!STEmpty(&st))
	{
		int begin = STTop(&st);
		STPop(&st);

		int end = STTop(&st);
		STPop(&st);
		//一趟
		int keyi = begin;
		int cur = begin + 1;
		int prev = begin;
		while (cur <= end)
		{
			if (a[cur] < a[keyi])
			{
				++prev;
				Swap(&a[cur], &a[prev]);
			}
			++cur;
		}
		Swap(&a[keyi], &a[prev]);
		keyi = prev;
		//是begin不是0
		//[begin  keyi-1] keyi [keyi+1  end]  先入右面,再入左面
		if (keyi + 1 < end)
		{
			STPush(&st, end);
			STPush(&st, keyi + 1);
		}

		if (begin < keyi - 1)
		{
			STPush(&st, keyi - 1);
			STPush(&st, begin);
		}
	}

	STDestroy(&st);
}

这个博客如果对你有帮助,给博主一个免费的点赞就是最大的帮助❤

欢迎各位点赞,收藏和关注哦❤

如果有疑问或有不同见解,欢迎在评论区留言哦❤

后续我会一直分享双一流211西北大学软件(C,数据结构,C++,Linux,MySQL)的学习干货以及重要代码的分享

相关推荐
liulilittle25 分钟前
IP校验和算法:从网络协议到SIMD深度优化
网络·c++·网络协议·tcp/ip·算法·ip·通信
Want5951 小时前
C/C++圣诞树①
c语言·开发语言·c++
bkspiderx2 小时前
C++经典的数据结构与算法之经典算法思想:贪心算法(Greedy)
数据结构·c++·算法·贪心算法
l1t3 小时前
轻量级XML读写库Mini-XML的编译和使用
xml·c语言·解析器
中华小当家呐3 小时前
算法之常见八大排序
数据结构·算法·排序算法
沐怡旸4 小时前
【算法--链表】114.二叉树展开为链表--通俗讲解
算法·面试
tju新生代魔迷4 小时前
数据结构:双向链表
数据结构·链表
一只懒洋洋4 小时前
K-meas 聚类、KNN算法、决策树、随机森林
算法·决策树·聚类
小莞尔4 小时前
【51单片机】【protues仿真】基于51单片机停车场的车位管理系统
c语言·开发语言·单片机·嵌入式硬件·51单片机
xianyinsuifeng5 小时前
Oracle 10g → Oracle 19c 升级后问题解决方案(Pro*C 项目)
c语言·数据库·oracle