学习笔记----快速排序的java实现

news/2024/5/19 23:36:53 标签: java, 快速排序

快速排序算法是我们学习数据结构必学的算法之一,虽然在java中,对列表的排序可直接使用Collections.sort(List l) (这使用的是归并排序算法) ,对基本类型的数组也有Arrays.sort()(这使用的是改进的快速排序算法),但实现一个快速排序,仍能给自己很多启发。
很多算法书上都使用c或者c++实现快排算法,但是作为一个写惯了java的程序员,再去写c或c++有着各种水土不服(没有丰富的API库帮忙),加上jvm虚拟机性能的提高,也就可以用java回顾一下以前的快速排序算法,也算为面试做个准备。 快速排序的平均时间复杂度能达到O(n*log n),最坏情况下 (元素基本有序,中轴选择总是最大或最小 、元素,此时快速排序退化成冒泡排序)为O(n^2)。
本例中使用随机选择中轴元素的方式降低了最坏情况可能性,并在子数组比较小(在书上推荐是5-15个元素即比较小)的时候停止快排,采用插入排序(最好情况既元素基本有序下,时间复杂度为O(n))完成整个List的排序。 有关快速排序的原理,算法书上已经讲的很清楚了,按照我个人的理解,快速排序就是如何将整个数组通过选择的中轴(key)划分成两个子数组,并且满足(key)这种关系。这就算完成一趟快排了,剩下的只需要递归(key)即可。 快排代码如下:

java">public class QuickSort {

	static List<Integer> list = new ArrayList<>();
	private static int END_QUICKSORT = 7;

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		for (int i = 0; i < 100000; i++) {
			list.add((int) (Math.random() * 1000));
			//list.add(i);
		}
		long a1 = System.nanoTime();
		
		quickSort(list);

		long a2 = System.nanoTime();
		System.out.println(a2 - a1);
		/*for (Integer temp : list) {
			System.out.println(temp);
		}*/
	}

	public static void quickSort(List<Integer> list) {
		
		quick(list, 0, list.size() - 1);
		

		// 对快排后基本有序数组进行一次插入排序
		insertSort(list);
	}

	private static void insertSort(List<Integer> list2) {
		// TODO Auto-generated method stub
		for (int i = 1; i < list2.size(); i++) {
			int v = list2.get(i);
			int j = i - 1;
			for (; j >= 0 && list2.get(j) > v; j--) {
				list2.set(j + 1, list.get(j));
			}
			list.set(j + 1, v);
		}
	}

	private static void quick(List<Integer> list, int low, int hight) {
		// TODO Auto-generated method stub
		if (low < hight) {
			int key = partition(list, low, hight); // 选择中轴并对子数组部分排序
			
			if (key - low > END_QUICKSORT)
				quick(list, low, key - 1); // 对左半部分继续使用快排
			if (hight - key > END_QUICKSORT)
				quick(list, key + 1, hight); // 当(key,hight)范围小到一定程度,不再进行快排
		}
	}

	private static int partition(List<Integer> list, int low, int hight) {
		// TODO Auto-generated method stub
		int rand = (int) (Math.random() * (hight - low)) + low;
		int key = list.get(rand);
		if (rand != low) {
			int temp = list.get(low);
			list.set(low, key);
			list.set(rand, temp);
		}
		while (low < hight) {
			while (low < hight && list.get(hight) >= key)
				hight--;
			list.set(low, list.get(hight));
			while (low < hight && list.get(low) <= key)
				low++;
			list.set(hight, list.get(low));
		}

		list.set(low, key);
		return low;
	}

}

然而比较下原快速排序和随机化快排的代码执行速度发现两者差别并不大,当然在电脑上还存在其它进程影响执行,不够准确,所以这个时间值就不贴出来了。

在JDK中,对快速排序做了如下三个优化,有兴趣的同学可以去看看Arrays.sort方法的源码。
1、就像上面提到的,对于元素数小于7(java内定值)的数组,直接返回插入排序的结果(因为插入排序对基本有序数组和简单数组能保证线性性能,所以一些O(n^2)的算法不一定就不能使用)
2、使用三平均划分法(数组最左边,最右边,最中间的元素的中位数)找到中轴。
3、对于这一点我还不太理解,即是说:将和中轴相等的元素都放到数组中间,如:4,3,1,15,15,15,23,34,21 . 这样只需排序(4,3,1)和(23,34,21)这三个子数组,对于重复元素多的数组可减少问题规模。


http://www.niftyadmin.cn/n/1792739.html

相关文章

CNN做时间序列预测_一种高可靠的周时间序列预测基线模型

一种高可靠的周时间序列预测基线模型[Submitted on 16 Oct 2020]摘要&#xff1a;现在&#xff0c;许多企业和行业都需要对每周时间序列的准确预测。然而&#xff0c;目前的预测文献并没有提供易于使用的、自动的、可重复的和准确的方法来完成这项任务。我们提出一种预测方法&a…

15.2、systemd守护进程介绍

1、系统启动的流程回顾&#xff1a;post&#xff08;加电自检&#xff0c;主要用来检查支持系统启动的硬件环境是否满足&#xff09;---> bootseqence(根据bios中设定启动顺序&#xff0c;去加载相应的启动项设备&#xff09;---> bootloader&#xff08;根据启动项设备的…

修身论文2000字_哪些情况下发表的论文评职称没用?

情况一在校期间或任职前发表的论文&#xff0c;不能用做评职称的依据。情况二论文字数低于2000或者2500字&#xff08;具体根据单位的要求&#xff09;&#xff0c;或者论文没有发表在正规期刊上&#xff0c;比如增刊、假刊、套刊等。情况三论文发表的时间晚于参加职称评审交材…

如何使Session永不过期

用在要保持session的页里设隐藏iframe每隔一段时间&#xff08;这个时间小于session.timeout的时间&#xff09;把涮 新一次frame里的空页面&#xff01;实现方法如下&#xff1a; 在要保持session页里加上&#xff1a; <iframe width0 height0 src"SessionKeeper.asp&…

MaterialDesign+MovePicImageView实现漂亮的登陆界面

最近正在完成一个摇一摇的项目&#xff0c;打算加入一点社交元素。第一步是实现登陆界面&#xff0c;一个人独自设计加开发。最后的效果还是比较满意&#xff0c;但还是有性能上的损失&#xff0c;应该可以做得更好。 背景图片可以循环左右移动&#xff0c;界面里的Edittext…

python学习笔记(十四)加密模块

1 import hashlib2 ybq_pwdbugaosuni3 mhashlib.md5()4 bytes_ybqybq_pwd.encode()#把字符串转成bytes类型&#xff0c;中文字符在Python中是以unicode存在的,我们在进行hash前必须把数据转换成bytes类型5 m.update(bytes_ybq)#加密&#xff0c;不能字符串&#xff0c;只能传by…

分支运算

//语句分类&#xff1a;顺序语句&#xff0c;选择语句&#xff08;分支语句&#xff09;&#xff0c;循环语句 //选择分支语句 //if(){} int a 10; if (a < 13) { a; } if (a > 3) { a--; } Console.WriteLine(a);if(){}else{} 二选一 若if成立&#xff0c;则不去走else…

斐波那契数列前20项_牛客网 NC200607 A-解锁专家 斐波那契数列

目录目录1. 题目描述1.1. Limit1.2. Problem Description1.3. Input1.4. Output1.5. Sample Input1.6. Sample Output1.7. Notes1.8. Source2. 解读3. 代码1. 题目描述1.1. LimitTime Limit: 1000 msMemory Limit: 262144 kB1.2. Problem Description阿炳是一个精通文理的小机灵…