快速排序算法原理 Quicksort —— 图解(精讲) JAVA

文章详细解析了Java中sort函数主要采用的快速排序算法的工作原理,该算法利用离散数学中的传递性提高效率。通过示例展示了快速排序的过程,包括设立基准、分区操作以及递归排序左右子区间的步骤,解释了为何总是让j先移动以保证正确性。最后给出了快速排序的Java代码实现,并讨论了几种特殊情况的处理。
摘要由CSDN通过智能技术生成

快速排序是 Java 中 sort 函数主要的排序方法,所以今天要对快速排序法这种重要算法的详细原理进行分析。

思路:首先快速排序之所以高效一部分原因是利用了离散数学中的传递性

例如 1 < 2 且 2 < 3 所以可以推出 1 < 3。在快速排序的过程中巧妙地使用了这个原理,所以快速排序在一般情况下效率是比其他排序高。

下面用一个示例对快速排序的运行过程进行模拟:

[4, 3, 5, 1, 2]

利用快速排序运行过程如下:

1.首先我们要设立基准,一般选择最左边的数即 temp = 4;

2. 对于 j 让其往左边移动直到遇到第一个比 temp小的数停下来。这样才能执行第3步。

3.再让 i 向右边移动直到遇到第一个比temp大的数停下来。

执行完后 i ,j 分别停留在 5,2的位置。

4.交换 i 与 j  位置所对应元素(如下图所示):

 2. 对于 j 让其往左边移动直到遇到第一个比 temp小的数停下来。

3.再让 i 向右边移动直到遇到第一个比temp大的数停下来。

上述在执行步骤 3 的时候由于 i = j 了所以不再让 i 右移动了。让 temp 与  i,j 指向的元素 交换一下即可(1与4交换位置)这样temp左边的数都比基准小,右边的数都比它大。操作完后如下所示:

以 temp 为分界线分别对左边和右边部分进行上述操作(由于分界线右边部分只有一个元素所以不必再操作):

1.首先我们要设立基准,一般选择最左边的数即 temp = 1;

2. 对于 j 让其往左边移动直到遇到第一个比 temp小的数停下来。

由于 i = j,所以严格按照规则 temp 会与temp本身交换,交换后 temp 成为了分界线,要对其左边和右边元素分别进行上述规定操作(由于temp左边没有元素所以不再操作)对分界线右边元素操作如下图所示:

1.首先我们要设立基准,一般选择最左边的数即 temp = 3;

2.对于 j 让其往左边移动直到遇到第一个比 temp小的数停下来 。

3.再让 i 向右边移动直到遇到第一个比temp大的数停下来。

由于 i = j 所以 i 不再向右移动了将 i ,j 对应元素于temp交换。得到:

left                                 right

2                                        3    

                                           i     

                                           j    

                                        temp

此时 temp为分界线,由于temp左边只有一个数,右边没有数,所以不再对分界线左右两边进行操作了。

将每一部分的运行结果拼接起来就是快速排序后的数组 [1, 2, 3, 4, 5]

需要注意的是:为什么每次都是 j 先移动,而不是i?

因为 j 的目标是找到一个比 temp 小的数,所以当 j 移动完后 j 所对应的元素大小是小于等于temp的。

i 如果再向 j 靠近的途中没有发现比temp大的数则最后会以 i = j 结束,此时 i,j所指向的元素小于等于 temp,此时交换 i,temp 所对应元素,交换完后刚好能使temp左边不比它大,右边不比它小。

反之先移动 i 情况就相反了,不符合我们所要求的结果。 

理论成立快排代码如下:

class Solution{
	 public void Quicksort(int a[], int left, int right) {
		 int temp = 0;
		 int next = 0;
		 if(left >= right) return;//退出条件
		 temp = a[left];
		 int i = left;
		 int j = right;
		 while(i != j) {//结束循环条件
			 
		 while(i < j && a[j] >= temp) j --;//找到比temp小的数
		 while(i < j && a[i] <= temp) i ++;//找比temp大的数
		 if(i == j) {
			 next = a[left];
			 a[left] = a[i];
			 a[i] = next;
		 }//与基准交换
		 else {
			 next = a[i];
			 a[i] = a[j];
			 a[j] = next;
		 }//i,j交换
		 
		 }
		 //i,j为分界线
		 Quicksort(a, left, i - 1);//递归分界线左边
		 Quicksort(a, i + 1, right);//递归分解线右边
	 }
}

对几种特殊情况的解释:当 j 向左移动时没有找到比 temp 小的数,最后会以 i = j 收尾,此种情况说明 temp 已经是最小的数了,而且 temp 就在最左侧,对 temp 右边数进行后续快排操作完全没问题。

当 j 找到比 temp 大的数,i 向右移动的过程中没有找到比 temp 大的数,最后也会以 i = j 收尾。此种情况说明 i 和 j 左边元素都不比 temp 大,右边元素都不比temp小此时 i,j 所对应元素是比temp 小的,然后交换temp 与 i ,j 所对应元素刚好使得交换后temp左边元素不比temp大,右边元素不比temp小。

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值