排序算法源碼剖析
首先在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;
}
}
}