總結一下Java排序算法,以便記憶。算法
各種排序的時間複雜度:數組
排序方法 | 時間複雜度(平均) | 時間複雜度(最壞) | 時間複雜度(最好) | 空間複雜度 | 穩定性 | 複雜性 |
---|---|---|---|---|---|---|
直接插入排序 | O(n2)O(n2) | O(n2)O(n2) | O(n)O(n) | O(1)O(1) | 穩定 | 簡單 |
希爾排序 | O(nlog2n)O(nlog2n) | O(n2)O(n2) | O(n)O(n) | O(1)O(1) | 不穩定 | 較複雜 |
直接選擇排序 | O(n2)O(n2) | O(n2)O(n2) | O(n2)O(n2) | O(1)O(1) | 不穩定 | 簡單 |
堆排序 | O(nlog2n)O(nlog2n) | O(nlog2n)O(nlog2n) | O(nlog2n)O(nlog2n) | O(1)O(1) | 不穩定 | 較複雜 |
冒泡排序 | O(n2)O(n2) | O(n2)O(n2) | O(n)O(n) | O(1)O(1) | 穩定 | 簡單 |
快速排序 | O(nlog2n)O(nlog2n) | O(n2)O(n2) | O(nlog2n)O(nlog2n) | O(nlog2n)O(nlog2n) | 不穩定 | 較複雜 |
歸併排序 | O(nlog2n)O(nlog2n) | O(nlog2n)O(nlog2n) | O(nlog2n)O(nlog2n) | O(n)O(n) | 穩定 | 較複雜 |
基數排序 | O(d(n+r))O(d(n+r)) | O(d(n+r))O(d(n+r)) | O(d(n+r))O(d(n+r)) | O(n+r)O(n+r) | 穩定 | 較複雜 |
1、冒泡排序
一、基本思想
冒泡排序(Bubble Sort)是一種簡單的排序算法。它重複地走訪過要排序的數列,一次比較兩個元素,若是他們的順序錯誤就把他們交換過來。走訪數列的工做是重複地進行直到沒有再須要交換,也就是說該數列已經排序完成。這個算法的名字由來是由於越小的元素會經由交換慢慢「浮」到數列的頂端。ui
二、算法描述
冒泡排序算法的運做以下:spa
①. 比較相鄰的元素。若是第一個比第二個大,就交換他們兩個。
②. 對每一對相鄰元素做一樣的工做,從開始第一對到結尾的最後一對。這步作完後,最後的元素會是最大的數。
③. 針對全部的元素重複以上的步驟,除了最後一個。
④. 持續每次對愈來愈少的元素重複上面的步驟①~③,直到沒有任何一對數字須要比較code
三、代碼實現
冒泡排序須要兩個嵌套的循環. 其中, 外層循環移動遊標; 內層循環遍歷遊標及以後(或以前)的元素, 經過兩兩交換的方式, 每次只確保該內循環結束位置排序正確, 而後內層循環週期結束, 交由外層循環日後(或前)移動遊標, 隨即開始下一輪內層循環, 以此類推, 直至循環結束.blog
public static void bubbleSort(int[] arr){ for (int i = arr.length - 1; i > 0; i--) { //外層循環移動遊標 for(int j = 0; j < i; j++){ //內層循環遍歷遊標及以後(或以前)的元素 if(arr[j] > arr[j+1]){ int temp = arr[j]; arr[j] = arr[j+1]; arr[j+1] = temp; System.out.println("Sorting: " + Arrays.toString(arr)); } } } }
2、快速排序(Quick Sort)
一、基本思想
快速排序的基本思想:挖坑填數+分治法。排序
首先選一個軸值(pivot,也有叫基準的),經過一趟排序將待排記錄分隔成獨立的兩部分,其中一部分記錄的關鍵字均比另外一部分的關鍵字小,則可分別對這兩部分記錄繼續進行排序,以達到整個序列有序。遞歸
二、算法描述
快速排序使用分治策略來把一個序列(list)分爲兩個子序列(sub-lists)。步驟爲:it
①. 從數列中挑出一個元素,稱爲」基準」(pivot)。io
②. 從新排序數列,全部比基準值小的元素擺放在基準前面,全部比基準值大的元素擺在基準後面(相同的數能夠到任一邊)。在這個分區結束以後,該基準就處於數列的中間位置。這個稱爲分區(partition)操做。
③. 遞歸地(recursively)把小於基準值元素的子數列和大於基準值元素的子數列排序。
遞歸到最底部時,數列的大小是零或一,也就是已經排序好了。這個算法必定會結束,由於在每次的迭代(iteration)中,它至少會把一個元素擺到它最後的位置去。
三、代碼實現
用僞代碼描述以下:
①. i = L; j = R;
將基準數挖出造成第一個坑a[i]
。
②.j--
,由後向前找比它小的數,找到後挖出此數填前一個坑a[i]
中。
③.i++
,由前向後找比它大的數,找到後也挖出此數填到前一個坑a[j]
中。
④.再重複執行②,③二步,直到i==j
,將基準數填入a[i]
中
/** * 快速排序(遞歸) * * ①. 從數列中挑出一個元素,稱爲"基準"(pivot)。 * ②. 從新排序數列,全部比基準值小的元素擺放在基準前面,全部比基準值大的元素擺在基準後面(相同的數能夠到任一邊)。在這個分區結束以後,該基準就處於數列的中間位置。這個稱爲分區(partition)操做。 * ③. 遞歸地(recursively)把小於基準值元素的子數列和大於基準值元素的子數列排序。 * @param arr 待排序數組 * @param low 左邊界 * @param high 右邊界 */ public static void quickSort(int[] arr, int low, int high){ if(arr.length <= 0) return; if(low >= high) return; int left = low; int right = high; int temp = arr[left]; //挖坑1:保存基準的值 while (left < right){ while(left < right && arr[right] >= temp){ //坑2:從後向前找到比基準小的元素,插入到基準位置坑1中 right--; } arr[left] = arr[right]; while(left < right && arr[left] <= temp){ //坑3:從前日後找到比基準大的元素,放到剛纔挖的坑2中 left++; } arr[right] = arr[left]; } arr[left] = temp; //基準值填補到坑3中,準備分治遞歸快排 System.out.println("Sorting: " + Arrays.toString(arr)); quickSort(arr, low, left-1); quickSort(arr, left+1, high); }
說明:快速排序每次交換的元素都有可能不是相鄰的, 所以它有可能打破原來值爲相同的元素之間的順序. 所以, 快速排序並不穩定.