快速排序算法原理、C++代码

这篇博客介绍了快速排序的原理,包括其分治思想和递归实现过程。通过选取基准值,局部微调并分割区域,最终完成数组排序。文章还提供了具体的C++代码实现。
摘要由CSDN通过智能技术生成

最近在啃算法导论,看完了关于快排的章节,用代码实现了一遍,决定写个blog记录一下,日后忘记了好拿来复习。

一、快速排序的思想

快速排序使用了分治思想——假设现在手头有一个待排序的数组A:

int a[] = { 1,2,5,6,7,4,2,10,9,2,30,1,4,11 }; //任意数组

快速排序首先从A中任取一个基准值A0,遍历整个数组,将整个数组元素以A0为基准分为左右两个区域,左边的都小于A0,右边的都大于A0。举个例子,倘若取最后一个元素11作为基准值A0,以11为界限划分数组会得到如下结果:

{1,2,5,6,7,4,2,10,9,2,1,4,11,30}

现在我们只能说对数组进行了微调,为什么是微调?因为整个数组中只有11这一个元素(也就是基准值)走到了它最终的位置,而且大部分元素位置并无改变。我们先忽略微调算法的实现过程(一会再讲),继续思考如何实现整个数组的排序。

接下来,我们以11为界,将整个数组分成左右两个半区,我们就得到了一模一样的两个子问题:

A1 = {1,2,5,6,7,4,2,10,9,2,1,4}
A2 = {30}

这里的两个“{}”只是方便理解,并非物理上两个新的数组,我们的“分割”操作都是在原数组A上通过下标访问进行的。

接下来怎么做?对每个新的子问题重复进行“选基准值——局部微调——分割区域”的操作,显然可以递归实现,递归的出口就是只剩下一个元素时,不需要再微调。结果如下:

A = {1,1,2,2,2,4,4,5,6,7,9,10,11,30};

总结一下,快速排序的思想就是分治法+递归,通过一步步微调实现整个数组的有序。下面来看具体的实现方法:

二、快速排序算法实现

由于算法是递归的,所以关键就是如何实现“选基准值——局部微调——分割区域”这一操作。

  • 选基准值

为了简单起见,我们仍然选取当前数组(或者子数组)的最后一个元素为基准值 A0。接下来就是通过一次遍历剩下的元素完成微调过程。

  • 局部微调

在这里我们维护两个下标指针 i 和 j,i 之前保存小于基准值的序列,i 之后 j 之前保存大于基准值的序列,当 j = size(A) - 1停止遍历,最后将基准值和 A[i+1] 作交换,初始时 i = -1,j = 0,让 j 指针向后滑动。

倘若 A[j] < A0,发现一个应当前移的元素,将i 指针向后移动(i += 1),然后交换 A[j] 与 A[i] 。

手画一个将就看
图看不懂的可以直接看代码:

int Partition(int* array, int begin, int end) //左闭右开
{
	int ref = array[end - 1]; //参考值
	int i = begin-1;
	for (int j = begin; j < end - 1; j++) //遍历插入
	{
		if (array[j] <= ref)
		{
			i += 1;
			int temp = array[j];
			array[j] = array[i];
			array[i] = temp;
		}
	}// 指针i之前的元素是<end的
	int temp = array[end - 1];
	array[end - 1] = array[i + 1];
	array[i + 1] = temp;
	return i + 1;
}
  • 分割区域

分割的工作很简单,因为我们已知当前数组的起始和结束,所以只要在函数中返回基准值的下标就OK了。

最后的最后,我们直接用递归调用子函数实现整个数组的全部有序:

void Quick_Sort(int* array, int begin, int end)
{
	if (begin < end-1) //最少2个元素,否则直接返回
	{
		int q = Partition(array, begin, end);
		Quick_Sort(array, begin, q);
		Quick_Sort(array, q+1, end);
	}
}

主函数调用一下打印结果看看:

int main()
{
	int array[] = { 1,2,5,6,7,4,2,10,9,2,30,1,4,11 };
	Quick_Sort(array, 0, size(array));
	for (int i : array)
		cout << i << " ";
	return 0;
}

在这里插入图片描述
以上就是学习快排的一些收获,有用的话就点个赞吧~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值