详述 Java 中 sort 排序函数
前言
手写一个排序算法的效率是很慢的,当然这也不利于我们在比赛或者工程中的实战,如今几乎每个语言的标准库中都有排序算法,今天让我来给大家讲解一下 Java 语言中的 sort 排序
升序排序
Collections 类中的 sort 方法可以实现 List 接口的集合进行排序
降序排序
Java 中降序排序有俩种方法(和 c++很类似,可以看我这篇博客):c++sort排序
利用 Collections.reverseOrder() 方法
实现 Comparator 接口的复写 compare() 方法
排序原理
对 sort 方法如何排序感到好奇?
通常,在看有关算法书籍的时候,会发现都说有关数组的排序算法,而且使用的都是随机访问,但是我们知道数组的随机访问是很快的,链表的随机访问很慢!实际上,可以使用一种归并排序的方法对链表高效的排序,不过,Java 并不是这样做的,它是将所有元素转入一个数组,对数组进行排序,然后,将排好序 的序列复制回列表
事实上 Collections.sort 方法底层就是调用的 Arrays.sort 方法,而 Arrays.sort 使用了两种排序方法,快速排序和优化的归并排序。
快速排序(quick)主要是对那些基本类型数据(int, short, long 等)排序, 而归并排序(merge)用于对 Object 类型进行排序。使用不同类型的排序算法主要是由于快速排序是不稳定的,而归并排序是稳定的。这里的稳定是指比较相等的数据在排序之后仍然按照排序之前的前后顺序排列。对于基本数据类型,稳定性没有意义,而对于 Object 类型,稳定性是比较重要的,因为对象相等的判断可能只是判断关键属性,最好保持相等对象的非关键属性的顺序与排序前一致;另外一个原因是由于归并排序相对而言比较次数比快速排序少,移动(对象引用的移动)次数比快速排序多,而对于对象来说,比较一般比移动耗时。此外,对大数组排序。快速排序的 sort()采用递归实现,数组规模太大时会发生堆栈溢出,而归并排序 sort()采用非递归实现,不存在此问题。
sort()是根据需要排序的数组的长度进行区分的:
首先先判断需要排序的数据量是否大于 60。小于 60:使用插入排序,插入排序是稳定的大于 60 的数据量会根据数据类型选择排序方式:基本类型:使用快速排序。「因为基本类型不需要考虑稳定性」Object 类型:使用归并排序「因为归并排序具有稳定性」
注意:不管是快速排序还是归并排序。在二分的时候小于 60 的数据量依旧会使用插入排序
关于稳定性,我们用下面这个例子来说明:
假设,有一个已经按照姓名排序的员工列表,现在我们要按照工资进行再次的排序,如果俩个员工的工资又刚好相同怎么办?如果采用稳定的排序方法,将会保留按照姓名的排序,换句话说,我们最后得到的是一个先按照姓名排序,又按照工资排序的一个表
版权声明: 本文为 InfoQ 作者【秋名山码民】的原创文章。
原文链接:【http://xie.infoq.cn/article/e1701f972a71e888b898f0f3d】。
本文遵守【CC-BY 4.0】协议,转载请保留原文出处及本版权声明。
评论