【数据结构1.0】快速排序

最近学习了快速排序,鼠鼠俺来做笔记了!

本篇博客用排升序为例介绍快速排序!

目录

1.快速排序

1.1.快速排序的”单趟“

1.1.1.hoare版本

1.1.2.挖坑法版本

1.1.3.前后指针版本

1.2.快速排序的递归写法 

1.3.快速排序的非递归写法

2.快速排序递归写法优化 

2.1.三数取中法选基准值

2.2.小区间优化


1.快速排序

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

如果对上面的介绍蒙圈的话,没关系,我们继续看下面的内容,会仔细介绍的!

1.1.快速排序的”单趟“

快速排序的”单趟“简单来说就是在需排序数组中任取一个元素作为基准值,经过”单趟“过后,大于或者等于基准值的元素都排在基准值的后面,小于或者等于基准值的元素都排在基准值的前面,也就是说基准值所在的位置就是它应该出现的位置,这个基准值就排好了!

对于”单趟“的实现方法有但不限于下面三种:

1.1.1.hoare版本

这个动图就是hoare版本的”单趟“实现方法!这里取第一个元素6为基准值;R从最”右边“开始找比基准值小的元素,L从最”左边“开始找比基准值大的元素, 然后交换下标为R和L的元素;R继续找比基准值小的元素,L继续找比基准值大的元素,再交换下标为R和L的元素…………直到R和L相遇,将基准值和相遇位置的元素即可!

其实这个本质就是将比基准值大的元素”甩“到”后面“,将比基准值小的元素”甩“到”前面“。

也许会有疑问,怎么保证相遇位置的元素一定不大于基准值呢?

因为只要是R先动,L后动的话必然能保证相遇的元素一定不大于基准值!

相遇无非两种情况:

1.R遇L:R在去找小于基准值的元素的过程中,下标为L的元素必然是不大于基准值的元素。当R去找小于基准值的元素没有找到却遇到L时, 那么相遇位置的值就是不大于基准值的元素。

2.L遇R:由于R先动,那么L在找大于基准值的元素的过程中,下标为R的元素必然是不大于基准值的元素。当L去找大于基准值的元素没有找到却遇到R时,那么相遇位置的值就是不大于基准值的元素。

 hoare版本的“单趟”代码如下,需排序数组下标为begin—end:

//hoare版本
	int keyi = begin;
	int left = begin, right = end;
	while (left < right)
	{
		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;

由于hoare版本写起来很容易出错误,所以我们一般写下面两种版本!

1.1.2.挖坑法版本

也是取第一个元素6为基准值。初始坑位设置为基准值下标。让R从最“右边”开始找比基准值小的元素,找到后将下标为R的元素填入坑位,那么新的坑位就变成了R;让L从最“左边”开始找比基准值大的元素,找到后将下标为L的元素填入坑位,那么新的坑位就变成了L;R再找比基准值小的元素……直到R和L相遇,将基准值填入坑位即可。

本质就是R找小填入“左边”坑位,L找大填入“右边”坑位,最后一个坑位必定是R和L相遇位置,填入基准值就好。

挖坑法版本“单趟”代码如下,需排序数组下标为begin—end:

//挖坑法版本
	int  key=a[begin];
	int left = begin, right = end;
	int hole = begin;
	while (left < right)
	{
		while (left < right && a[right] >= key)
		{
			right--;;
		}
		a[hole] = a[right];
		hole = right;
		while (left < right && a[left] <= key)
		{
			left++;
		}
		a[hole] = a[left];
		hole = left;
	}
	a[hole] = key;
	int keyi = hole;
1.1.3.前后指针版本

取第一个元素6为基准值。prev初始指向基准值,cur初始指向基准值的下一个元素。cur遍历数组:如果cur遇到大于基准值的元素,++cur;否则++prev、cur指向的元素和prev指向的元素交换、++cur。

前后指针版本“单趟”代码如下, 需排序数组下标为begin—end:

//前后指针版本
	int cur = begin + 1, prev = begin;
	int
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

X_chengonly

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

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

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

打赏作者

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

抵扣说明:

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

余额充值