快速搞定经典“快排”与“随机快排”

快排算法

快排其实是在荷兰国旗问题的基础上发展出来的,不知道荷兰国旗问题的请看我上一篇博文,它分为3步:分割、交换、递归

以下就是关于快排的详细代码

package Sort_learning;

public class QuickSort {
	public static void quickSort(int[] arr, int L, int R) {
		//只有当L<R时,才排序,否则直接退出。
		if(L < R) {
			//swap(arr, L + (int)(Math.random()*(R-L+1)),R);//随机快排
			int[] p = partition(arr, L, R);
			//由于递归排序[less + 1, more]中的元素已经排好,
			//只要将此区域左右两边的区域递归即可。
			quickSort(arr, 0, p[0] - 1);
			quickSort(arr, p[1] + 1, R);
		}
		
	}
	public static int[] partition(int[] arr, int L, int R) {
		int less = L - 1;    //定义一个变量用来表示遍历区间的前一位置
		int more = R;		//定义一个变量用来表示遍历区间的后一位置
		while(L < more) { 	//L逐步向R推进,直到L与more相遇
			if(arr[L] > arr[R]) {      
				swap(arr , ++less, L++);
			}if(arr[L] < arr[R]) {
				swap(arr, --more , L);
			}else
				L++;
		}
		swap(arr, R, more);   //由于前面的循环只搞定了[L,R-1]上的排序
							  //而R处的数还没有交换位置到相等的区域
		                      //因此,此步用来将R处的数归位,相当于是先给R定制这样一个等于区域,在将它归位。
		return new int[] {less + 1, more};  //返回一个数组,内含2个数:用来表示数组的边界
		
		
	}
	public static void swap(int arr[], int L, int R) {
		int temp = arr[L];
		arr[L] = arr[R];
		arr[R] = temp;
	}
	public static void main(String[] args) {
		int arr[] = {3,4,50,22,37,82,4,14};
		quickSort(arr, 0,arr.length-1);
		for(int i = 0; i < arr.length - 1; i++) {
			System.out.println(arr[i]);
		}
	}
}

经典快排的时间复杂度

当等于区域都正好在中间时,是快排最好的情况,此时,最好的时间复杂度为:
T(N) = 1/2T(N/2) + O(n)) 和归并排序一样,他最终的时间复杂度也是O(NlogN);
在最坏的情况下,也就是待排序的序列为正序或者逆序时,每一次排序后,都得到只比之前少一个记录数的子序列,也就是只排除了一个数。剩余的数依然要一个一个地递归下去,此时需要执行n‐1次递归调用,且第i次划分需要经过n‐i次关键字的比较才能找到第i个记录,也就是枢轴的位置,因此,比较次数为在这里插入图片描述
最终计算的最坏的情况下的时间复杂度为O(N^2);

随机快排的时间复杂度

上面代码中的swap(arr, L + (int)(Math.random()*(R-L+1)),R);即为随机快排。
就是从区间[L,R]随机选一个数,再用随机选的数与最后一个数作交换。此时复杂度就是一个概率事件了,此时估计的就是一个概率表达式了,只能用长期期望的方式来估算时间复杂度。经计算,这个时间复杂度的长期期望值是O(nlogn).
随机快排是最常用的排序手段,在3个时间复杂度为O(nlogn)(归并排序、随机快排、外排)中,随机快排因其常数项最小,且代码非常简洁 ,且归并排序的空间复杂度为O(n),而随机快排的空间复杂度为O(logn),它的空间复杂度主要浪费在需要记下每一个划分点上,而最好的情况下,一共需要分割的次数为O(logn),因此一共需要记录logn个断点;最坏的情况下,即每个点都需要记时,一共需要分割的次数为O(n),因此一共需要记录O(n)个断点。综上所述,随机快排是我们的最佳选择。

觉得写得不错的,点个关注,再点个赞,给你分享更多干货。
关注我的微信公众号,更多干货等你白票!
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

追梦_赤子

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

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

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

打赏作者

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

抵扣说明:

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

余额充值