排序是計算機內常常進行的一種操做,其目的是將一組「無序」的記錄序列調整爲「有序」的記錄序列。份內部排序和外部排序。若整個排序過程不須要訪問外存便能完成,則稱此類排序問題爲內部排序。反之,若參加排序的記錄數量很大,整個序列的排序過程不可能在內存中完成,則稱此類排序問題爲外部排序。html
穩定排序:假設在待排序的文件中,存在兩個或兩個以上的記錄具備相同的關鍵字,在用某種排序法排序後,若這些相同關鍵字的元素的相對次序仍然不變,則這種排序方法是穩定的。java
冒泡,插入,基數,歸併屬於穩定排序git
選擇,快速,希爾,堆屬於不穩定排序。算法
就地排序:若排序算法所需的輔助空間並不依賴於問題的規模n,即輔助空間爲O(1),則稱爲就地排序。shell
冒泡排序(Bubble Sort)數組
一種簡單直觀的排序算法。它重複地走訪過要排序的數列,一次比較兩個元素,若是他們的順序錯誤就把他們交換過來。走訪數列的工做是重複地進行直到沒有再須要交換,也就是說該數列已經排序完成。這個算法的名字由來是由於越小的元素會經由交換慢慢「浮」到數列的頂端。數據結構
算法步驟:
1)比較相鄰的元素。若是第一個比第二個大,就交換他們兩個。
2)對每一對相鄰元素做一樣的工做,從開始第一對到結尾的最後一對。這步作完後,最後的元素會是最大的數。
3)針對全部的元素重複以上的步驟,除了最後一個。
4)持續每次對愈來愈少的元素重複上面的步驟,直到沒有任何一對數字須要比較。架構
圖解:ide
優勢:穩定,簡單oop
缺點:慢,每次只移動相鄰的兩個元素。
時間複雜度:
理想狀況下(數組原本就是有序的),此時最好的時間複雜度爲o(n),
最壞的時間複雜度(數據反序的),此時的時間複雜度爲o(n*n) 。
冒泡排序的平均時間負責度爲o(n*n).
快速排序
由東尼·霍爾所發展的一種排序算法。
算法步驟:
1)從數列中挑出一個元素,稱爲 「基準」(pivot),
2)從新排序數列,全部元素比基準值小的擺放在基準前面,全部元素比基準值大的擺在基準的後面(相同的數能夠到任一邊)。在這個分區退出以後,該基準就處於數列的中間位置。這個稱爲分區(partition)操做。
3)遞歸地(recursive)把小於基準值元素的子數列和大於基準值元素的子數列排序。
遞歸的最底部情形,是數列的大小是零或一,也就是永遠都已經被排序好了。雖然一直遞歸下去,可是這個算法總會退出,由於在每次的迭代(iteration)中,它至少會把一個元素擺到它最後的位置去。
圖解:
時間複雜度:
在平均情況下,排序 n 個項目要Ο(n log n)次比較。
在最壞情況下則須要Ο(n2)次比較,但這種情況並不常見。
事實上,快速排序一般明顯比其餘Ο(n log n) 算法更快,由於它的內部循環(inner loop)能夠在大部分的架構上頗有效率地被實現出來。
直接插入排序
插入排序是一種最簡單直觀的排序算法,它的工做原理是經過構建有序序列,對於未排序數據,在已排序序列中從後向前掃描,找到相應位置並插入。
算法步驟:
1)將第一待排序序列第一個元素看作一個有序序列,把第二個元素到最後一個元素當成是未排序序列。
2)從頭至尾依次掃描未排序序列,將掃描到的每一個元素插入有序序列的適當位置。(若是待插入的元素與有序序列中的某個元素相等,則將待插入元素插入到相等元素的後面。)
圖解:
希爾排序
希爾排序,也稱遞減增量排序算法,是插入排序的一種更高效的改進版本。但希爾排序是非穩定排序算法。
希爾排序是基於插入排序的如下兩點性質而提出改進方法的:
插入排序在對幾乎已經排好序的數據操做時, 效率高, 便可以達到線性排序的效率
插入排序通常來講是低效的, 由於插入排序每次只能將數據移動一位
希爾排序的基本思想是:先將整個待排序的記錄序列分割成爲若干子序列分別進行直接插入排序,待整個序列中的記錄「基本有序」時,再對全體記錄進行依次直接插入排序。
算法步驟:
1)選擇一個增量序列t1,t2,…,tk,其中ti>tj,tk=1;
2)按增量序列個數k,對序列進行k 趟排序;
3)每趟排序,根據對應的增量ti,將待排序列分割成若干長度爲m 的子序列,分別對各子表進行直接插入排序。僅增量因子爲1 時,整個序列做爲一個表來處理,表長度即爲整個序列的長度。
圖解:
簡單選擇排序
算法步驟:
1)首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置
2)再從剩餘未排序元素中繼續尋找最小(大)元素,而後放到已排序序列的末尾。
3)重複第二步,直到全部元素均排序完畢。
圖解:
時間複雜度:
簡單選擇排序過程當中,所需移動記錄的次數比較少。
最好狀況下,即待排序記錄初始狀態就已是正序排列了,則不須要移動記錄。
最壞狀況下,即待排序記錄初始狀態是按逆序排列的,則須要移動記錄的次數最多爲3(n-1)。
簡單選擇排序過程當中須要進行的比較次數與初始狀態下待排序的記錄序列的排列狀況無關。
共須要進行的比較次數是(n-1)+(n-2)+…+2+1=n(n-1)/2,即進行比較操做的時間複雜度爲O(n^2),進行移動操做的時間複雜度爲O(n)。
堆排序
堆排序(Heapsort)是指利用堆這種數據結構所設計的一種排序算法。堆積是一個近似徹底二叉樹的結構,並同時知足堆積的性質:即子結點的鍵值或索引老是小於(或者大於)它的父節點。
算法步驟:
1)建立一個堆H[0..n-1]
2)把堆首(最大值)和堆尾互換
3)把堆的尺寸縮小1,並調用shift_down(0),目的是把新的數組頂端數據調整到相應位置
4) 重複步驟2,直到堆的尺寸爲1
圖解:
時間複雜度:
平均時間複雜度爲Ο(nlogn) 。
歸併排序
歸併排序是創建在歸併操做上的一種有效的排序算法,該算法是採用分治法(Divide and Conquer)的一個很是典型的應用。將已有序的子序列合併,獲得徹底有序的序列;即先使每一個子序列有序,再使子序列段間有序。若將兩個有序表合併成一個有序表,稱爲二路歸併。
算法步驟:
1. 申請空間,使其大小爲兩個已經排序序列之和,該空間用來存放合併後的序列
2. 設定兩個指針,最初位置分別爲兩個已經排序序列的起始位置
3. 比較兩個指針所指向的元素,選擇相對小的元素放入到合併空間,並移動指針到下一位置
4. 重複步驟3直到某一指針達到序列尾
5. 將另外一序列剩下的全部元素直接複製到合併序列尾
圖解:
基數排序(radix sort)
基數排序(radix sort)屬於「分配式排序」(distribution sort),又稱「桶子法」(bucket sort)或bin sort,顧名思義,它是透過鍵值的部份資訊,將要排序的元素分配至某些「桶」中,藉以達到排序的做用,基數排序法是屬於穩定性的排序,其時間複雜度爲O (nlog(r)m),其中r爲所採起的基數,而m爲堆數,在某些時候,基數排序法的效率高於其它的穩定性排序法。
基數排序是一種非比較型整數排序算法,其原理是將整數按位數切割成不一樣的數字,而後按每一個位數分別比較。因爲整數也能夠表達字符串(好比名字或日期)和特定格式的浮點數,因此基數排序也不是隻能使用於整數。
桶排序算法思想:是將陣列分到有限數量的桶子裏。每一個桶子再個別排序(有可能再使用別的排序算法或是以遞迴方式繼續使用桶排序進行排序)。桶排序是鴿巢排序的一種概括結果。當要被排序的陣列內的數值是均勻分配的時候,桶排序使用線性時間(Θ(n))。但桶排序並非比較排序,他不受到 O(n log n) 下限的影響。簡單來講,就是把數據分組,放在一個個的桶中,而後對每一個桶裏面的在進行排序。
例如要對大小爲[1..1000]範圍內的n個整數A[1..n]排序
首先,能夠把桶設爲大小爲10的範圍,具體而言,設集合B[1]存儲[1..10]的整數,集合B[2]存儲 (10..20]的整數,……集合B[i]存儲( (i-1)*10, i*10]的整數,i = 1,2,..100。總共有 100個桶。
而後,對A[1..n]從頭至尾掃描一遍,把每一個A[i]放入對應的桶B[j]中。 再對這100個桶中每一個桶裏的數字排序,這時可用冒泡,選擇,乃至快排,通常來講任 何排序法均可以。
最後,依次輸出每一個桶裏面的數字,且每一個桶中的數字從小到大輸出,這 樣就獲得全部數字排好序的一個序列了。
假設有n個數字,有m個桶,若是數字是平均分佈的,則每一個桶裏面平均有n/m個數字。若是對每一個桶中的數字採用快速排序,那麼整個算法的複雜度是O(n + m * n/m*log(n/m)) = O(n + nlogn – nlogm)
從上式看出,當m接近n的時候,桶排序複雜度接近O(n)
固然,以上覆雜度的計算是基於輸入的n個數字是平均分佈這個假設的。這個假設是很強的 ,實際應用中效果並無這麼好。若是全部的數字都落在同一個桶中,那就退化成通常的排序了。
前面說的幾大排序算法 ,大部分時間複雜度都是O(n2),也有部分排序算法時間複雜度是O(nlogn)。而桶式排序卻能實現O(n)的時間複雜度。但桶排序的缺點是:
1)首先是空間複雜度比較高,須要的額外開銷大。排序有兩個數組的空間開銷,一個存放待排序數組,一個就是所謂的桶,好比待排序值是從0到m-1,那就須要m個桶,這個桶數組就要至少m個空間。
2)其次待排序的元素都要在必定的範圍內等等。
java 源碼:
冒泡排序
1 package com.zhd.sort; 2 3 //冒泡排序 4 public class SwapSortBubbleApp { 5 6 public static void main(String[] args) { 7 int[] test = new int[]{9, 8, 7, 6, 5, 4, 3, 2, 1}; 8 showArray(test); 9 doSort(test); 10 showArray(test); 11 } 12 13 //小->大 14 static void doSort(int[] arr) { 15 bubbleSort(arr); 16 } 17 18 private static void bubbleSort(int[] arr) { 19 for(int out = arr.length - 1; out > 0; out--) { 20 for(int in = 0; in < out; in++) { 21 if(arr[in] > arr[in+1]) swap(in, in+1, arr); 22 } 23 //System.out.println(out);showArray(arr); 24 } 25 } 26 private static void swap(int one, int two, int[] arr) { 27 int tmp = arr[one]; 28 arr[one] = arr[two]; 29 arr[two] = tmp; 30 } 31 32 private static void showArray(int[] arr) { 33 System.out.print("[ "); 34 for(int i = 0; i < arr.length; i++) { 35 System.out.print(arr[i] + " "); 36 } 37 System.out.println("]"); 38 } 39 }
快速排序
1 package com.zhd.sort; 2 3 //快速排序(基於交換) 4 public class SwapSortQuickApp { 5 6 public static void main(String[] args) { 7 int[] test = new int[]{9, 8, 7, 6, 5, 4, 3, 2, 1}; 8 showArray(test); 9 doSort(test); 10 showArray(test); 11 } 12 13 //小->大 14 static void doSort(int[] arr) { 15 quickSort(arr, 0, arr.length-1); 16 } 17 private static void quickSort(int[] arr, int left, int right) { 18 int dp; 19 if(left < right) { 20 dp = partition(arr, left, right); 21 quickSort(arr, left, dp-1); 22 quickSort(arr, dp+1, right); 23 } 24 } 25 private static int partition(int[] n, int left, int right) { 26 int pivot = n[left]; 27 while(left < right) { 28 while(left < right && n[right] >= pivot) right--; 29 if(left < right) n[left++] = n[right]; 30 while(left < right && n[left] <= pivot) left++; 31 if(left < right) n[right--] = n[left]; 32 } 33 n[left] = pivot; 34 return left; 35 } 36 37 private static void showArray(int[] arr) { 38 System.out.print("[ "); 39 for(int i = 0; i < arr.length; i++) { 40 System.out.print(arr[i] + " "); 41 } 42 System.out.println("]"); 43 } 44 }
(非遞歸寫法)
1 package com.zhd.sort; 2 3 import java.util.LinkedList; 4 5 6 //快速排序(基於交換) 7 public class SwapSortQuickNonRecursionApp { 8 9 public static void main(String[] args) { 10 int[] test = new int[]{9, 8, 7, 6, 5, 4, 3, 2, 1}; 11 showArray(test); 12 doSort(test); 13 showArray(test); 14 } 15 16 //小->大 17 static void doSort(int[] arr) { 18 quickSort(arr, 0, arr.length-1); 19 quickSort2(arr, 0, arr.length-1); 20 } 21 private static void quickSort(int[] arr, int left, int right) { 22 int dp; 23 LinkedList<Integer> stack = new LinkedList<Integer>(); 24 if(left < right) { 25 dp = partition(arr, left, right); 26 if(left < dp-1) { 27 stack.push(left); 28 stack.push(dp-1); 29 } 30 if(right > dp+1) { 31 stack.push(dp+1); 32 stack.push(right); 33 } 34 } 35 36 while(!stack.isEmpty()) { 37 int r = stack.pop(); 38 int l = stack.pop(); 39 dp = partition(arr, l, r); 40 if(l < dp-1) { 41 stack.push(l); 42 stack.push(dp-1); 43 } 44 if(r > dp+1) { 45 stack.push(dp+1); 46 stack.push(r); 47 } 48 } 49 } 50 private static void quickSort2(int[] arr, int left, int right) { 51 if(left > right) return; 52 53 int dp; 54 LinkedList<Integer> stack = new LinkedList<Integer>(); 55 do { 56 if(!stack.isEmpty()) { 57 right = stack.pop(); 58 left = stack.pop(); 59 } 60 61 dp = partition(arr, left, right); 62 if (left < dp - 1) { 63 stack.push(left); 64 stack.push(dp - 1); 65 } 66 if (right > dp + 1) { 67 stack.push(dp + 1); 68 stack.push(right); 69 } 70 71 } while(!stack.isEmpty()); 72 } 73 private static int partition(int[] n, int left, int right) { 74 int pivot = n[left]; 75 while(left < right) { 76 while(left < right && n[right] >= pivot) right--; 77 if(left < right) n[left++] = n[right]; 78 while(left < right && n[left] <= pivot) left++; 79 if(left < right) n[right--] = n[left]; 80 } 81 n[left] = pivot; 82 return left; 83 } 84 85 private static void showArray(int[] arr) { 86 System.out.print("[ "); 87 for(int i = 0; i < arr.length; i++) { 88 System.out.print(arr[i] + " "); 89 } 90 System.out.println("]"); 91 } 92 }
直接插入排序
1 package com.zhd.sort; 2 3 //直接插入排序 4 public class InsertSortDirectApp { 5 6 public static void main(String[] args) { 7 int[] test = new int[]{9, 8, 7, 6, 5, 4, 3, 2, 1}; 8 showArray(test); 9 doSort(test); 10 showArray(test); 11 } 12 13 //基本有序下,效率最優O(n); 基本反序,效率最差O(n*n) 14 static void doSort(int[] arr) { 15 directInsertSort(arr); 16 } 17 18 private static void directInsertSort(int[] arr) { 19 for(int out = 1; out < arr.length; out++) { 20 int tmp = arr[out], in = out; 21 for(; in > 0 && arr[in-1] >= tmp; --in) 22 arr[in] = arr[in-1]; 23 arr[in] = tmp; 24 //System.out.println(out);showArray(arr); 25 } 26 } 27 28 private static void showArray(int[] arr) { 29 System.out.print("[ "); 30 for(int i = 0; i < arr.length; i++) { 31 System.out.print(arr[i] + " "); 32 } 33 System.out.println("]"); 34 } 35 }
希爾排序
1 package com.zhd.sort; 2 3 //shell 排序 4 public class InsertSortShellApp { 5 6 public static void main(String[] args) { 7 int[] test = new int[]{9, 8, 7, 6, 5, 4, 3, 2, 1, 0}; 8 showArray(test); 9 doSort(test); 10 showArray(test); 11 System.exit(0); 12 } 13 14 static void doSort(int[] arr) { 15 shellSort(arr); 16 } 17 18 //最好,最壞狀況下,效率相差不大 19 private static void shellSort(int[] arr) { 20 int h = 1; 21 while(h <= arr.length/3) h = h*3+1; 22 23 while(h>0) { 24 for(int out = h; out < arr.length; out++) { 25 int tmp = arr[out], in = out; 26 for(; in > h-1 && arr[in-h] >= tmp; in -= h) { 27 arr[in] = arr[in-h]; 28 } 29 arr[in] = tmp; 30 //System.out.println("out=" + out + " h=" + h);showArray(arr); 31 } 32 h = (h-1)/3; 33 } 34 } 35 36 private static void showArray(int[] arr) { 37 System.out.print("[ "); 38 for(int i = 0; i < arr.length; i++) { 39 System.out.print(arr[i] + " "); 40 } 41 System.out.println("]"); 42 } 43 }
簡單選擇排序
1 package com.zhd.sort; 2 3 //簡單選擇排序 4 public class SelectSortSimpleApp { 5 6 public static void main(String[] args) { 7 //int[] test = new int[]{9, 8, 7, 6, 5, 4, 3, 2, 1}; 8 int[] test = new int[]{9, 8, 7, 6, 5, 4, 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, 1}; 9 showArray(test); 10 doSort(test); 11 showArray(test); 12 } 13 14 static void doSort(int[] arr) { 15 simpleSelectSort(arr); 16 } 17 18 private static void simpleSelectSort(int[] arr) { 19 for(int out = 0; out < arr.length; out++) { 20 int min = out; 21 for(int in = out + 1; in < arr.length; in++) 22 if(arr[in] < arr[min]) min = in; 23 swap(out, min, arr); 24 //System.out.println(out);showArray(arr); 25 } 26 } 27 private static void swap(int one, int two, int[] arr) { 28 int tmp = arr[one]; 29 arr[one] = arr[two]; 30 arr[two] = tmp; 31 } 32 33 private static void showArray(int[] arr) { 34 System.out.print("[ "); 35 for(int i = 0; i < arr.length; i++) { 36 System.out.print(arr[i] + " "); 37 } 38 System.out.println("]"); 39 } 40 }
堆排序
1 package com.zhd.sort; 2 3 //改進選擇排序(堆排序) 4 public class SelectSortHeapApp { 5 6 public static void main(String[] args) { 7 //int[] test = new int[]{9, 8, 7, 6, 5, 4, 3, 2, 1, 0}; 8 int[] test = new int[]{9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 8, 7, 6, 5, 4, 3, 2, 1, 0, 8, 7, 6, 5, 4, 3, 2, 1, 0, 8, 7, 6, 5, 4, 3, 2, 1, 0}; 9 showArray(test); 10 doSort(test); 11 showArray(test); 12 System.exit(0); 13 } 14 15 static void doSort(int[] arr) { 16 heapSort(arr); 17 } 18 19 private static void heapSort(int[] arr) { 20 buildHeap(arr, arr.length); 21 for(int i = arr.length - 1; i > 0; --i) { 22 swap(i, 0, arr); 23 heapAdjust(arr, 0, i); 24 } 25 } 26 private static void heapAdjust(int[] arr, int s, int len) { //構建大根堆 27 int tmp = arr[s], child = 2*s+1; 28 while(child < len) { 29 if(child+1 < len && arr[child] < arr[child+1]) 30 ++child; 31 if(arr[s] < arr[child]) { 32 arr[s] = arr[child]; 33 s = child; 34 child = 2*s+1; 35 } else { 36 break; 37 } 38 arr[s] = tmp; 39 } 40 } 41 private static void buildHeap(int[] arr, int len) { 42 for(int i = (len-1)/2; i > 0; --i) 43 heapAdjust(arr, i, len); 44 } 45 46 private static void swap(int one, int two, int[] arr) { 47 int tmp = arr[one]; 48 arr[one] = arr[two]; 49 arr[two] = tmp; 50 } 51 52 private static void showArray(int[] arr) { 53 System.out.print("[ "); 54 for(int i = 0; i < arr.length; i++) { 55 System.out.print(arr[i] + " "); 56 } 57 System.out.println("]"); 58 } 59 }
歸併排序
1 package com.zhd.sort; 2 3 public class MergeSortApp { 4 5 public static void main(String[] args) { 6 //int[] test = new int[]{9, 8, 7, 6, 5, 4, 3, 2, 1}; 7 int[] test = new int[]{9, 8, 7, 6, 5, 4, 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, 1}; 8 showArray(test); 9 doSort(test); 10 showArray(test); 11 System.exit(0); 12 } 13 14 static void doSort(int[] arr) { 15 mergeSort(arr, 0, arr.length-1); 16 } 17 18 private static void mergeSort(int[] array, int left, int right) { 19 if (left >= right) 20 return; 21 int center = (left + right) / 2;// 找出中間索引 22 mergeSort(array, left, center);// 對左邊數組進行遞歸 23 mergeSort(array, center + 1, right);// 對右邊數組進行遞歸 24 merge(array, left, center, right);// 合併 25 //showArray(array); 26 } 27 private static void merge(int[] array, int left, int center, int right) { 28 int[] tmpArr = new int[array.length]; 29 int mid = center + 1; 30 int third = left; 31 int tmp = left; 32 while (left <= center && mid <= right) { 33 if (array[left] <= array[mid]) { 34 tmpArr[third++] = array[left++]; 35 } else { 36 tmpArr[third++] = array[mid++]; 37 } 38 } 39 // 剩餘部分依次放入臨時數組(實際上兩個while只會執行其中一個) 40 while (mid <= right) { 41 tmpArr[third++] = array[mid++]; 42 } 43 while (left <= center) { 44 tmpArr[third++] = array[left++]; 45 } 46 // 將臨時數組中的內容拷貝回原數組中 (原left-right範圍的內容被複制回原數組) 47 while (tmp <= right) { 48 array[tmp] = tmpArr[tmp++]; 49 } 50 } 51 52 53 private static void showArray(int[] arr) { 54 System.out.print("[ "); 55 for(int i = 0; i < arr.length; i++) { 56 System.out.print(arr[i] + " "); 57 } 58 System.out.println("]"); 59 } 60 }
三大線性排序(計數排序,桶排序,基排序)
計數排序的基本思想是:統計一個數序列中小於某個元素a的個數爲n,則直接把該元素a放到第n+1個位置上。當有幾個元素相同時要作適當的調整,由於不能把全部的元素放到同一個位置上。計數排序假設輸入的元素都是0到k之間的整數。
Java源碼:
1 package com.zhd.sort; 2 3 public class LinearSortCountApp { 4 5 public static void main(String[] args) { 6 //int[] test = new int[]{9, 8, 7, 6, 5, 4, 3, 2, 1}; 7 int[] test = new int[]{5, 4, 3, 2, 1, 9, 8, 7, 6, 77, -1}; 8 showArray(test); 9 doSort(test); 10 showArray(test); 11 } 12 static void doSort(int[] arr) { 13 countSort(arr); 14 } 15 16 //計數排序(要求待排數據是整數) 17 private static void countSort(int[] arr) { 18 int[] b = new int[arr.length]; 19 int max = 0, min = 0; 20 for(int i = 1; i < arr.length; i++) { 21 if(arr[i] > arr[max]) max = i; 22 if(arr[i] < arr[min]) min = i; 23 } 24 25 int k = arr[max] - arr[min] + 1; //這裏k的大小是要排序的數組中,元素大小的極值差+1 26 int[] c = new int[k]; //優化過的地方,減少了數組c的大小 27 for(int i = 0; i < arr.length; ++i) { 28 c[arr[i]-arr[min]] += 1; 29 } 30 for(int i = 1; i < c.length; ++i) { 31 c[i] = c[i] + c[i-1]; 32 } 33 for(int i = arr.length-1; i >= 0; --i) { 34 b[--c[arr[i]-arr[min]]] = arr[i]; //按存取的方式取出c的元素 35 } 36 37 for(int i = arr.length-1; i >= 0; --i) arr[i] = b[i]; 38 } 39 40 private static void showArray(int[] arr) { 41 System.out.print("[ "); 42 for(int i = 0; i < arr.length; i++) { 43 System.out.print(arr[i] + " "); 44 } 45 System.out.println("]"); 46 } 47 }
桶排序
桶排序:桶排序的思想是把區間[0,1)劃分紅n個相同大小的子區間,稱爲桶。而後將n個輸入數分佈到各個桶中去。由於輸入數均勻且獨立分佈在[0,1)上,因此,通常不會有不少數落在一個桶中的狀況。爲了獲得結果,先對各個桶中的數進行排序,而後按次序把各桶中的元素列出來。
桶排序的時間複雜度爲O(n) ,如有n個待排數據,m個桶,空間複雜度爲O(n+m)
桶排序時間,空間複雜度分析:
桶排序的平均時間複雜度爲線性的O(N+C),其中C=N*(logN-logM)。
若是相對於一樣的N,桶數量M越大,其效率越高,最好的時間複雜度達到O(N)。
桶排序的空間複雜度 爲O(N+M),
若是輸入數據很是龐大,而桶的數量也很是多,則空間代價無疑是昂貴的。
桶排序是穩定的。
Java源碼:
1 package com.zhd.sort; 2 3 import java.util.Collections; 4 import java.util.Iterator; 5 import java.util.LinkedList; 6 7 public class LinearSortBucketApp { 8 9 public static void main(String[] args) { 10 //int[] test = new int[]{5, 4, 3, 2, 1, 9, 8, 7, 6, 77, -1}; 11 double[] test = { 0.78, 0.17, 0.39, 0.26, 0.72, 0.94, 0.21, 0.12, 0.23, 0.68 }; 12 showArray(test); 13 doSort(test); 14 showArray(test); 15 } 16 static void doSort(double[] arr) { 17 bucketSort(arr); 18 } 19 20 @SuppressWarnings({ "rawtypes", "unchecked" }) 21 private static void bucketSort(double[] arr) { 22 int len = arr.length; 23 LinkedList[] lls = new LinkedList[len]; 24 //劃分桶並填元素 25 for(int i = 0; i < len; i++) { 26 int tmp = (int) Math.floor(10 * arr[i]); //0.7到0.79放在第8個桶裏,編號7;第一個桶放0到0.09 27 if (null == lls[tmp]) lls[tmp] = new LinkedList(); 28 lls[tmp].add(arr[i]); 29 } 30 // 對每一個桶中的數進行排序 31 for(int i = 0; i < len; i++) { 32 if (null != lls[i]) { 33 Collections.sort(lls[i]); //Collections和Arrays裏的sort 是調優後的快排 34 } 35 } 36 //輸出相似鴿巢排序 37 int count = 0; 38 for(int i = 0; i < len; i++) { 39 if (null != lls[i]) { 40 Iterator iter = lls[i].iterator(); 41 while (iter.hasNext()) { 42 arr[count++] = (Double)iter.next(); 43 } 44 } 45 } 46 } 47 48 // private static void showArray(int[] arr) { 49 // System.out.print("[ "); 50 // for(int i = 0; i < arr.length; i++) { 51 // System.out.print(arr[i] + " "); 52 // } 53 // System.out.println("]"); 54 // } 55 private static void showArray(double[] arr) { 56 System.out.print("[ "); 57 for(int i = 0; i < arr.length; i++) { 58 System.out.print(arr[i] + " "); 59 } 60 System.out.println("]"); 61 } 62 }
基數排序
基數排序也不是基於比較和元素移位的,
本文是基於計數排序的基數排序,只介紹最低位優先(Least Significant Digit First)
LSD(Least Significant Digit First):就是從數字的最低位逐個比較,比較的趟數就是最大數字的位數digit,所以須要先用countDigit方法求出位數digit。(是否是有語病,看完就知道了)
優劣:
本算法是穩定的,LSD須要使用穩定的算法,
因爲按位比較,所以須要整數,
和計數排序不一樣的是,整數能夠是負數(各類排序均可以正負混合),待排序數值也能夠很大。
圖解:
Java源碼:
1 package com.zhd.sort; 2 3 import java.util.Arrays; 4 5 public class LinearSortRadixApp { 6 7 public static void main(String[] args) { 8 int[] test = new int[]{5, 4, 3, 2, 1, 9, 8, 7, 6, 77, 890, 222, 64, 89}; 9 showArray(test); 10 doSort(test); 11 showArray(test); 12 } 13 private static void doSort(int[] arr) { 14 radixSort(arr); 15 } 16 17 private static void radixSort(int[] arr) { 18 int digit = countDigit(arr); //digit 表明排序元素的位數,實際意義是排序趟數 19 int radix = 10; //radix 表明基數,實際就是幾個數字,那就是10嘍 20 radixSort(arr, radix, digit); 21 } 22 private static void radixSort(int[] arr, int radix, int digit) { 23 int len = arr.length; 24 int[] res = new int[len]; 25 int[] c = new int[radix]; 26 int divide = 1; 27 28 for(int i = 0; i < digit; i++) { 29 res = Arrays.copyOf(arr, len); 30 Arrays.fill(c, 0); 31 32 //計數排序(穩定) 33 for(int j = 0; j < len; j++) { 34 int key = (res[j]/divide) % radix; 35 c[key]++; 36 } 37 for(int j = 1; j < radix; j++) { 38 c [j] = c[j] + c[j-1]; 39 } 40 for(int j = len - 1; j >= 0; j--) { 41 int key = (res[j]/divide) % radix; 42 arr[c[key]-1] = res[j]; 43 c[key]--; 44 } 45 divide = divide * radix; 46 } 47 } 48 private static int countDigit(int[] arr) { 49 int max = arr[0]; 50 for (int i = 1; i < arr.length; i++) { 51 if (arr[i] > max) { 52 max = arr[i]; 53 } 54 } 55 int time = 0; 56 while (max > 0) { 57 max /= 10; 58 time++; 59 } 60 return time; 61 } 62 63 private static void showArray(int[] arr) { 64 System.out.print("[ "); 65 for(int i = 0; i < arr.length; i++) { 66 System.out.print(arr[i] + " "); 67 } 68 System.out.println("]"); 69 } 70 }
參考url
url:http://www.cricode.com/3212.html
url:http://my.oschina.net/mkh/blog/341172
url:http://www.cnblogs.com/wolf-sun/p/4312475.html
url:http://blog.csdn.net/hguisu/article/details/7776068
url:http://m.blog.csdn.net/blog/likaiwalkman/23713373
url:http://www.cnblogs.com/kkun/archive/2011/11/23/2260312.html
url:http://www.cnblogs.com/hxsyl/p/3214379.html
url:http://www.cnblogs.com/hxsyl/p/3210647.html
url:http://blog.csdn.net/qeshine/article/details/9821567
url:http://my.oschina.net/liyixiangBlog/blog/266175
交換排序(冒泡排序,快速排序)
插入排序(直接插入排序,希爾排序)
選擇排序(簡單選擇排序,堆排序)
歸併排序