地道的快速排序渐行渐远

博客指出网上多数快速排序算法介绍存在问题,将其改成稳定算法后失去原汁原味,称其为伪快排。分析代码发现查找交换值时遇到与基准值相同数值略过不符合快速排序规则。解决方案借鉴中间值快速排序思路,还提及快速排序的优化及其他用到它的排序算法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

背景

网上大多数快速排序算法介绍都是挂羊头卖狗肉,为何我有这种感慨,那是因为快速排序是一种不稳定的算法,如果将它改成稳定算法的话,是不是有些四不像,说的再好听一些就是快速排序的一些变种,改进都说不上,因为改的失去了快速排序的原汁原味。但是想不到网上不少人对该算法津津乐道,称之为简单快捷,我愿将之称为伪快排


问题分析:

来进入代码看一看这种类快排或者伪快速排序(不含测试方法):


	public static void quicksortbyleft(int[]arr , int left,int right) {
		//注意递归函数必须有返回值,下面为递归的结束条件,如果缺少就会报错,这里会报数组下标越界.
		if(left>=right) {
			return;
		}
		int l = left;
		int r = right;
		int temp =0;
		int pivot = arr[left];
		
		while(l!=r) {
			while(arr[r]>=pivot && l<r) {
				r--;
			}
			while(arr[l]<=pivot && l<r) {//这里应该大于等于要交换,这才是快速排序,是不稳定的
				l++;
			}
			if(l!=r) {
				temp = arr[r];
				arr[r] =arr[l];
				arr[l]=temp;
			}	
		}
		//把l与r共同指向的值赋值给基准值,即left
		arr[left] = arr[l];//这里可以填arr[l]==arr[r]
		//把基准值放到最终的位置上
		arr[l]=pivot;
		//递归,让l+1指向右半部分第一个值,r-1指向左半部分最后一个值
		quicksortbyleft(arr, left,r-1);
		quicksortbyleft(arr, l+1, right);
		}

代码中有详细的解释,如果你有一个序列带入的话,会发现结果很可观,同时各个阶段都很清晰,比如跳出while循环就是l==r的时候,就是这次递归将要结束,给基准赋值等。整套流程下来是不是行云流水,水到渠成的痛快,但是转念一想,不对啊,老哥,你这两个小while找交换值最后出来个值相等也略过是什么鬼,那岂不是说,查到和基准值一样的数值,直接过去了,这有点说不过去了,按照快速排序是不是要交换一下,哎,年轻人不讲武德。

解决方案:

public static void  quicksort(int[] arr,int left,int right) {
		int l = left;
		int r = right;
		int mid = left;
		int temp = 0;
		while(l!=r) {
			while(arr[l]<arr[mid]) {
				l++;
			}
			while(arr[r]>arr[mid]) {
				r--;
			}
			//当l>=r,结束这个while循环,实际上此时l==r
			if(l>=r) {
				break;
			}
			//交换大小值
			temp = arr[l];
			arr[l]=arr[r];
			arr[r]=temp;
			
			if(arr[l]==arr[mid]) {
				//这里可以避免死循环。如{-9,3,0,23,3,3,3,-567,70}中当下//标l=4,r=6,mid=5时的值相同,换来换去都一样的尴尬局面。
				r--;
			}
			//作用同上
			if(arr[r]==arr[mid]) {
				l++;
			}
			
		}
		//当l=r时,让r-1,到左半部分;让l+1到右半部分
		if(left<r-1) {
		quicksort(arr, left, r-1);
		}
		if(l+1<right) {
		quicksort(arr, l+1, right);
		}
	}

这里借鉴了按照中间值快速派排序的思路和实现方式,另外快速排序还有很多不错的优化与创新,还有不少常用的排序算法比如内省排序、bfptr排序都用到了快速排序,实现在最坏时间复杂度下依旧有良好的时空高性能,有机会还会记录下来。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值