排序算法源码剖析
首先在eclipse 中使用Ctrl+鼠标左键查看源码发现 source not found ,出现这个问题很简单就是源码没有连接。把JDK 安装时的src.zip连接就可以
具体参考百度经验:http://jingyan.baidu.com/article/22a299b5234ecb9e19376ae1.html
首先说下Collections下面sort 方法两个使用场景。
场景一:对java 内置类型比如String、Integer 等进行排序,因为这些类型已经implements Comparable接口,所以这些类型排序最简单直接。
package javaUsage;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class LearningSortMethod {
public static void main(String[] args){
List<String> list = new ArrayList<>();
String[] strs = {"hello","world","good"};
for(String str:strs){
list.add(str);
}
System.out.println(list);
Collections.sort(list);
System.out.println(list);
Collections.reverse(list);
System.out.println(list);
}
}
输出结果:
[hello, world, good]
[good, hello, world]
[world, hello, good]
场景二:需要对自定义的对象就行排序,这是有两种方法。
方法1:自定义类implements Comparable并且重写 compareTo方法
构造了一个学生类,根据学生分数进行排名输出,见代码
package javaUsage;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class LearningSortMethod {
public static void main(String[] args){
List<StudentInof> list = new ArrayList<>();
StudentInof[] stus = {new StudentInof("alice", 85.0),new StudentInof("Tony", 75.0),
new StudentInof("Bob", 99.0)};
for(StudentInof stu:stus){
list.add(stu);
}
Collections.sort(list);
System.out.println(list);
Collections.reverse(list);
System.out.println(list);
}
}
class StudentInof implements Comparable<Object>{
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Double getScore() {
return score;
}
public void setScore(Double score) {
this.score = score;
}
private Double score;
public StudentInof(String name,Double score){
this.name = name;
this.score = score;
}
@Override
public int compareTo(Object o) {
StudentInof stu = (StudentInof) o;
Double otherScore = stu.getScore();
return this.score.compareTo(otherScore);
}
public String toString(){
return "name:"+this.getName() + " score:"+ this.getScore();
}
}
升序和逆序分别输出:
[name:Tony score:75.0, name:alice score:85.0, name:Bob score:99.0]
[name:Bob score:99.0, name:alice score:85.0, name:Tony score:75.0]
方法 2 :自己定义一个比较器类实现Comparator接口,然后Collections sort 方法传入比较器实例作为第二个参数
package javaUsage;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class LearningSortMethod {
public static void main(String[] args){
/**
List<StudentInof> list = new ArrayList<>();
StudentInof[] stus = {new StudentInof("alice", 85.0),new StudentInof("Tony", 75.0),
new StudentInof("Bob", 99.0)};
for(StudentInof stu:stus){
list.add(stu);
}
Collections.sort(list);
System.out.println(list);
Collections.reverse(list);
System.out.println(list);
*/
List<TeacherInfo> list = new ArrayList<>();
TeacherInfo[] techs = {new TeacherInfo(22, "shang"),new TeacherInfo(32, "chen"),
new TeacherInfo(18, "lin"),new TeacherInfo(10, "hu")};
for(TeacherInfo tech:techs){
list.add(tech);
}
MyCompartor mc = new MyCompartor();
Collections.sort(list, mc);
System.out.println(list);
}
}
class TeacherInfo {
private Integer age;
// Integer 类中 implements 了接口,而int 类型没有
public Integer getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
private String name;
public TeacherInfo(int age,String name){
this.age = age;
this.name = name;
}
public String toString(){
return "name:"+this.getName() + " age:"+ this.getAge();
}
}
class MyCompartor implements Comparator<Object>{
@Override
public int compare(Object o1, Object o2) {
// 根据Teacher信息age 排序
TeacherInfo t1 = (TeacherInfo)o1;
TeacherInfo t2 = (TeacherInfo)o2;
return t1.getAge().compareTo(t2.getAge());
}
}
升序和逆序排序输出:
[name:hu age:10, name:lin age:18, name:shang age:22, name:chen age:32]
上面主要还是涉及如何使用,下面主要涉及实现源码(JDK 1.7)部分:
public static <T extends Comparable<? super T>> void sort(List<T> list) {
Object[] a = list.toArray();
Arrays.sort(a);
ListIterator<T> i = list.listIterator();
for (int j=0; j<a.length; j++) {
i.next();
i.set((T)a[j]);
}
}
public static <T> void sort(List<T> list, Comparator<? super T> c) {
Object[] a = list.toArray();
Arrays.sort(a, (Comparator)c);
ListIterator i = list.listIterator();
for (int j=0; j<a.length; j++) {
i.next();
i.set(a[j]);
}
}
查看了这两个方法参数就明白为什么需要implements Comparable接口或者 创建自己 Comparator类。
当然还可以发现一个问题 Collections sort 方法底层其实就是 Arrays 的sort 方法,接下来继续看Arrays 的sort 方法。
public static void sort(Object[] a) {
if (LegacyMergeSort.userRequested)
legacyMergeSort(a);
else
ComparableTimSort.sort(a);
}
private static void legacyMergeSort(Object[] a) {
Object[] aux = a.clone();
mergeSort(aux, a, 0, a.length, 0);
}
核心是mergeSort函数
private static void mergeSort(Object[] src,
Object[] dest,
int low,
int high,
int off) {
int length = high - low;
// Insertion sort on smallest arrays
if (length < INSERTIONSORT_THRESHOLD) {
for (int i=low; i<high; i++)
for (int j=i; j>low &&
((Comparable) dest[j-1]).compareTo(dest[j])>0; j--)
swap(dest, j, j-1);
return;
}
// Recursively sort halves of dest into src
int destLow = low;
int destHigh = high;
low += off;
high += off;
int mid = (low + high) >>> 1;
mergeSort(dest, src, low, mid, -off);
mergeSort(dest, src, mid, high, -off);
// If list is already sorted, just copy from src to dest. This is an
// optimization that results in faster sorts for nearly ordered lists.
if (((Comparable)src[mid-1]).compareTo(src[mid]) <= 0) {
System.arraycopy(src, low, dest, destLow, length);
return;
}
// Merge sorted halves (now in src) into dest
for(int i = destLow, p = low, q = mid; i < destHigh; i++) {
if (q >= high || p < mid && ((Comparable)src[p]).compareTo(src[q])<=0)
dest[i] = src[p++];
else
dest[i] = src[q++];
}
}
所以可以确定一个事情就是 Collections 排序和Arrays 排序都是底层 mergeSort实现,但是文档也说了,不一定必须要是mergesort但是必须要是稳定的排序算法。
Comparable & Comparator
Sorts the specified list into ascending order, according to the natural ordering of its elements. All elements in the list must implement the Comparable interface
这里的自然顺序就是实现Comparable接口设定的排序方式。
package javaUsage;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Random;
public class TestComparator {
public static void main(String[] args) {
Random rnd = new Random();
Integer[] integers = new Integer[20];
for (int i = 0; i < integers.length; i++)
integers[i] = new Integer(rnd.nextInt(100)
* (rnd.nextBoolean() ? 1 : -1));
System.out.println("用Integer内置方法排序:");
Arrays.sort(integers);
System.out.println(Arrays.asList(integers));
System.out.println("用AbsComparator排序:");
Arrays.sort(integers, new AbsComparator());
System.out.println(Arrays.asList(integers));
}
}
class AbsComparator implements Comparator<Object> {
public int compare(Object o1, Object o2) {
int v1 = Math.abs(((Integer) o1).intValue());
int v2 = Math.abs(((Integer) o2).intValue());
return v1 > v2 ? 1 : (v1 == v2 ? 0 : -1);
}
}
用Integer内置方法排序:
[-92, -88, -84, -84, -74, -63, -56, -26, -19, 29, 35, 52, 73, 78, 79, 79, 83, 87, 90, 99]
用AbsComparator排序:
[-19, -26, 29, 35, 52, -56, -63, 73, -74, 78, 79, 79, 83, -84, -84, 87, -88, 90, -92, 99]
京东在线笔试编程题
package contest;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Scanner;
// 京东在线编程题
public class MaxLetters {
public static void ShowInfo(int letters[][]){
for(int i=0;i<letters.length;i++){
System.out.println(letters[i][0]+":"+letters[i][1]);
}
System.out.println("------");
}
public static int FindIndex(int[]letter,int[][]letters){
int i ;
for(i=0;i<letters.length;i++){
if(letters[i][0]==letter[0] && letters[i][1]==letter[1]){
break;
}
}
return i;
}
public static void main(String[] args) {
int n,w,h;
@SuppressWarnings("resource")
Scanner sc = new Scanner(System.in);
while(sc.hasNext()){
n = sc.nextInt();
w = sc.nextInt();
h = sc.nextInt();
int [][]letters = new int[n][2];
int [][]copy = new int[n][2];
for(int i=0;i<n;i++){
letters[i] = new int[2];
copy[i] = new int[2];
letters[i][0] = sc.nextInt();
letters[i][1] = sc.nextInt();
copy[i][0] = letters[i][0];
copy[i][1] = letters[i][1];
}
ShowInfo(letters);
ShowInfo(copy);
Mycomparator my = new Mycomparator();
Arrays.sort(letters,my);
ShowInfo(letters);
int index = 0;
int count = 0;
int []res = new int[letters.length];
for(int i=0;i<letters.length;i++){
for(int j=index;j<letters.length;j++){
if(w < letters[j][0] && h < letters[j][1]){
res[count] = FindIndex(letters[j], copy)+1;
count++;
index = j;
w = letters[j][0];
h = letters[j][1];
}
}
}
if(count == 0){
System.out.println(0);
}else{
System.out.println(count);
for(int i=0;i<count;i++){
System.out.print(res[i]+" ");
}
System.out.println();
}
}
}
}
class Mycomparator implements Comparator<Object>{
@Override
public int compare(Object o1, Object o2) {
int[] letter1 = (int[])o1;
int[] letter2 = (int[])o2;
if(letter1[0] > letter2[0] && letter1[1] < letter2[1]){
return 1;
}
else if(letter1[0] < letter2[0] && letter1[1] < letter2[1]){
return -1;
}else{
return 0;
}
}
}