快速排序分析

前言:


刚刚学习到快速排序,快速排序是个基础问题,去网上查了下,发现竟然没有一个让人满意的答案。
就连为什么快速排序比冒泡排序快这个基本的概念,也没人说清楚。
一般而言,网上对于为什么快速排序比冒泡快,有两种方向:
1.算时间复杂度
2.二分法的优越性


对于这两种解释,明显没有从根本上触及原理。
对于1.算时间复杂度
这是逻辑颠倒,恰恰是效率高导致时间复杂度低。所以说这种解释因果倒置。
对于2.二分法的优越性
这个我不知道说什么好。

这里预先我给出我的答案:冒泡法一轮比较,只确定了一个数的位置。而快速排序,可以确定一个点的同时,还将数组一分为二。冒泡排序由于是不同的数相比较而快速排序是和相同的数比较。相当于在比较中选择了最极端的模式,浪费了信息。冒泡排序可以算是每次都是最坏选择的快速排序。(实际操作中:为提高效率,快速排序一般是一分为二,而没有确定一个点的位置)

概念:
快速排序:对一个数组操作,将数组分成两部分,前面的一部分比后面的一部分小(同组之间乱序),然后继续分割两个小数组。。。

将数组分成两部分的操作:选取数组中的一个数,从两端开始比较,左端的话如果小于就说明这个数可以放左边,比较下一个,如果大于那么先待定;右边的话,如果大于基数那么说明这个数可以放右边,比较下一个,如果小于那么和刚刚那个数对换。这样依次确认位置,就能划分完整个数组。



如何通过比较和交换位置,达到左边的都比该数小,右边的都比该数大.

这里直接给出思路:


1.单边确认
规定:需要排序的数组为arr ,选取的第一个排序数为:arr[random](r表示在数组下标范围之内的随机数)

1.if(arr[0]>arr[random]){arr[0]和arr[length-1]交换位置(此操作等于确定了数组最后一个位置的值)}
2.if(arr[0]<arr[r]){比较下一个(此操作等于确定了数组第一个位置的值)}

基于以上思路,给出代码:

public static void sort(int[] arr,int left,int right) {
		//设置递归结束条件
		if (right-left<1) {
			return ;
		}
		int l=left;
		int r=right;
		int sPoint=arr[left+new Random().nextInt(right-left+1)];//用随机位置确定比较的基数
		
		while (l<=r) {//使用等于为了比较每一个数
			if (arr[l]<=sPoint) {
				l++;//这里就确定了一个左边位置
			}else if(arr[l]>sPoint){
				int temp=arr[r];
				arr[r]=arr[l];
				arr[l]=temp;
				r--;
				//这里是一个交换操作,不过用往后抛形容更恰当,因为这样操作一次,右边的位置就确定了一个
			}
		}
		
		if (l-1>=0) {
			sort(arr, left,l-1);
		}
		sort(arr, r+1, right);


	}

此时我们发现:有很多交换操作是不必要的,例如:如果最后一个数是大于基数的就没必要换过来。以及对于等于的情况没有处理,所以无法排序有等值的数列。
2.双边排序+等值处理
public static void sort2(int[] arr,int left,int right) {
		if (right-left<1) {
			return ;
		}
		int l=left;
		int r=right;
		int index=left+new Random().nextInt(right-left+1);
		int sPoint=arr[index];//用随机位置确定比较的基数
		while (l<r) {
			while (l<=r&&arr[l]<=sPoint) {
				//等值处理,及:如果所有的数小于或等于基数,那么将基数移至最后,防止出现无法划分数组的情况
				if(l==right){
					if(arr[index]!=arr[right]){
						int temp=arr[index];
						arr[index]=arr[right];
						arr[right]=temp;
					}
					break;
				}
				l++;//这里就确定了一个左边位置
				
			}
			while(arr[r]>sPoint&&l<r){
					r--;
				}
			if (l<r) {
				int temp=arr[r];
				arr[r]=arr[l];
				arr[l]=temp;
			}
		}
		if (l-1>=0) {
			sort2(arr, left,l-1);			
		}	
		sort2(arr, l, right);
	}







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值