參考:【todo】
https://blog.csdn.net/realYuzhou/article/details/109299625
https://blog.csdn.net/duuuhs/article/details/89167231
https://www.jianshu.com/p/e2b7256163ae
Arrays.sort使用的排序算法
java中Arrays.sort使用了兩種排序方法,快速排序和優化的歸並排序。
快速排序主要是對哪些基本類型數據(int,short,long等)排序, 而合並排序用於對對象類型進行排序。使用不同類型的排序算法主要是由於快速排序是不穩定的,而合並排序是穩定的
歸並排序相對而言比較次數比快速排序少,移動(對象引用的移動)次數比快速排序多,而對於對象來說,比較一般比移動耗時。補充一點合並排序的時間復雜度是nlogn, 快速排序的平均時間復雜度也是nlogn,但是合並排序的需要額外的n個引用的空間。
import java.util.Arrays; import java.util.Comparator; public class ArraySort { public static void main(String[] args) { Dog d2 = new Dog(2); Dog d1 = new Dog(1); Dog d3 = new Dog(3); Dog[] dogArray = {d3,d1,d2}; printDog(dogArray); Arrays.sort(dogArray,new DogSizeComparator()); printDog(dogArray); } public static void printDog(Dog[] dogs){ for (Dog dog:dogs) { System.out.println(dog.size+" "); } System.out.println(); } } class Dog{ int size; public Dog(int s){ this.size = s; } } class DogSizeComparator implements Comparator<Dog> { @Override public int compare(Dog o1, Dog o2) { return o1.size - o2.size; } }
源碼中的快速排序,主要做了以下幾個方面的優化:
1)當待排序的數組中的元素個數較少時,源碼中的閥值為7,采用的是插入排序。盡管插入排序的時間復雜度為0(n^2),但是當數組元素較少時,插入排序優於快速排序,因為這時快速排序的遞歸操作影響性能。
2)較好的選擇了划分元(基准元素)。能夠將數組分成大致兩個相等的部分,避免出現最壞的情況。例如當數組有序的的情況下,選擇第一個元素作為划分元,將使得算法的時間復雜度達到O(n^2).
3)根據划分元 v ,形成不變式 v* (
源碼中選擇划分元的方法:
1)當數組大小為 size=7 時 ,取數組中間元素作為划分元。int n=m>>1;(此方法值得借鑒)。
2)當數組大小size大於7小於等於40時,取首、中、末三個元素中間大小的元素作為划分元。
3)當數組大小 size>40 時 ,從待排數組中較均勻的選擇9個元素,選出一個偽中數做為划分元。
普通的快速排序算法,經過一次划分后,將划分元排到素組較中間的位置,左邊的元素小於划分元,右邊的元素大於划分元,而沒有將與划分元相等的元素放在其附近,這一點,在Arrays.sort()中得到了較大的優化。
舉例:15、93、15、41、6、15、22、7、15、20
舉例:15、93、15、41、6、15、22、7、15、20
因size大於7小於等於40 ,所以在15、6、和20 中選擇v = 15 作為划分元。
經過一次換分后: 15、15、7、6、41、20、22、93、15、15. 與划分元相等的元素都移到了素組的兩邊。
接下來將與划分元相等的元素移到數組中間來,形成:7、6、15、15、15、15、41、20、22、93.
最后遞歸對兩個區間進行排序[7、6]和[41、20、22、93].,所以在15、6、和20 中選擇v = 15 作為划分元。