快速排序暴力解析

快速排序是冒泡排序的改进版,也是最好的一种内排序,还涉及到分治和递归,在很多面试题中都会出现,也是作为程序员必须掌握的一种排序方法。

过程解析:

第一趟排序:
在这里插入图片描述在这里插入图片描述具体运行简析:
首先使用两个指针low 和high分别指向待排序的数组的两界,即arr[0]和arr[arr.length-1],然后我们可以将arr[0]作为一个基准值,即int p=arr[0].
首先我们从high指针开始,逐步向前搜索,直到搜索到第一个比p小的值,然后将其设置到low所指的值,随后再从low指针开始向后搜索第一个比p大的值,然后将其设置到high所指的位置.重复上述步骤,直到low=high.然后,将p设置到low与high共同指向的位置,此时p左侧便都是小于p的值,右侧都是大于p的值.
然后我们可以以p为基点将原数组分为两个新的数组,然后利用递归的方法对其进行上述步骤,最终便可得到一个完全排好序的数组.
快速排序=冒泡+分治+递归
快速排序的过程:东拆西补或西拆东补,一边拆一边补

代码实现:

方法:

private static int partition(int[] arr,int low,int high){
		int x=arr[low];
		while(low<high){
			while(low<high&&arr[high]>=x){
				high--;
			}
			if(low<high){
				arr[low]=arr[high];
				low++;
			}
			while(low<high&&arr[low]<x){
				low++;
			}
			if(low<high){
				arr[high]=arr[low];
				high--;
			}
		}
		arr[low]=x;
		return low;
	}
	private static void quickSort(int[] arr,int low ,int high){
		if(low<high){
			int n=partition(arr, low, high);
			quickSort(arr, low, n-1);
			quickSort(arr, n+1, high);
		}
	}
	
	private static void quickSort(int[] arr){
		int low=0;
		int high=arr.length-1;
		quickSort(arr, low, high);
	}

测试:

public static void main(String[] args) {
		int arr[] = {72,6,57,88,60,42,83,73,48,85};
		System.out.println(Arrays.toString(arr));
		quickSort(arr);
		System.out.println(Arrays.toString(arr));
	}

快速排序算法的分析

  • 1.当分区选取的基准元素为待排序元素中的最大或最小值时,为最坏的情况,时间复杂度和直接插入排序的一样,移动次数达到最大值Cmax = 1+2+…+(n-1) = n*(n-1)/2 = O(n2) 此时最好时间复杂为O(n2)
  • 2.当分区选取的基准元素为待排序元素中的"中值",为最好的情况,时间复杂度为O(nlog2n)。
  • 3.快速排序的空间复杂度为O(1*log2n). (用到了递归,当然占用空间多了)
  • 4.当待排序元素类似[6,1,3,7,3]且基准元素为6时,经过分区,形成[1,3,3,6,7],两个3的相对位置发生了改变,所是快速排序是一种不稳定排序。

时间效率:
快速排序算法的运行时间依赖于划分是否平衡,即根据枢轴元素 pivot 将序列划分为两个子序列中的元素个数,
而划分是否平衡又依赖于所使用的枢轴元素。下面我们在不同的情况下来分析快速排序的渐进时间复杂度。
快速排序的最坏情况是每次进行划分时,在所得到的两个子序列中有一个子序列为空。此时,算法的时间复杂度T(n) = T p (n) + T(n-1),
其中T p (n)是对具有n个元素的序列进行划分所需的时间,由以上划分算法的过程可以得到T p (n) = Θ(n)。由此,T(n) =Θ(n) + T(n-1) =Θ(n 2 )。
在快速排序过程中,如果总是选择r[low]作为枢轴元素,则在待排序序列本身已经有序或逆向有序时,快速排序的时间复杂度为Ο(n 2 ),
而在有序时插入排序的时间复杂度为Ο(n)。
快速排序的最好情况是在每次划分时,都将序列一分为二,正好在序列中间将序列分成长度相等的两个子序列。
此时,算法的时间复杂度T(n) = T p (n) + 2T(n/2),由于T p (n) = Θ(n),所以T(n) = 2T(n/2) +Θ(n),
由master method知道T(n) = Θ(n log n)。
在平均情况下,快速排序的时间复杂度 T(n) = kn ㏑ n,其中 k 为某个常数,经验证明,在所有同数量级的排序方法中,
快速排序的常数因子 k 是最小的。因此就平均时间而言,快速排序被认为是目前最好的一种内部排序方法。
快速排序的平均性能最好,但是,若待排序序列初始时已按关键字有序或基本有序,则快速排序蜕化为起泡排序,其时间复杂度为Ο(n 2 )。
为改进之,可以采取随机选择枢轴元素pivot的方法,具体做法是,在待划分的序列中随机选择一个元素然后与r[low]交换,再将r[low]作为枢轴元素,
作如此改进之后将极大改进快速排序在序列有序或基本有序时的性能,在待排序元素个数n较大时,其运行过程中出现最坏情况的可能性可以认为不存在。

空间效率:
虽然从时间上看快速排序的效率优于前述算法,然而从空间上看,在前面讨论的算法中都只需要一个辅助空间,
而快速排序需要一个堆栈来实现递归。若每次划分都将序列均匀分割为长度相近的两个子序列,则堆栈的最大深度为 log n,
但是,在最坏的情况下,堆栈的最大深度为 n。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值