精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

動畫+原理+代碼,解讀十大經典排序算法

開發 后端 算法
排序算法可以分為內部排序和外部排序,內部排序是數據記錄在內存中進行排序,而外部排序是因排序的數據很大,一次不能容納全部的排序記錄,在排序過程中需要訪問外存。常見的內部排序算法有:插入排序、希爾排序、選擇排序、冒泡排序、歸并排序、快速排序、堆排序、基數排序等。

排序算法是《數據結構與算法》中最基本的算法之一。

排序算法可以分為內部排序和外部排序,內部排序是數據記錄在內存中進行排序,而外部排序是因排序的數據很大,一次不能容納全部的排序記錄,在排序過程中需要訪問外存。常見的內部排序算法有:插入排序、希爾排序、選擇排序、冒泡排序、歸并排序、快速排序、堆排序、基數排序等。用一張圖概括: 

關于時間復雜度:

  1. 平方階 (O(n2)) 排序 各類簡單排序:直接插入、直接選擇和冒泡排序。
  2. 線性對數階 (O(nlog2n)) 排序 快速排序、堆排序和歸并排序。
  3. O(n1+§)) 排序,§ 是介于 0 和 1 之間的常數。 希爾排序。
  4. 線性階 (O(n)) 排序 基數排序,此外還有桶、箱排序。

關于穩定性:

穩定的排序算法:冒泡排序、插入排序、歸并排序和基數排序。

不是穩定的排序算法:選擇排序、快速排序、希爾排序、堆排序。

名詞解釋:

n:數據規模

k:“桶”的個數

In-place:占用常數內存,不占用額外內存

Out-place:占用額外內存

穩定性:排序后 2 個相等鍵值的順序和排序之前它們的順序相同

一、冒泡排序

冒泡排序(Bubble Sort)也是一種簡單直觀的排序算法。它重復地走訪過要排序的數列,一次比較兩個元素,如果他們的順序錯誤就把他們交換過來。走訪數列的工作是重復地進行直到沒有再需要交換,也就是說該數列已經排序完成。這個算法的名字由來是因為越小的元素會經由交換慢慢“浮”到數列的頂端。

作為最簡單的排序算法之一,冒泡排序給我的感覺就像 Abandon 在單詞書里出現的感覺一樣,每次都在***頁***位,所以最熟悉。冒泡排序還有一種優化算法,就是立一個 flag,當在一趟序列遍歷中元素沒有發生交換,則證明該序列已經有序。但這種改進對于提升性能來說并沒有什么太大作用。

1. 算法步驟

  1. 比較相鄰的元素。如果***個比第二個大,就交換他們兩個。
  2. 對每一對相鄰元素作同樣的工作,從開始***對到結尾的***一對。這步做完后,***的元素會是***的數。
  3. 針對所有的元素重復以上的步驟,除了***一個。
  4. 持續每次對越來越少的元素重復上面的步驟,直到沒有任何一對數字需要比較。

2. 動圖演示 

3. 什么時候最快

當輸入的數據已經是正序時(都已經是正序了,我還要你冒泡排序有何用啊)。

4. 什么時候最慢

當輸入的數據是反序時(寫一個 for 循環反序輸出數據不就行了,干嘛要用你冒泡排序呢,我是閑的嗎)。

5. Java 代碼實現 

  1. public class BubbleSort implements IArraySort {  
  2.     @Override 
  3.     public int[] sort(int[] sourceArray) throws Exception { 
  4.         // 對 arr 進行拷貝,不改變參數內容 
  5.         int[] arr = Arrays.copyOf(sourceArray, sourceArray.length); 
  6.  
  7.         for (int i = 1; i < arr.length; i++) { 
  8.             // 設定一個標記,若為true,則表示此次循環沒有進行交換,也就是待排序列已經有序,排序已經完成。 
  9.             boolean flag = true
  10.  
  11.             for (int j = 0; j < arr.length - i; j++) { 
  12.                 if (arr[j] > arr[j + 1]) { 
  13.                     int tmp = arr[j]; 
  14.                     arr[j] = arr[j + 1]; 
  15.                     arr[j + 1] = tmp; 
  16.  
  17.                     flag = false
  18.                 } 
  19.             } 
  20.  
  21.             if (flag) { 
  22.                 break; 
  23.             } 
  24.         } 
  25.         return arr; 
  26.     } 

二、選擇排序

選擇排序是一種簡單直觀的排序算法,無論什么數據進去都是 O(n²) 的時間復雜度。所以用到它的時候,數據規模越小越好。唯一的好處可能就是不占用額外的內存空間了吧。

1. 算法步驟

  1. 首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置
  2. 再從剩余未排序元素中繼續尋找最小(大)元素,然后放到已排序序列的末尾。
  3. 重復第二步,直到所有元素均排序完畢。

2. 動圖演示 

3. Java 代碼實現 

  1. public class SelectionSort implements IArraySort {  
  2.     @Override 
  3.     public int[] sort(int[] sourceArray) throws Exception { 
  4.         int[] arr = Arrays.copyOf(sourceArray, sourceArray.length); 
  5.  
  6.         // 總共要經過 N-1 輪比較 
  7.         for (int i = 0; i < arr.length - 1; i++) { 
  8.             int min = i; 
  9.  
  10.             // 每輪需要比較的次數 N-i 
  11.             for (int j = i + 1; j < arr.length; j++) { 
  12.                 if (arr[j] < arr[min]) { 
  13.                     // 記錄目前能找到的最小值元素的下標 
  14.                     min = j; 
  15.                 } 
  16.             } 
  17.  
  18.             // 將找到的最小值和i位置所在的值進行交換 
  19.             if (i != min) { 
  20.                 int tmp = arr[i]; 
  21.                 arr[i] = arr[min]; 
  22.                 arr[min] = tmp; 
  23.             } 
  24.  
  25.         } 
  26.         return arr; 
  27.     } 

三、插入排序

插入排序的代碼實現雖然沒有冒泡排序和選擇排序那么簡單粗暴,但它的原理應該是最容易理解的了,因為只要打過撲克牌的人都應該能夠秒懂。插入排序是一種最簡單直觀的排序算法,它的工作原理是通過構建有序序列,對于未排序數據,在已排序序列中從后向前掃描,找到相應位置并插入。

插入排序和冒泡排序一樣,也有一種優化算法,叫做拆半插入。

1. 算法步驟

  • 將***待排序序列***個元素看做一個有序序列,把第二個元素到***一個元素當成是未排序序列。
  • 從頭到尾依次掃描未排序序列,將掃描到的每個元素插入有序序列的適當位置。(如果待插入的元素與有序序列中的某個元素相等,則將待插入元素插入到相等元素的后面。)

2. 動圖演示 

3. Java 代碼實現

  1. public class InsertSort implements IArraySort {  
  2.     @Override 
  3.     public int[] sort(int[] sourceArray) throws Exception { 
  4.         // 對 arr 進行拷貝,不改變參數內容 
  5.         int[] arr = Arrays.copyOf(sourceArray, sourceArray.length); 
  6.  
  7.         // 從下標為1的元素開始選擇合適的位置插入,因為下標為0的只有一個元素,默認是有序的 
  8.         for (int i = 1; i < arr.length; i++) { 
  9.  
  10.             // 記錄要插入的數據 
  11.             int tmp = arr[i]; 
  12.  
  13.             // 從已經排序的序列最右邊的開始比較,找到比其小的數 
  14.             int j = i; 
  15.             while (j > 0 && tmp < arr[j - 1]) { 
  16.                 arr[j] = arr[j - 1]; 
  17.                 j--; 
  18.             } 
  19.  
  20.             // 存在比其小的數,插入 
  21.             if (j != i) { 
  22.                 arr[j] = tmp; 
  23.             } 
  24.  
  25.         } 
  26.         return arr; 
  27.     } 

四、希爾排序

希爾排序,也稱遞減增量排序算法,是插入排序的一種更高效的改進版本。但希爾排序是非穩定排序算法。

希爾排序是基于插入排序的以下兩點性質而提出改進方法的:

  • 插入排序在對幾乎已經排好序的數據操作時,效率高,即可以達到線性排序的效率
  • 但插入排序一般來說是低效的,因為插入排序每次只能將數據移動一位

希爾排序的基本思想是:先將整個待排序的記錄序列分割成為若干子序列分別進行直接插入排序,待整個序列中的記錄“基本有序”時,再對全體記錄進行依次直接插入排序。

1. 算法步驟

  1. 選擇一個增量序列 t1,t2,……,tk,其中 ti > tj, tk = 1;
  2. 按增量序列個數 k,對序列進行 k 趟排序;
  3. 每趟排序,根據對應的增量 ti,將待排序列分割成若干長度為 m 的子序列,分別對各子表進行直接插入排序。僅增量因子為 1 時,整個序列作為一個表來處理,表長度即為整個序列的長度。

2. Java 代碼實現 

  1. public class ShellSort implements IArraySort {  
  2.     @Override 
  3.     public int[] sort(int[] sourceArray) throws Exception { 
  4.         // 對 arr 進行拷貝,不改變參數內容 
  5.         int[] arr = Arrays.copyOf(sourceArray, sourceArray.length); 
  6.  
  7.         int gap = 1; 
  8.         while (gap < arr.length) { 
  9.             gap = gap * 3 + 1; 
  10.         } 
  11.  
  12.         while (gap > 0) { 
  13.             for (int i = gap; i < arr.length; i++) { 
  14.                 int tmp = arr[i]; 
  15.                 int j = i - gap; 
  16.                 while (j >= 0 && arr[j] > tmp) { 
  17.                     arr[j + gap] = arr[j]; 
  18.                     j -= gap; 
  19.                 } 
  20.                 arr[j + gap] = tmp; 
  21.             } 
  22.             gap = (int) Math.floor(gap / 3); 
  23.         } 
  24.  
  25.         return arr; 
  26.     } 

五、歸并排序

歸并排序(Merge sort)是建立在歸并操作上的一種有效的排序算法。該算法是采用分治法(Divide and Conquer)的一個非常典型的應用。

作為一種典型的分而治之思想的算法應用,歸并排序的實現由兩種方法:

  • 自上而下的遞歸(所有遞歸的方法都可以用迭代重寫,所以就有了第 2 種方法)
  • 自下而上的迭代

在《數據結構與算法 JavaScript 描述》中,作者給出了自下而上的迭代方法。但是對于遞歸法,作者卻認為:

However, it is not possible to do so in JavaScript, as the recursion goes too deep for the language to handle.

然而,在 JavaScript 中這種方式不太可行,因為這個算法的遞歸深度對它來講太深了。

說實話,我不太理解這句話。意思是 JavaScript 編譯器內存太小,遞歸太深容易造成內存溢出嗎?還望有大神能夠指教。

和選擇排序一樣,歸并排序的性能不受輸入數據的影響,但表現比選擇排序好的多,因為始終都是 O(nlogn) 的時間復雜度。代價是需要額外的內存空間。

1. 算法步驟

  1. 申請空間,使其大小為兩個已經排序序列之和,該空間用來存放合并后的序列;
  2. 設定兩個指針,最初位置分別為兩個已經排序序列的起始位置;
  3. 比較兩個指針所指向的元素,選擇相對小的元素放入到合并空間,并移動指針到下一位置;
  4. 重復步驟 3 直到某一指針達到序列尾;
  5. 將另一序列剩下的所有元素直接復制到合并序列尾。

2. 動圖演示 

3. Java 代碼實現 

  1. public class MergeSort implements IArraySort {  
  2.     @Override 
  3.     public int[] sort(int[] sourceArray) throws Exception { 
  4.         // 對 arr 進行拷貝,不改變參數內容 
  5.         int[] arr = Arrays.copyOf(sourceArray, sourceArray.length); 
  6.  
  7.         if (arr.length < 2) { 
  8.             return arr; 
  9.         } 
  10.         int middle = (int) Math.floor(arr.length / 2); 
  11.  
  12.         int[] left = Arrays.copyOfRange(arr, 0, middle); 
  13.         int[] right = Arrays.copyOfRange(arr, middle, arr.length); 
  14.  
  15.         return merge(sort(left), sort(right)); 
  16.     } 
  17.  
  18.     protected int[] merge(int[] leftint[] right) { 
  19.         int[] result = new int[left.length + right.length]; 
  20.         int i = 0; 
  21.         while (left.length > 0 && right.length > 0) { 
  22.             if (left[0] <= right[0]) { 
  23.                 result[i++] = left[0]; 
  24.                 left = Arrays.copyOfRange(left, 1, left.length); 
  25.             } else { 
  26.                 result[i++] = right[0]; 
  27.                 right = Arrays.copyOfRange(right, 1, right.length); 
  28.             } 
  29.         } 
  30.  
  31.         while (left.length > 0) { 
  32.             result[i++] = left[0]; 
  33.             left = Arrays.copyOfRange(left, 1, left.length); 
  34.         } 
  35.  
  36.         while (right.length > 0) { 
  37.             result[i++] = right[0]; 
  38.             right = Arrays.copyOfRange(right, 1, right.length); 
  39.         } 
  40.  
  41.         return result; 
  42.     } 
  43.  

六、快速排序

快速排序是由東尼·霍爾所發展的一種排序算法。在平均狀況下,排序 n 個項目要 Ο(nlogn) 次比較。在最壞狀況下則需要 Ο(n2) 次比較,但這種狀況并不常見。事實上,快速排序通常明顯比其他 Ο(nlogn) 算法更快,因為它的內部循環(inner loop)可以在大部分的架構上很有效率地被實現出來。

快速排序使用分治法(Divide and conquer)策略來把一個串行(list)分為兩個子串行(sub-lists)。

快速排序又是一種分而治之思想在排序算法上的典型應用。本質上來看,快速排序應該算是在冒泡排序基礎上的遞歸分治法。

快速排序的名字起的是簡單粗暴,因為一聽到這個名字你就知道它存在的意義,就是快,而且效率高!它是處理大數據最快的排序算法之一了。雖然 Worst Case 的時間復雜度達到了 O(n²),但是人家就是優秀,在大多數情況下都比平均時間復雜度為 O(n logn) 的排序算法表現要更好,可是這是為什么呢,我也不知道。好在我的強迫癥又犯了,查了 N 多資料終于在《算法藝術與信息學競賽》上找到了滿意的答案:

快速排序的最壞運行情況是 O(n²),比如說順序數列的快排。但它的平攤期望時間是 O(nlogn),且 O(nlogn) 記號中隱含的常數因子很小,比復雜度穩定等于 O(nlogn) 的歸并排序要小很多。所以,對絕大多數順序性較弱的隨機數列而言,快速排序總是優于歸并排序。

1. 算法步驟

  1. 從數列中挑出一個元素,稱為 “基準”(pivot);
  2. 重新排序數列,所有元素比基準值小的擺放在基準前面,所有元素比基準值大的擺在基準的后面(相同的數可以到任一邊)。在這個分區退出之后,該基準就處于數列的中間位置。這個稱為分區(partition)操作;
  3. 遞歸地(recursive)把小于基準值元素的子數列和大于基準值元素的子數列排序;

遞歸的***部情形,是數列的大小是零或一,也就是永遠都已經被排序好了。雖然一直遞歸下去,但是這個算法總會退出,因為在每次的迭代(iteration)中,它至少會把一個元素擺到它***的位置去。

2. 動圖演示 

3. Java 代碼實現 

  1. public class QuickSort implements IArraySort {  
  2.     @Override 
  3.     public int[] sort(int[] sourceArray) throws Exception { 
  4.         // 對 arr 進行拷貝,不改變參數內容 
  5.         int[] arr = Arrays.copyOf(sourceArray, sourceArray.length); 
  6.  
  7.         return quickSort(arr, 0, arr.length - 1); 
  8.     } 
  9.  
  10.     private int[] quickSort(int[] arr, int leftint right) { 
  11.         if (left < right) { 
  12.             int partitionIndex = partition(arr, leftright); 
  13.             quickSort(arr, left, partitionIndex - 1); 
  14.             quickSort(arr, partitionIndex + 1, right); 
  15.         } 
  16.         return arr; 
  17.     } 
  18.  
  19.     private int partition(int[] arr, int leftint right) { 
  20.         // 設定基準值(pivot) 
  21.         int pivot = left
  22.         int index = pivot + 1; 
  23.         for (int i = index; i <= right; i++) { 
  24.             if (arr[i] < arr[pivot]) { 
  25.                 swap(arr, i, index); 
  26.                 index++; 
  27.             } 
  28.         } 
  29.         swap(arr, pivot, index - 1); 
  30.         return index - 1; 
  31.     } 
  32.  
  33.     private void swap(int[] arr, int i, int j) { 
  34.         int temp = arr[i]; 
  35.         arr[i] = arr[j]; 
  36.         arr[j] = temp
  37.     } 
  38.  

七、堆排序

堆排序(Heapsort)是指利用堆這種數據結構所設計的一種排序算法。堆積是一個近似完全二叉樹的結構,并同時滿足堆積的性質:即子結點的鍵值或索引總是小于(或者大于)它的父節點。堆排序可以說是一種利用堆的概念來排序的選擇排序。分為兩種方法:

  1. 大頂堆:每個節點的值都大于或等于其子節點的值,在堆排序算法中用于升序排列;
  2. 小頂堆:每個節點的值都小于或等于其子節點的值,在堆排序算法中用于降序排列;

堆排序的平均時間復雜度為 Ο(nlogn)。

1. 算法步驟

  1. 創建一個堆 H[0……n-1];
  2. 把堆首(***值)和堆尾互換;
  3. 把堆的尺寸縮小 1,并調用 shift_down(0),目的是把新的數組頂端數據調整到相應位置;
  4. 重復步驟 2,直到堆的尺寸為 1。

2. 動圖演示 

3. Java 代碼實現 

  1. public class HeapSort implements IArraySort {  
  2.     @Override 
  3.     public int[] sort(int[] sourceArray) throws Exception { 
  4.         // 對 arr 進行拷貝,不改變參數內容 
  5.         int[] arr = Arrays.copyOf(sourceArray, sourceArray.length); 
  6.  
  7.         int len = arr.length; 
  8.  
  9.         buildMaxHeap(arr, len); 
  10.  
  11.         for (int i = len - 1; i > 0; i--) { 
  12.             swap(arr, 0, i); 
  13.             len--; 
  14.             heapify(arr, 0, len); 
  15.         } 
  16.         return arr; 
  17.     } 
  18.  
  19.     private void buildMaxHeap(int[] arr, int len) { 
  20.         for (int i = (int) Math.floor(len / 2); i >= 0; i--) { 
  21.             heapify(arr, i, len); 
  22.         } 
  23.     } 
  24.  
  25.     private void heapify(int[] arr, int i, int len) { 
  26.         int left = 2 * i + 1; 
  27.         int right = 2 * i + 2; 
  28.         int largest = i; 
  29.  
  30.         if (left < len && arr[left] > arr[largest]) { 
  31.             largest = left
  32.         } 
  33.  
  34.         if (right < len && arr[right] > arr[largest]) { 
  35.             largest = right
  36.         } 
  37.  
  38.         if (largest != i) { 
  39.             swap(arr, i, largest); 
  40.             heapify(arr, largest, len); 
  41.         } 
  42.     } 
  43.  
  44.     private void swap(int[] arr, int i, int j) { 
  45.         int temp = arr[i]; 
  46.         arr[i] = arr[j]; 
  47.         arr[j] = temp
  48.     } 
  49.  

八、計數排序

計數排序的核心在于將輸入的數據值轉化為鍵存儲在額外開辟的數組空間中。作為一種線性時間復雜度的排序,計數排序要求輸入的數據必須是有確定范圍的整數。

1. 動圖演示 

2. Java 代碼實現 

  1. public class CountingSort implements IArraySort {  
  2.     @Override 
  3.     public int[] sort(int[] sourceArray) throws Exception { 
  4.         // 對 arr 進行拷貝,不改變參數內容 
  5.         int[] arr = Arrays.copyOf(sourceArray, sourceArray.length); 
  6.  
  7.         int maxValue = getMaxValue(arr); 
  8.  
  9.         return countingSort(arr, maxValue); 
  10.     } 
  11.  
  12.     private int[] countingSort(int[] arr, int maxValue) { 
  13.         int bucketLen = maxValue + 1; 
  14.         int[] bucket = new int[bucketLen]; 
  15.  
  16.         for (int value : arr) { 
  17.             bucket[value]++; 
  18.         } 
  19.  
  20.         int sortedIndex = 0; 
  21.         for (int j = 0; j < bucketLen; j++) { 
  22.             while (bucket[j] > 0) { 
  23.                 arr[sortedIndex++] = j; 
  24.                 bucket[j]--; 
  25.             } 
  26.         } 
  27.         return arr; 
  28.     } 
  29.  
  30.     private int getMaxValue(int[] arr) { 
  31.         int maxValue = arr[0]; 
  32.         for (int value : arr) { 
  33.             if (maxValue < value) { 
  34.                 maxValue = value; 
  35.             } 
  36.         } 
  37.         return maxValue; 
  38.     } 
  39.  

九、桶排序

桶排序是計數排序的升級版。它利用了函數的映射關系,高效與否的關鍵就在于這個映射函數的確定。為了使桶排序更加高效,我們需要做到這兩點:

  • 在額外空間充足的情況下,盡量增大桶的數量
  • 使用的映射函數能夠將輸入的 N 個數據均勻的分配到 K 個桶中

同時,對于桶中元素的排序,選擇何種比較排序算法對于性能的影響至關重要。

1. 什么時候最快

當輸入的數據可以均勻的分配到每一個桶中。

2. 什么時候最慢

當輸入的數據被分配到了同一個桶中。

3. Java 代碼實現 

  1. public class BucketSort implements IArraySort { 
  2.  
  3.     private static final InsertSort insertSort = new InsertSort(); 
  4.  
  5.     @Override 
  6.     public int[] sort(int[] sourceArray) throws Exception { 
  7.         // 對 arr 進行拷貝,不改變參數內容 
  8.         int[] arr = Arrays.copyOf(sourceArray, sourceArray.length); 
  9.  
  10.         return bucketSort(arr, 5); 
  11.     } 
  12.  
  13.     private int[] bucketSort(int[] arr, int bucketSize) throws Exception { 
  14.         if (arr.length == 0) { 
  15.             return arr; 
  16.         } 
  17.  
  18.         int minValue = arr[0]; 
  19.         int maxValue = arr[0]; 
  20.         for (int value : arr) { 
  21.             if (value < minValue) { 
  22.                 minValue = value; 
  23.             } else if (value > maxValue) { 
  24.                 maxValue = value; 
  25.             } 
  26.         } 
  27.  
  28.         int bucketCount = (int) Math.floor((maxValue - minValue) / bucketSize) + 1; 
  29.         int[][] buckets = new int[bucketCount][0]; 
  30.  
  31.         // 利用映射函數將數據分配到各個桶中 
  32.         for (int i = 0; i < arr.length; i++) { 
  33.             int index = (int) Math.floor((arr[i] - minValue) / bucketSize); 
  34.             buckets[index] = arrAppend(buckets[index], arr[i]); 
  35.         } 
  36.  
  37.         int arrIndex = 0; 
  38.         for (int[] bucket : buckets) { 
  39.             if (bucket.length <= 0) { 
  40.                 continue
  41.             } 
  42.             // 對每個桶進行排序,這里使用了插入排序 
  43.             bucket = insertSort.sort(bucket); 
  44.             for (int value : bucket) { 
  45.                 arr[arrIndex++] = value; 
  46.             } 
  47.         } 
  48.  
  49.         return arr; 
  50.     } 
  51.  
  52.     /** 
  53.      * 自動擴容,并保存數據 
  54.      * 
  55.      * @param arr 
  56.      * @param value 
  57.      */ 
  58.     private int[] arrAppend(int[] arr, int value) { 
  59.         arr = Arrays.copyOf(arr, arr.length + 1); 
  60.         arr[arr.length - 1] = value; 
  61.         return arr; 
  62.     } 
  63.  

十、基數排序

基數排序是一種非比較型整數排序算法,其原理是將整數按位數切割成不同的數字,然后按每個位數分別比較。由于整數也可以表達字符串(比如名字或日期)和特定格式的浮點數,所以基數排序也不是只能使用于整數。

1. 基數排序 vs 計數排序 vs 桶排序

基數排序有兩種方法:

這三種排序算法都利用了桶的概念,但對桶的使用方法上有明顯差異:

  • 基數排序:根據鍵值的每位數字來分配桶;
  • 計數排序:每個桶只存儲單一鍵值;
  • 桶排序:每個桶存儲一定范圍的數值;

2. LSD 基數排序動圖演示 

3. Java 代碼實現 

  1. /** 
  2.  * 基數排序 
  3.  * 考慮負數的情況還可以參考: https://code.i-harness.com/zh-CN/q/e98fa9 
  4.  */ 
  5. public class RadixSort implements IArraySort { 
  6.  
  7.     @Override 
  8.     public int[] sort(int[] sourceArray) throws Exception { 
  9.         // 對 arr 進行拷貝,不改變參數內容 
  10.         int[] arr = Arrays.copyOf(sourceArray, sourceArray.length); 
  11.  
  12.         int maxDigit = getMaxDigit(arr); 
  13.         return radixSort(arr, maxDigit); 
  14.     } 
  15.  
  16.     /** 
  17.      * 獲取***位數 
  18.      */ 
  19.     private int getMaxDigit(int[] arr) { 
  20.         int maxValue = getMaxValue(arr); 
  21.         return getNumLenght(maxValue); 
  22.     } 
  23.  
  24.     private int getMaxValue(int[] arr) { 
  25.         int maxValue = arr[0]; 
  26.         for (int value : arr) { 
  27.             if (maxValue < value) { 
  28.                 maxValue = value; 
  29.             } 
  30.         } 
  31.         return maxValue; 
  32.     } 
  33.  
  34.     protected int getNumLenght(long num) { 
  35.         if (num == 0) { 
  36.             return 1; 
  37.         } 
  38.         int lenght = 0; 
  39.         for (long temp = num; temp != 0; temp /= 10) { 
  40.             lenght++; 
  41.         } 
  42.         return lenght; 
  43.     } 
  44.  
  45.     private int[] radixSort(int[] arr, int maxDigit) { 
  46.         int mod = 10; 
  47.         int dev = 1; 
  48.  
  49.         for (int i = 0; i < maxDigit; i++, dev *= 10, mod *= 10) { 
  50.             // 考慮負數的情況,這里擴展一倍隊列數,其中 [0-9]對應負數,[10-19]對應正數 (bucket + 10) 
  51.             int[][] counter = new int[mod * 2][0]; 
  52.  
  53.             for (int j = 0; j < arr.length; j++) { 
  54.                 int bucket = ((arr[j] % mod) / dev) + mod; 
  55.                 counter[bucket] = arrayAppend(counter[bucket], arr[j]); 
  56.             } 
  57.  
  58.             int pos = 0; 
  59.             for (int[] bucket : counter) { 
  60.                 for (int value : bucket) { 
  61.                     arr[pos++] = value; 
  62.                 } 
  63.             } 
  64.         } 
  65.  
  66.         return arr; 
  67.     } 
  68.  
  69.     /** 
  70.      * 自動擴容,并保存數據 
  71.      * 
  72.      * @param arr 
  73.      * @param value 
  74.      */ 
  75.     private int[] arrayAppend(int[] arr, int value) { 
  76.         arr = Arrays.copyOf(arr, arr.length + 1); 
  77.         arr[arr.length - 1] = value; 
  78.         return arr; 
  79.     } 

 

責任編輯:龐桂玉 來源: 機器學習算法與Python學習
相關推薦

2021-10-31 07:38:37

排序算法代碼

2019-08-28 11:08:51

排序算法Java

2022-03-10 12:03:33

Python算法代碼

2017-07-18 10:50:38

前端JavaScript排序算法

2021-11-08 15:12:48

排序算法面試

2016-01-29 11:00:55

數據挖掘算法大數據

2013-02-25 09:46:35

數據挖掘算法ICDM

2021-01-26 05:33:07

排序算法快速

2021-01-21 05:22:36

排序算法選擇

2018-10-27 15:47:35

CART算法決策樹

2010-08-31 14:01:48

CSS

2011-01-26 09:14:43

數據挖掘

2018-09-13 12:51:58

數據挖掘算法樸素貝葉斯

2024-09-06 17:57:35

2013-07-09 13:56:48

微信

2018-04-25 08:10:50

算法k-means代碼

2018-05-03 09:36:53

算法數據挖掘C4.5

2020-06-05 16:05:58

人工智能機器學習人臉識別

2018-02-01 18:45:12

機器學習算法線性回歸

2015-11-11 08:36:40

數據中心網絡運維
點贊
收藏

51CTO技術棧公眾號

天天综合久久综合| 国产精品sss| 人妻av无码一区二区三区| 搜成人激情视频| 亚洲欧洲国产日本综合| 国产精品久久精品视| 日韩美一区二区| 91成人影院| 亚洲福利视频久久| 欧美精品久久久久久久久25p| 91麻豆免费在线视频| 91婷婷韩国欧美一区二区| 国产精品第七影院| 日本熟妇毛耸耸xxxxxx| 日韩av大片| 亚洲第一av网| 午夜免费看毛片| 在线免费看h| 日韩码欧中文字| 蜜桃网站成人| 亚洲高清视频网站| 秋霞成人午夜伦在线观看| 欧美激情在线播放| 在线观看天堂av| 天天久久夜夜| 欧美一二三四区在线| 午夜视频在线瓜伦| 2021中文字幕在线| 欧美国产1区2区| 精品久久一区二区三区蜜桃| 国产精品欧美亚洲| 视频一区国产视频| 欧美日韩高清在线观看| 欧美aaa级片| 国产成人av| 亚洲国产精久久久久久| 日本美女久久久| jizzyou欧美16| 欧美日韩在线免费| 久久99久久久久久| 国产精品扒开做爽爽爽的视频| 国产亚洲精品aa| 精品欧美一区二区久久久伦| 亚洲精品网站在线| 国产精品123| 91在线视频免费| 在线观看一二三区| 噜噜噜在线观看免费视频日韩| 欧美激情国产高清| 欧美精品videos极品| 99精品全国免费观看视频软件| 中文字幕v亚洲ⅴv天堂| 人妻aⅴ无码一区二区三区| 台湾色综合娱乐中文网| 亚洲精品电影网在线观看| 99riav国产精品视频| 日韩精品一区二区三区免费视频| 91精品午夜视频| 国产成人在线综合| 日日夜夜精品| 在线不卡欧美精品一区二区三区| 粉色视频免费看| 中文成人激情娱乐网| 91.com在线观看| 五月天六月丁香| 亚洲1区在线| 亚洲国产精品资源| a毛片毛片av永久免费| 中国av一区| 中文字幕视频在线免费欧美日韩综合在线看 | 每日更新在线观看av| 久久天天做天天爱综合色| 欧美日本韩国一区二区三区| 精品电影在线| 国产精品久久久久久久午夜片| 亚洲最新免费视频| 18视频在线观看| 亚洲国产一区二区三区 | 女人十八毛片嫩草av| 日韩久久电影| 欧美黄色www| 99热只有这里有精品| 老司机亚洲精品| 成人黄色免费网站在线观看| 国产成人免费看一级大黄| 成人av免费在线播放| 免费久久99精品国产自| 日本亚洲精品| 亚洲午夜久久久久久久久久久| 无码精品a∨在线观看中文| 日韩一区二区三区在线免费观看| 欧美猛男超大videosgay| 无套白嫩进入乌克兰美女| 少妇一区二区三区| 中文字幕一区日韩电影| 久久精品99久久久久久| 男女精品网站| 7777奇米亚洲综合久久| 日韩三级电影网| 综合久久一区二区三区| 人妻久久久一区二区三区| av成人在线播放| 精品国产乱码久久久久久浪潮| 一区二区三区四区免费| 综合久久亚洲| 日本一欧美一欧美一亚洲视频| 国产免费无遮挡| 91免费看`日韩一区二区| 在线国产精品网| 午夜影院在线观看国产主播| 777奇米成人网| 欧美狂猛xxxxx乱大交3| 你懂的视频一区二区| 国产99久久精品一区二区永久免费 | 精品无码av一区二区三区| 波多野结衣在线观看一区二区 | 国产黄色片在线免费观看| 国产视频一区三区| av资源站久久亚洲| 在线观看免费版| 欧美丝袜一区二区三区| 中文字幕一二三| 久久综合国产| 日本欧美黄网站| 天堂成人在线视频| 一二三四区精品视频| 亚洲一区日韩精品| 国内黄色精品| 欧美夜福利tv在线| 高h调教冰块play男男双性文| 国产精品福利在线播放| 精品久久久久久无码国产| 牛牛精品成人免费视频| 欧美黑人性猛交| www.国产精品视频| 亚洲精品乱码久久久久久黑人| 国产免费又粗又猛又爽| 精品国产一区二区三区噜噜噜| 97香蕉超级碰碰久久免费软件| www.狠狠干| 亚洲免费观看高清完整| 天天综合天天添夜夜添狠狠添| 欧美理论电影大全| 国产精品99免视看9| 欧美亚洲日本| 第一福利永久视频精品| 中文字幕在线国产| 国模吧视频一区| 国产精品9999久久久久仙踪林| а天堂中文在线官网| 91精品国产91久久综合桃花| а天堂中文在线资源| 麻豆精品一区二区av白丝在线 | 一精品久久久| 2022国产精品| 污视频免费在线观看| 欧美成人a在线| 国产无遮挡又黄又爽在线观看| 成人小视频免费观看| 精品免费久久久久久久| 一区二区三区四区高清视频| 欧美大片第1页| 可以免费观看的毛片| 亚洲成人7777| 国产精品1000部啪视频| 日日夜夜精品免费视频| 亚洲精品自在在线观看| 成人亚洲精品| 久久久久久91| 日本亚洲欧美| 欧美午夜精品一区二区蜜桃| 日韩精品久久久久久久的张开腿让| 人人爽香蕉精品| 日本女人高潮视频| 嗯用力啊快一点好舒服小柔久久| 欧美在线视频网| 在线观看精品一区二区三区| 欧美一区二区成人6969| 中文字幕在线观看免费视频| 91丨国产丨九色丨pron| 免费看污污网站| 欧美片第1页综合| 精品乱子伦一区二区三区| 亚洲综合av一区二区三区| 精品久久久91| 网站黄在线观看| 在线观看日韩电影| 欧美黄色一区二区三区| 91碰在线视频| 在线播放av中文字幕| 激情久久一区| 亚洲国产欧美一区二区三区不卡| 欧美a级大片在线| 欧美亚洲在线播放| 国产在线一区二区视频| 亚洲精品一区久久久久久| 91美女精品网站| 污片在线观看一区二区| 四季av中文字幕| av中文字幕一区| 91pony九色| 亚洲一区国产一区| 中文字幕剧情在线观看一区| 欧美freesex8一10精品| 91精品久久久久久久久久久久久 | 亚洲三区在线观看无套内射| 欧美日韩精品高清| 一区二区三区福利视频| ●精品国产综合乱码久久久久| 懂色av粉嫩av蜜乳av| 国产一区二区三区四区五区入口 | 免费不卡在线视频| 波多野结衣综合网| 亚洲蜜桃视频| 翔田千里亚洲一二三区| 欧美亚洲色图校园春色| 亚洲淫片在线视频| 成人在线高清| 欧美一性一乱一交一视频| 亚洲七七久久综合桃花剧情介绍| 国产一区二区三区视频 | 亚洲图片小说区| 欧美一级淫片videoshd| 黑人精品视频| 北条麻妃久久精品| 国产二区在线播放| 日韩精品中文字幕视频在线| 精品人妻一区二区三区含羞草 | www.爱爱.com| 在线不卡a资源高清| 久久久久在线视频| 欧美日韩亚洲成人| 97人人澡人人爽人人模亚洲| 一区二区三区四区在线播放 | 国产精品久久99久久| 少妇视频在线观看| 91精品国产自产91精品| 丁香花视频在线观看| 九色91av视频| 超碰在线网址| 久久香蕉国产线看观看网| jizz在线免费观看| 在线日韩第一页| 国产在线超碰| 国产亚洲精品成人av久久ww| 欧美色综合一区二区三区| 日韩精品福利在线| 视频国产在线观看| 欧美精品一区在线观看| 黄色av小说在线观看| 精品久久久久久久一区二区蜜臀| 精品国产无码一区二区三区| 日韩一级完整毛片| www.国产视频| 亚洲国产美女精品久久久久∴| 东京干手机福利视频| 精品成人在线观看| 五月婷婷丁香六月| 亚洲欧美另类人妖| 国产主播福利在线| 中文字幕精品在线| 久草资源在线观看| 欧美成人三级视频网站| 黄网av在线| 欧美一区二区色| free欧美| 国产在线观看精品| 天堂精品在线视频| 精品乱码一区| 日本一区二区三区视频| 欧洲金发美女大战黑人| 亚洲视频中文| 欧美视频免费播放| 久久精品国产亚洲一区二区三区| www.欧美激情.com| 成人黄色a**站在线观看| 极品人妻一区二区三区| 国产精品丝袜一区| 久久久久99精品成人片毛片| 精品久久久久久久久久久| 天天综合久久综合| 精品日韩在线一区| 欧美女优在线观看| 久久精品国产亚洲7777| 国产第一页在线| 日本亚洲欧洲色| 久久wwww| 麻豆蜜桃91| 一区二区三区午夜探花| 亚欧无线一线二线三线区别| 免费在线一区观看| 中文字幕天堂av| 亚洲国产精品传媒在线观看| 国模无码国产精品视频| 日韩欧美主播在线| 国产欧美一级片| 亚洲精品国产精品国自产在线 | 亚洲国产精品av| 久久久久久国产精品免费播放| 一本色道久久综合狠狠躁的推荐| 国产精品永久久久久久久久久| 亚洲国内精品在线| 黄色国产网站在线播放| 热99久久精品| 亚洲一二av| 图片区小说区区亚洲五月| 亚洲激情av| 在线免费看污网站| 久久免费偷拍视频| 久久黄色免费视频| 欧美日本一区二区| 欧美成熟毛茸茸| 欧美精品久久一区二区 | 欧美日韩美少妇| 天堂a中文在线| 色综合视频一区中文字幕| 影音成人av| 麻豆av一区二区| 欧美特黄a级高清免费大片a级| 超碰在线公开97| 久久久久久久免费视频了| 国产一级免费观看| 日韩一区二区电影在线| 欧美尤物美女在线| 国产成人精品久久久| 秋霞蜜臀av久久电影网免费| 中文字幕色呦呦| 狠狠色丁香久久婷婷综| 懂色av粉嫩av浪潮av| 色女孩综合影院| 青青草免费在线| 欧美亚洲在线观看| 久久夜色精品国产噜噜av小说| 欧美性猛交内射兽交老熟妇| 理论片日本一区| 欧美黄色高清视频| 在线免费不卡电影| 第一福利在线| 国产精品久久久久久久久久久久 | 亚洲一卡二卡三卡| 日本不卡在线视频| gv天堂gv无码男同在线观看| 在线免费观看日本欧美| 国产福利免费在线观看| 国产精品久久久91| 日韩精品电影| gai在线观看免费高清| 国产精品麻豆久久久| 一区二区小视频| 精品国产区一区二区三区在线观看| 怡红院成人在线| 亚洲 日韩 国产第一区| 麻豆精品精品国产自在97香蕉 | 熟妇人妻中文av无码| 久久久亚洲国产| 日韩av资源网| 欧美极品欧美精品欧美图片| 久久久五月婷婷| 国产一级片免费视频| 一区二区在线视频播放| 91av一区| 成人午夜免费剧场| 国产成人免费在线观看| 国产乡下妇女做爰| 精品一区电影国产| 成人在线高清| 日本aa在线观看| 99精品国产99久久久久久白柏 | 欧美一区二区三区在线电影| av网站免费在线观看| 成人黄色在线免费观看| 亚洲精选在线| 亚洲一区视频在线播放| 欧美日本一道本在线视频| 里番在线播放| 欧美三级华人主播| 韩国成人精品a∨在线观看| 久草福利资源在线观看| 日韩精品视频在线播放| 国产亚洲精品精品国产亚洲综合| 综合视频免费看| fc2成人免费人成在线观看播放 | 日本不卡影院| 美女主播视频一区| 紧缚奴在线一区二区三区| 日本三级网站在线观看| 亚洲日韩欧美视频一区| 高清一区二区| 久久亚洲中文字幕无码| 亚洲国产高清在线观看视频| www.黄色国产| 国产成人综合精品在线| 亚洲天堂一区二区三区四区| 日韩无码精品一区二区| 欧美日韩另类一区| 免费h视频在线观看| 在线视频91| 久久综合久久99| 国产成人精品无码高潮| 国产xxx69麻豆国语对白|