快速排序详解

 

感谢各位大佬的光临,希望和大家一起进步,望得到你的三连,互三支持,一起进步

个人主页LaNzikinh-CSDN博客

收入专栏:初阶数据结构_LaNzikinh篮子的博客-CSDN博客

文章目录

  • 前言
  • 一.什么是快速排序
  • 二.快排的实现--挖坑法
  • 三.快排的实现--左右指针法
  • 四.快排的实现--前后指针法
  • 总结

前言

前面讲了很多的排序算法,今天我们来讲一下快速排序的多种方法


一.什么是快速排序

快速排序快速排序是对冒泡排序算法的一种改进,同冒泡排序一样,快速排序也属于交换排序,通过元素之间的比较和交换位置来达到排序的目的快速排序原理 快速排序是基于“分治法”原理实现,所谓分治法就是不断的将原数组序列按照一定规律进行拆分,拆分后各自实现排序直到拆分到序列只剩下一个关键字为止。

二.快排的实现--挖坑法

总思路:快速排序的主要思想还是分治,将一串无序的数字不断地分治变为有序的,先选出一个数,然后将这个数的右边放大于它的数左边小于它的数,这就是一轮,这个数选完之后再选下一个数不断地循环就可以排好。

挖坑法思路:

先选出一个数为坑,再把这个数存为钥匙保存后面可以用,然后从数组的最后开始找小于坑位置的数,找到了之后,与可能位置互换,形成新的坑,再从最开始的位置找大于当前坑位置的数,直到begin与end相等,就结束结束之后,再把钥匙放在他们的中间就完成了一次,后面通过函数递归来完成这个循环

void Quick1sort(int* a, int left, int right)
{
   //三数取中
	int index = GetMidIndex(a, left, right);
	Swap(&a[left], &a[index]);

	int begin = left;
	int end = right;
	int pivot = begin;
	int key = a[begin];
	while (begin < end)
	{
		//右边找小,放到左边去
		while (begin < end && a[end] >= key)
		{
			end--;
		}
		//小的放到左边的坑里,自己变成新的坑位
		a[pivot] = a[end];
		pivot = end;
		//左边找大,放到右边去
		while (begin < end && a[begin] <= key)
		{
			begin++;
		}
		//大的放到右边坑里,自己变成新的坑位
		a[pivot] = a[begin];
		pivot = begin;
	}
	//最后把最开始的钥匙放到中间去即可
	pivot = begin;
	a[pivot] = key;
	Quick1sort(a, left, pivot - 1);
	Quick1sort(a, pivot+1,right);
}

这里还要引出一个三数取中的思想,结束快速排序若排的是逆序的话O(N),我们要避免逆序,关键在找钥匙上,如果min或max值为key就会出现这种,避免逆序O(N*logN)

int GetMidIndex(int* a, int left, int right)
{
	int mid = (left + right) / 2;
	if (a[left] < a[mid])
	{
		if (a[mid] < a[right])
			return mid;
		else if (a[left] < a[right])
			return left;
		else
			return right;
	}
	else if (a[left] > a[mid])
	{
		if (a[mid] > a[right])
			return mid;
		else if (a[left] < a[right])
			return left;
		else
			return right;
	}
}

三.快排的实现--左右指针法

思路:利用三数取中来找钥匙,从开始end找小找到小的时候停下来,从begin开始找大,找到大的时候停下来,把小的和大的互换,然后继续直到相等,最后再把钥匙放到他们的中间就完成了一轮,后面在用函数递归来完成

void Quick2sort(int* a, int left, int right)
{
	int index = GetMidIndex(a, left, right);
	Swap(&a[left], &a[index]);
	int begin = left;
	int end = right;
	//
	int pivot = begin;
	int key = begin;
	while (begin < end)
	{
		//找小,begin < end防止数组越界
		while (begin < end && a[end] >= a[key])
		{
			end--;
		}
		//找大,begin < end防止数组越界
		while (begin < end && a[begin] <= a[key])
		{
			begin++;
		}
		Swap(&a[begin], &a[end]);
	}
	//把钥匙放到中间去
	Swap(&a[begin], a[key]);
	int pi = begin;
	Quick1sort(a, left,pi-1);
	Quick1sort(a, pi + 1, right);

}

四.快排的实现--前后指针法

思路:cur找小,每次遇到比key小的值就停下来,prev++,交换prev和cur的位置的值等cur结束,最后交换key和prve

void Quick3sort(int* a, int left, int right)
{
	int index = GetMidIndex(a, left, right);
	Swap(&a[left], &a[index]);
	int key = left;
	int prve = left;
	int cur = left + 1;
	while (cur <= right)
	{
		if (a[cur] < a[key])
		{
			prve++;
			Swap(&a[prve], &a[cur]);
		}
		cur++;
	}
	Swap(&a[key], &a[prve]);
	Quick1sort(a, left, prve-1);
	Quick1sort(a, prve + 1, right);
}

总结

今天说了快排的3种实现方法,但是多次调用函数递归,可能回栈溢出,所以还要有快排的非递归的实现,下次在来讲解,还有最后几个排序的收尾

  • 69
    点赞
  • 43
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 75
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

LaNzikinh篮子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值