读完我写的java实现快速排序,80岁的老大爷表示写代码不过如此!

前言

面试中无可避免地会问到算法题,快速排序是很常见的题目,那么用java代码如何实现呢?

基础思想

快速排序的基本思想:通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序。

基本步骤

1.从数列中挑出一个元素,称为 “基准”(pivot);

2.重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作;

3.递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。

测试代码

话不多说,先上代码,然后逐步分析,看每一步执行了什么操作。

package com.unicom;

/**
 * @Description:java快速排序
 * @Author: tkai
 * @CreateDate: 2021年4月23日
 * @Version:
 */
public class AarrySort {
	public static void main(String[] args) {
		int[] a = {20,1,34,32,18,13,16};
		System.out.print("原始数组:");
		printArray(a,0);
		fastSortArray(a,0,a.length-1);
	}
	
	
	/**
	 * @Description:快速排序主函数
	 * @param ary   数组
	 * @param low   最小下标
	 * @param high  最大下标
	 */
	public static void fastSortArray(int[] ary,int low ,int high) {
		System.out.println("开始下标:"+low+"----------------结束下标:"+high);
		int start = low;
		int end = high;
		int key =  ary[low];
		System.out.println("基数下标:"+low+"基数值:"+key);
		
		//进入循环
		while(start<end) {
			
			//从后往前比较
			while (end>=start&&ary[end]>key) {
				end--;
				System.out.println("end减1");
			}
			/*如果大于关键值,就跳到前一个进行比较
			 * 如果小于等于关键值,替换当前值与start位的值*/
			if(ary[end]<=key) {
				int temp = ary[end];
				ary[end] = ary[start];
				ary[start] = temp;
				System.out.print("[start:"+start+"]|[end:"+end+"]<"+ary[end]+">换<"+ary[start]+">");
				printArray(ary,key);
				System.out.println("跳出从后往前:");
			}
			
			//从前往后比较
			while (end>start&&ary[start]<=key) {
				start++;
				System.out.println("start+1");
			}
			/*如果当前值小于关键值,就跳到后一个比较
			 * 如果当前值大于关键值,替换当前值与end的值*/
			if(ary[start]>=key) {
				int temp = ary[start];
                ary[start] = ary[end];
                ary[end] = temp;
                System.out.print("[start:"+start+"]|[end:"+end+"]<"+ary[end]+">换<"+ary[start]+">");
                printArray(ary,key);
                System.out.println("跳出从前往后:");
			}
			//至此完成第一轮比较
		}
		//递归
		if(start>low+1) {
			//左边,从第一个到关键值位置的前一个 
			System.out.println("左侧进入递归");
			fastSortArray(ary,low,start-1);
		}
		if(end+1<high) {
			//右边,从关键值位置的后一个,到最后一个
			System.out.println("右侧进入递归");
			fastSortArray(ary,end+1,high);
		}
		
	}
	
	/**
	 * @Description:便于识别基数的打印数组
	 * @param a
	 * @param key
	 */
	public static void printArray(int[] a,int key) {
		System.out.print("[");
		for (int i = 0; i < a.length; i++) {
			if(a[i]==key) {
				System.out.print("("+a[i]+"),");
			}else if(i==a.length-1) {
				System.out.print(a[i]);
			}else {
				System.out.print(a[i]+",");
			}
		}
		System.out.print("]");
		System.out.println();
		
	}
}

过程分析

第一轮:

原始数组:[20,1,34,32,18,13,16]
开始下标:0----------------结束下标:6
基数下标:0基数值:20

先从后往前依次与基数20相比,
[start:0]|[end:6]<20>换<16>[16,1,34,32,18,13,(20),]
跳出从后往前:
start+1
start+1
[start:2]|[end:6]<34>换<20>[16,1,(20),32,18,13,34]
跳出从前往后:
end减1
[start:2]|[end:5]<20>换<13>[16,1,13,32,18,(20),34]
跳出从后往前:
start+1
[start:3]|[end:5]<32>换<20>[16,1,13,(20),18,32,34]
跳出从前往后:
end减1
[start:3]|[end:4]<20>换<18>[16,1,13,18,(20),32,34]
跳出从后往前:
start+1
[start:4]|[end:4]<20>换<20>[16,1,13,18,(20),32,34]

第一轮执行完成后,得到的数组为[16,1,13,18,20,32,34],此时进入判断是否需要进入左侧递归环节,start为4,大于最小下标0+1=1,需要进入递归。

这一轮最小下标不变,仍然为0,最大下标则变为上一轮结束时的start-1,即是3。即是前4个数的比较,看日志:

第二轮

 

左侧进入递归
开始下标:0----------------结束下标:3
基数下标:0基数值:16
end减1
[start:0]|[end:2]<16>换<13>[13,1,(16),18,20,32,34]
跳出从后往前:
start+1
start+1
[start:2]|[end:2]<16>换<16>[13,1,(16),18,20,32,34]
跳出从前往后:

执行完成后,得到数组[13,1,16,18,20,32,34],此时start为2,仍然大于最小下标0+1,仍然进入左侧递归。递归下标为0到1,即前两个数的比较。

第三轮

左侧进入递归
开始下标:0----------------结束下标:1
基数下标:0基数值:13
[start:0]|[end:1]<13>换<1>[1,(13),16,18,20,32,34]
跳出从后往前:
start+1
[start:1]|[end:1]<13>换<13>[1,(13),16,18,20,32,34]
跳出从前往后:

执行完成后,得到数组为[1,13,16,18,20,32,34],此时start为1,不大于0+1,不再进入左侧递归。可以看到,第一轮选择的基数20左侧的数字已经按从小到大排列了

至此,判断是否进入右侧递归。end的值为4(我们看到第三轮结束时end和start为1,实际上是在判断进入左侧方法的代码块里的值,此处的值为4),end+1=5,

小于此时的最大下标6(与上一行标红处解释相同),应当进入右侧递归。

右侧递归的最小下标为end+1=5,最大下标仍为原最大下标6,即第6个数至第7个数的排序。

第四轮

右侧进入递归
开始下标:5----------------结束下标:6
基数下标:5基数值:32
end减1
[start:5]|[end:5]<32>换<32>[1,13,16,18,20,(32),34]
跳出从后往前:
[start:5]|[end:5]<32>换<32>[1,13,16,18,20,(32),34]
跳出从前往后:

执行完成后得到的数组为[1,13,16,18,20,32,34],可以看到,此时的数组已经排序完成。

但作为程序,依然会进入判断。

start =5 ,low=5,  high = 6;

start不大于low+1,固不进入左侧递归;

end+1不小于high,故不进入右侧递归。

========================================至此结束,排序完成===============================

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值