O(nlogn)快速排序-基礎版+詳細註釋
相關使用的工具類與介面
執行效率
/**
* 這是一個快速排序
* 陣列長度[2000] 值範圍[1-2000] 消耗的時間為[1]毫秒
* 陣列長度[4000] 值範圍[1-4000] 消耗的時間為[1]毫秒
* 陣列長度[8000] 值範圍[1-8000] 消耗的時間為[1]毫秒
* 陣列長度[16000] 值範圍[1-16000] 消耗的時間為[1]毫秒
* 陣列長度[32000] 值範圍[1-32000] 消耗的時間為[1]毫秒
* 陣列長度[64000] 值範圍[1-64000] 消耗的時間為[3]毫秒
* 陣列長度[128000] 值範圍[1-128000] 消耗的時間為[6]毫秒
* 陣列長度[256000] 值範圍[1-256000] 消耗的時間為[16]毫秒
* 陣列長度[512000] 值範圍[1-512000] 消耗的時間為[35]毫秒
* 陣列長度[1024000] 值範圍[1-1024000] 消耗的時間為[71]毫秒
* 陣列長度[2048000] 值範圍[1-2048000] 消耗的時間為[153]毫秒
* 陣列長度[4096000] 值範圍[1-4096000] 消耗的時間為[325]毫秒
* 陣列長度[8192000] 值範圍[1-8192000] 消耗的時間為[675]毫秒
* 陣列長度[16384000] 值範圍[1-16384000] 消耗的時間為[1397]毫秒
* 陣列長度[32768000] 值範圍[1-32768000] 消耗的時間為[2890]毫秒
* 陣列長度[65536000] 值範圍[1-65536000] 消耗的時間為[6031]毫秒
* 陣列長度[131072000] 值範圍[1-131072000] 消耗的時間為[12727]毫秒
* 陣列長度[262144000] 值範圍[1-262144000] 消耗的時間為[25993]毫秒
* <p>
* Process finished with exit code 0
*/
@Test
public void quickSortTest() {
ArraysSort arraysSort = new QuickSortMethod();
SortHelper.arraySort(arraysSort, 2000, 20);
}
實現程式碼
public static final Random RANDOM = new Random();
@Override
public String getSortName() {
return "這是一個快速排序";
}
@Override
public int[] arraySortMethod(int[] ints) {
sort(ints, 0, ints.length - 1);
return ints;
}
/**
* 最初的快排演算法邏輯
*
* @param ints 整個陣列
* @param l 當前最小索引
* @param r 當前最大索引
*/
private int quickSort(int[] ints, int l, int r) {
//這裡以每個l記錄進行比較
//但是這裡有個問題
//在快速排序處理近乎有序的陣列時 如果預設選取的是最左側索引節點
//這樣會造成左分塊除了l近乎沒有,右分塊又會出現很多
//以此迴圈會造成遞迴樹非常深 遞迴樹的深度可能就無限接近於n長度
//如果是這樣的話 該排序的時間效率就無限接近n^2
//每次隨機選取l-r一個索引 與l 索引進行交換就解決了該問題
SortHelper.swap(ints, l, RANDOM.nextInt(r - l + 1) + l);
int v = ints[l];
//初始化開始記錄比v小和比v大的中間索引點
//j理論上記錄的是比v小的最大索引
int j = l;
for (int i = l + 1; i <= r; i++) {
//如果出現比v小的情況
//就需要做交換 移動j的索引後移一格
if (ints[i] < v) {
//每次j+1=比v大一邊的第一個索引
//讓大一邊第一個索引和當前迴圈到的這個索引做交換
//以上交換後j+1=比v小一邊的最後一個索引
//之前比v大一邊的第一個索引就跑到i索引下 也是當時大一邊的最後一個索引
SortHelper.swap(ints, ++j, i);
}
}
//到這裡j記錄的就是比v小一邊的最大索引
//以上迴圈完成後就可以確定l索引在ints陣列中排序的位置
SortHelper.swap(ints, j, l);
//返回l在ints中排好序確定的索引位置 並以j分割繼續遞迴排序
return j;
}
/**
* 最初的快排演算法邏輯
*
* @param ints
* @param l
* @param r
*/
public void sort(int[] ints, int l, int r) {
//在出現左索引等於右索引的時候
//它們都是指向同一索引所以沒有相比的必要
//這裡直接返回
// if (l >= r) {
// return;
// }
//在資料量較小的時候使用插入排序
//這是因為經過了r-l>15的快速排序後 小一邊和大一邊的模糊排序後
//在r-l<=15 的時候之間的最大差已經很小了
//在最大差越小的情況下順序可能是越有序的
//說不定已經近乎有序的了 優化的快速排序對近乎有序的排序效率非常高
//優化後的插入排序對近乎有序的陣列進行效率相對較高
//插入排序相對歸併排序減少了陣列交換的過程
if (r - l <= 15) {
InsertSortMethod.insertSortMethod(ints, l, r);
return;
}
//個人理解快排核心
//每次遍歷排序對l-r之間的陣列進行區分
//好處1.每次遍歷可以定位一個p索引在ints陣列中確定的位置
//好處2.因為每次排序都對l-r之間的資料進行大小劃分做了一次模糊的排序
//保證下次排序l-r排序之間最大差越來越小
//所以下次遍歷都比上次排序更加有序效率相對更快
int p = quickSort(ints, l, r);
//以p中心點-1和+1為界限繼續遞迴快速排序
sort(ints, l, p - 1);
sort(ints, p + 1, r);
}
相關文章
- O(nlogn)快速排序-雙路排序+詳細註解排序
- 快速排序平均時間複雜度O(nlogn)的推導排序時間複雜度
- 基於GPUImage的美顏BeautifyFace詳細註釋GPUUI
- Java基礎-註釋Java
- 時間複雜度為O(nlogn)的排序演算法時間複雜度排序演算法
- 時間複雜度為 O(nlogn) 的排序演算法時間複雜度排序演算法
- Java基礎之字串String詳細解釋Java字串
- TERMIOS_H 詳細註釋iOS
- sqlHelper類的中文 詳細註釋SQL
- [java基礎]之註釋Java
- Java基礎01:註釋Java
- 0基礎,如何快速學習自媒體,詳細教程
- 演算法中的O(1), O(n),O(logn), O(nlogn)演算法
- java基礎註釋總結Java
- PHP基礎教程-05 註釋PHP
- O(lgn)的三種排序,快速排序、歸併排序、堆排序排序
- 【詳細】Python基礎(一)Python
- 「轉」Laravel 依賴注入原理(詳細註釋)Laravel依賴注入
- Bootstrap的Model原始碼詳細註釋 (轉)boot原始碼
- 時間複雜度O(1)、O(n)、O(n²)、O(nlogn)的含義時間複雜度
- QlikView Script 基礎教程1 - 註釋View
- PHP基礎演算法之快速排序法PHP演算法排序
- 超詳細Java基礎-多型Java多型
- SVG基礎教程(超級詳細)SVG
- JavaWeb—Servlet基礎(細節版,相當細節)JavaWebServlet
- I/O基礎
- Java基礎(五):包機制、文件註釋Java
- 資料結構 8 基礎排序演算法詳解、快速排序的實現、瞭解分治法資料結構排序演算法
- CreateJS入門 -- 註釋詳細到爆炸(My Style)JS
- JS實現輪播圖效果(有詳細註釋)JS
- 小白零基礎建站詳細教程
- python3.基礎爬取網易雲音樂【超詳細版】Python
- 最詳細的JavaWeb開發基礎之java環境搭建(Mac版)JavaWebMac
- 最詳細的JavaWeb開發基礎之java環境搭建(Windows版)JavaWebWindows
- Tarjan演算法及其應用 總結+詳細講解+詳細程式碼註釋演算法
- 【漫畫】為什麼說O(n)複雜度的基數排序沒有快速排序快?複雜度排序
- Python基礎語法–註釋說明Python
- JavaScript註釋:單行註釋和多行註釋詳解JavaScript