Java的Arrays.sort()方法排序算法實(shí)例分析
暫時網(wǎng)上看過很多JDK8中Arrays.sort的底層原理,有些說是插入排序,有些說是歸并排序,也有說大于域值用計(jì)數(shù)排序法,否則就使用插入排序。。。其實(shí)不全對。讓我們分析個究竟:
// Use Quicksort on small arrays
if (right - left < QUICKSORT_THRESHOLD)
{
//QUICKSORT_THRESHOLD = 286
sort(a, left, right, true);
return;
}數(shù)組一進(jìn)來,會碰到第一個閥值QUICKSORT_THRESHOLD(286),注解上說,小過這個閥值的進(jìn)入Quicksort (快速排序),其實(shí)并不全是,點(diǎn)進(jìn)去sort(a, left, right, true);方法:
// Use insertion sort on tiny arrays
if (length < INSERTION_SORT_THRESHOLD)
{
if (leftmost)
{
......點(diǎn)進(jìn)去后我們看到第二個閥值INSERTION_SORT_THRESHOLD(47),如果元素少于47這個閥值,就用插入排序,往下看確實(shí)如此:
/*
* Traditional (without sentinel) insertion sort,
* optimized for server VM, is used in case of
* the leftmost part.
*/
for (int i = left, j = i; i < right; j = ++i)
{
int ai = a[i + 1];
while (ai < a[j])
{
a[j + 1] = a[j];
if (j-- == left)
{
break;
}
}
a[j + 1] = ai;
元素少于47用插入排序
至于大過INSERTION_SORT_THRESHOLD(47)的,用一種快速排序的方法:
1.從數(shù)列中挑出五個元素,稱為 “基準(zhǔn)”(pivot);
2.重新排序數(shù)列,所有元素比基準(zhǔn)值小的擺放在基準(zhǔn)前面,所有元素比基準(zhǔn)值大的擺在基準(zhǔn)的后面(相同的數(shù)可以到任一邊)。在這個分區(qū)退出之后,該基準(zhǔn)就處于數(shù)列的中間位置。這個稱為分區(qū)(partition)操作;
3.遞歸地(recursive)把小于基準(zhǔn)值元素的子數(shù)列和大于基準(zhǔn)值元素的子數(shù)列排序。
快速排序(Quick Sort)
這是少于閥值QUICKSORT_THRESHOLD(286)的兩種情況,至于大于286的,它會進(jìn)入歸并排序(Merge Sort),但在此之前,它有個小動作:
// Check if the array is nearly sorted
for (int k = left; k < right; run[count] = k) { if (a[k] < a[k + 1]) { // ascending
while (++k <= right && a[k - 1] <= a[k]);
} else if (a[k] > a[k + 1]) { // descending
while (++k <= right && a[k - 1] >= a[k]); for (int lo = run[count] - 1, hi = k; ++lo < --hi; ) { int t = a[lo]; a[lo] = a[hi]; a[hi] = t;
}
} else { // equal
for (int m = MAX_RUN_LENGTH; ++k <= right && a[k - 1] == a[k]; ) { if (--m == 0) {
sort(a, left, right, true); return;
}
}
} /*
* The array is not highly structured,
* use Quicksort instead of merge sort.
*/
if (++count == MAX_RUN_COUNT) {
sort(a, left, right, true); return;
}
}這里主要作用是看他數(shù)組具不具備結(jié)構(gòu):實(shí)際邏輯是分組排序,每降序?yàn)橐粋€組,像1,9,8,7,6,8。9到6是降序,為一個組,然后把降序的一組排成升序:1,6,7,8,9,8。然后最后的8后面繼續(xù)往后面找。
每遇到這樣一個降序組,++count,當(dāng)count大于MAX_RUN_COUNT(67),被判斷為這個數(shù)組不具備結(jié)構(gòu)(也就是這數(shù)據(jù)時而升時而降),然后送給之前的sort(里面的快速排序)的方法(The array is not highly structured,use Quicksort instead of merge sort.)
如果count少于MAX_RUN_COUNT(67)的,說明這個數(shù)組還有點(diǎn)結(jié)構(gòu),就繼續(xù)往下走下面的歸并排序。
總結(jié):
從上面分析,Arrays.sort并不是單一的排序,而是插入排序,快速排序,歸并排序三種排序的組合,為此我畫了個流程圖:

O(nlogn)只代表增長量級,同一個量級前面的常數(shù)也可以不一樣,不同數(shù)量下面的實(shí)際運(yùn)算時間也可以不一樣。
數(shù)量非常小的情況下(就像上面說到的,少于47的),插入排序等可能會比快速排序更快。 所以數(shù)組少于47的會進(jìn)入插入排序。
快排數(shù)據(jù)越無序越快(加入隨機(jī)化后基本不會退化),平均常數(shù)最小,不需要額外空間,不穩(wěn)定排序。
歸排速度穩(wěn)定,常數(shù)比快排略大,需要額外空間,穩(wěn)定排序。
所以大于或等于47或少于286會進(jìn)入快排,而在大于或等于286后,會有個小動作:“// Check if the array is nearly sorted”。這里第一個作用是先梳理一下數(shù)據(jù)方便后續(xù)的歸并排序,第二個作用就是即便大于286,但在降序組太多的時候(被判斷為沒有結(jié)構(gòu)的數(shù)據(jù),The array is not highly structured,use Quicksort instead of merge sort.),要轉(zhuǎn)回快速排序。
到此這篇關(guān)于Java的Arrays.sort()方法排序算法實(shí)例分析的文章就介紹到這了,更多相關(guān)Java的Arrays.sort()方法內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- java中Arrays.sort()排序方法舉例詳解
- Java Arrays.sort()如何實(shí)現(xiàn)對int類型數(shù)組倒序排序
- Java中Arrays.sort自定義一維數(shù)組、二維數(shù)組的排序方式
- Java使用lambda自定義Arrays.sort排序規(guī)則說明
- Java使用Arrays.sort()方法實(shí)現(xiàn)給對象排序
- Java Arrays.sort和Collections.sort排序?qū)崿F(xiàn)原理解析
- java通過Arrays.sort(int[] a)實(shí)現(xiàn)由大到小排序的方法實(shí)現(xiàn)
相關(guān)文章
Java class文件格式之屬性詳解_動力節(jié)點(diǎn)java學(xué)院整理
這篇文章主要介紹了Java class文件格式之屬性詳解,需要的朋友可以參考下2017-06-06
SpringCloud之監(jiān)控?cái)?shù)據(jù)聚合Turbine的實(shí)現(xiàn)
這篇文章主要介紹了SpringCloud之監(jiān)控?cái)?shù)據(jù)聚合Turbine的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-08-08
IDEA創(chuàng)建父項(xiàng)目和子項(xiàng)目的實(shí)現(xiàn)步驟
本文主要介紹了IDEA創(chuàng)建父項(xiàng)目和子項(xiàng)目的實(shí)現(xiàn)步驟,文中通過圖文介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2024-07-07
controller函數(shù)中參數(shù)列表使用多個@RequestBody問題
這篇文章主要介紹了controller函數(shù)中參數(shù)列表使用多個@RequestBody問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-04-04
Java構(gòu)造方法 super 及自定義異常throw合集詳解用法
異常是程序中的一些錯誤,但不是所有錯誤都是異常,且錯誤有時候是可以避免的,super可以理解為是指向自己超(父)類對象的一個指針,而這個超類指的是離自己最近的一個父類,構(gòu)造器也叫構(gòu)造方法、構(gòu)造函數(shù),是一種特殊類型的方法,負(fù)責(zé)類中成員變量(域)的初始化2021-10-10
基于html5+java實(shí)現(xiàn)大文件上傳實(shí)例代碼
本文通過一段實(shí)例代碼給大家介紹基于html5+java實(shí)現(xiàn)大文件上傳,涉及到html5 java 文件上傳相關(guān)知識,感興趣的朋友一起學(xué)習(xí)吧2016-01-01
SrpingDruid數(shù)據(jù)源加密數(shù)據(jù)庫密碼的示例代碼
本篇文章主要介紹了SrpingDruid數(shù)據(jù)源加密數(shù)據(jù)庫密碼的示例代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-10-10

