精品欧美一区二区三区在线观看 _久久久久国色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技術棧公眾號

国产精品4hu.www| 都市激情在线视频| 国产日韩欧美一区| 中文字幕国产亚洲2019| 亚洲 国产 图片| 丰满大乳少妇在线观看网站| 26uuuu精品一区二区| 国产欧美日韩专区发布| 欧美激情一区二区视频| 亚洲婷婷影院| 欧美一级片免费看| 成人免费毛片网| 成人国产免费电影| 久久综合色综合88| 18成人在线| 无码人妻精品一区二区50| 欧美在线视屏| 在线观看欧美日韩| wwwxx日本| 97色婷婷成人综合在线观看| 欧美三级xxx| 国产制服91一区二区三区制服| 日本a一级在线免费播放| 韩日欧美一区二区三区| 欧美亚洲在线视频| 国产女片a归国片aa| 精品一区二区三区在线| 日韩福利视频在线观看| 亚洲丝袜在线观看| 电影一区二区三| 亚洲国产日韩av| 日韩一二区视频| 自拍视频在线免费观看| 国产亚洲欧洲一区高清在线观看| 97人人做人人人难人人做| 最新在线中文字幕| 免费亚洲一区| 国内精品美女av在线播放| 三级av在线免费观看| 精品国产精品| 亚洲免费视频在线观看| 免费的av网站| 黄色欧美在线| 亚洲福利小视频| 少妇献身老头系列| 粉嫩一区二区三区在线观看| 欧美日韩免费一区二区三区 | 国产51人人成人人人人爽色哟哟| 高清shemale亚洲人妖| 91综合免费在线| 国产精品久久久久久久成人午夜| 丝袜脚交一区二区| 欧美亚洲精品一区| 欧美成人xxxxx| 美女露胸视频在线观看| 精品色蜜蜜精品视频在线观看| 每日在线观看av| 国产理论在线| 欧美性xxxx极品hd满灌| 成人免费在线小视频| 涩涩av在线| 色婷婷综合久久久中文一区二区| 欧美视频第三页| 日韩免费网站| 国产精品传媒入口麻豆| 一本久久a久久精品vr综合| 在线观看a视频| 亚洲日本电影在线| 国产青草视频在线观看| 高h视频在线播放| 五月激情综合网| 日本xxxxxxx免费视频| 91超碰碰碰碰久久久久久综合| 欧美成人高清在线| 亚洲欧美综合自拍| 亚洲美女色禁图| 欧美自拍视频在线| 丰满人妻一区二区三区四区| 精品一区二区在线看| 91九色偷拍| 五月激情丁香婷婷| 国产欧美一区二区精品性色| 致1999电视剧免费观看策驰影院| 亚洲按摩av| 精品色蜜蜜精品视频在线观看| 国模杨依粉嫩蝴蝶150p| 四虎精品永久免费| 亚洲第一福利视频| 无码少妇精品一区二区免费动态| 国产国产精品| 性欧美亚洲xxxx乳在线观看| 日本丰满少妇做爰爽爽| 国产精品影视天天线| 国产一区免费| 午夜激情视频在线观看| 亚洲国产精品久久艾草纯爱| 狠狠热免费视频| 国产精品一区二区美女视频免费看| 亚洲成人精品久久| 天天操天天干天天操天天干| 午夜精品电影| 国产精品高清免费在线观看| 人人妻人人澡人人爽人人欧美一区| 久久久久国产成人精品亚洲午夜| 国产日产欧美a一级在线| av 一区二区三区| 久久久亚洲午夜电影| 欧美性视频在线播放| 69久成人做爰电影| 91精品国产高清一区二区三区| 黄色片视频免费观看| 99久久99热这里只有精品| 97超碰国产精品女人人人爽| 91国内精品视频| 久久蜜桃一区二区| 丁香婷婷综合激情| 91亚洲视频| 亚洲国产精品一区二区三区| 日本中文字幕免费在线观看| 日韩精品电影在线| 国产精品18久久久久久麻辣| 99精品在线视频观看| 国产女人18毛片水真多成人如厕| www.av蜜桃| 国产专区精品| 永久555www成人免费| 日韩av无码中文字幕| 国产一区二区调教| 亚洲va韩国va欧美va精四季| 在线观看v片| 亚洲成色999久久网站| 欧美人妻精品一区二区免费看| 久久草av在线| 四虎影视永久免费在线观看一区二区三区| wwww在线观看免费视频| 欧美一区二区三区在线观看视频| 香蕉久久久久久久| 石原莉奈一区二区三区在线观看| 精品卡一卡二| aa级大片免费在线观看| 欧美成人一区二区三区在线观看| 日本免费网站视频| 最新欧美人z0oozo0| 国产精品扒开腿做爽爽爽男男| 日中文字幕在线| 午夜成人免费电影| 无码国产精品一区二区免费式直播 | 欧美色图亚洲激情| 蜜臀91精品国产高清在线观看| 欧美黄色www| 99久久精品国产成人一区二区| 亚洲丝袜美腿综合| 日本精品一区在线| 91青青国产在线观看精品| 国产精品亚洲一区二区三区| av在线免费观看网| 欧美三电影在线| 免费黄色国产视频| 国产自产高清不卡| 欧美a级免费视频| 中文字幕日韩高清在线| 午夜免费久久久久| 男人天堂网在线| 欧美亚洲国产一区二区三区| 亚洲综合第一区| 韩国视频一区二区| wwwjizzjizzcom| 极品一区美女高清| 国产不卡av在线| 日韩免费网站| 精品精品欲导航| 国产九色在线播放九色| 久久久久久久久久电影| 一本岛在线视频| 欧美阿v一级看视频| 国产精品一区二区a| 少妇视频在线观看| 中文字幕一区电影| av 一区二区三区| 福利微拍一区二区| 日本黄区免费视频观看| 国产99精品国产| 人妻内射一区二区在线视频| 成人精品视频| 不卡视频一区二区三区| 蜜桃视频m3u8在线观看| 色偷偷综合社区| 蜜臀av中文字幕| 欧美性视频一区二区三区| 性色av无码久久一区二区三区| www..com久久爱| 中文字幕在线导航| 欧美激情一级片一区二区| 九色91国产| 国产人与zoxxxx另类91| 97视频网站入口| 暖暖日本在线观看| 亚洲国产一区自拍| 在线观看免费视频一区| 亚洲自拍偷拍麻豆| 五月天精品在线| 成人美女在线观看| 中文字幕在线视频精品| 一区二区三区国产盗摄| 国产三级中文字幕| 久久99久久人婷婷精品综合| 91久久精品国产91久久性色tv| 在线天堂新版最新版在线8| 欧美成人精品一区二区三区| 久草视频在线看| 精品乱人伦一区二区三区| 中文字幕xxxx| 婷婷成人综合网| 国产97免费视频| 国产日本亚洲高清| 国产精品无码毛片| 高潮精品一区videoshd| 中文字幕色网站| 日韩高清不卡一区| 国产亚洲综合视频| 狠狠入ady亚洲精品经典电影| 亚洲精品国产一区| 美女久久久久| 久久草视频在线看| 国产 日韩 欧美 综合 一区| 久久91亚洲人成电影网站| 欧洲伦理片一区 二区 三区| 欧美一区二区精品在线| 中文字幕+乱码+中文| 欧美日韩中文字幕综合视频| 国产成人啪精品午夜在线观看| 国产精品国产三级国产有无不卡 | 亚洲乱色熟女一区二区三区| 欧美三级在线视频| 高清乱码免费看污| 精品动漫一区二区| 成人午夜视频精品一区| 一区二区成人在线观看| 国产精品免费人成网站酒店| 国产精品嫩草99a| youjizz亚洲女人| 国产欧美视频一区二区| 色婷婷在线影院| 久久久久久久久久电影| 无码人妻精品一区二区中文| 91偷拍与自偷拍精品| 特级西西人体4444xxxx| 99精品欧美一区二区蜜桃免费| 国产一区二区三区精彩视频| 在线欧美日韩| 日韩欧美不卡在线| 一本久道久久综合婷婷鲸鱼| 国产黄页在线观看| 在线亚洲激情| 青青在线视频观看| 久久在线精品| 在线免费视频一区| 久久爱www久久做| 色婷婷激情视频| 懂色av中文字幕一区二区三区| 国产精品91av| av一二三不卡影片| 国产肉体xxxx裸体784大胆| 久久久久九九视频| 国产黄色片在线| 中文字幕一区二区三中文字幕| 91传媒免费观看| 亚洲精品欧美二区三区中文字幕| chinese全程对白| 一区二区三区.www| 日韩欧美高清在线观看| 在线精品亚洲一区二区不卡| 亚洲性生活大片| 日韩一区二区精品在线观看| 欧美 日韩 国产 在线| 精品性高朝久久久久久久| 国产毛片在线| 欧美成人午夜影院| 国产一二在线播放| 国产精品色婷婷视频| 国色天香久久精品国产一区| 人人澡人人澡人人看欧美| 国产 日韩 欧美一区| 91精品综合视频| 福利欧美精品在线| 人偷久久久久久久偷女厕| 羞羞答答成人影院www| 亚洲 自拍 另类小说综合图区| 日本伊人精品一区二区三区观看方式| gai在线观看免费高清| 成人av免费网站| 综合 欧美 亚洲日本| 亚洲尤物在线视频观看| 国产一级片免费在线观看| 欧美一区二区三区思思人| 手机福利在线| 亚洲成**性毛茸茸| 国产在线观看免费| 欧美片一区二区三区| 不卡av播放| 99re国产视频| av亚洲免费| 中文字幕无码精品亚洲资源网久久| 日韩高清一区二区| 一本色道久久hezyo无码| 中文字幕av一区 二区| 日本一级淫片色费放| 欧美日本一区二区| 欧美视频综合| 色综合91久久精品中文字幕| 亚洲伦乱视频| 狠狠色噜噜狠狠色综合久| 999精品色在线播放| 成人精品视频一区二区| 成人亚洲一区二区一| 欧美做爰啪啪xxxⅹ性| 欧美色videos| 亚洲国产成人一区二区| 色阁综合伊人av| 中文在线а√在线8| 国产欧美一区二区三区另类精品| 国产精品福利在线观看播放| 成人三级视频在线播放| 成人av免费观看| 加勒比av在线播放| 欧美一区二区三区在线| 天天综合视频在线观看| 国产福利精品av综合导导航| 日本一区福利在线| 国产精品国产亚洲精品看不卡| 国产精一区二区三区| 欧美肥妇bbwbbw| 欧美精品乱码久久久久久| 91在线高清| 国产精品爱久久久久久久| 神马午夜久久| 欧美国产亚洲一区| 成人看片黄a免费看在线| √天堂中文官网8在线| 欧美精品自拍偷拍动漫精品| 一广人看www在线观看免费视频| 国产91精品在线播放| 一本久久青青| 毛片av免费在线观看| 久久综合丝袜日本网| 成人免费毛片视频| 日韩av综合网| 午夜伦理福利在线| 久久狠狠久久综合桃花| 99成人在线| 欧美无人区码suv| 日韩欧美国产激情| 蜜桃视频在线播放| 国产精品免费久久久| 欧美一级本道电影免费专区| 欧美三级理论片| 国产精品美日韩| 国产女人高潮时对白| 欧美理论片在线观看| 牛牛影视久久网| 欧美极品欧美精品欧美图片| 久久久久久久久久美女| 国产suv精品一区二区33| 影音先锋欧美精品| 高清一区二区| 国产日韩欧美大片| 成人午夜私人影院| 久久久久久久久久久久久av| 国产亚洲激情在线| 成人污污视频| 激情小视频网站| 久久一留热品黄| 一级黄色a视频| 欧美俄罗斯性视频| 国产精品片aa在线观看| 爱爱爱爱免费视频| 亚洲综合视频网| 巨骚激情综合| 国产欧美在线观看| 国产精品豆花视频| 欧美狂猛xxxxx乱大交3| 欧美日韩一区不卡| 久操av在线| 日韩免费中文专区| 国产精品1024久久| www.com亚洲| 欧美成人免费网| 免费不卡中文字幕在线| 国产三级精品三级在线| 婷婷夜色潮精品综合在线| 浮生影视网在线观看免费| 亚洲综合在线做性| 亚洲一区二区免费看| www.色小姐com| 亚洲天堂av在线播放| 欧美精品影院| 日本xxxxxxx免费视频| 亚洲乱码国产乱码精品精98午夜 | 一区二区欧美日韩视频| 亚洲视频一起|