標籤:排序演算法
常見排序演算法包括以下七種:選擇排序、冒泡排序、插入排序、快速排序、希爾排序、堆排序、歸併排序。
在學習具體演算法實現並進行比較前,先來學習演算法比較的幾個維度。
一是穩定性
所謂穩定性,是指值相等的兩個元素在排序前後是否會發生位置的交換。如果不會發生交換,則認為是穩定的演算法;反之,則認為是不穩定的排序演算法。
二是時間複雜度,指執行演算法所需的時間長短。簡單說就是演算法執行的快慢程式。
三是空間複雜度,指執行演算法所佔用的記憶體大小。
有了這些基本概念,下面就來看以上七種排序演算法的java版實現
/** * <一句話功能簡述> */public class AllSort { /** * 快速排序<br/> * 不穩定排序,時間複雜度O(nlogn) * * @param a * @param left * @param right * @return */ public static void quickSort(int[] a, int left, int right) { if (left >= right) return; int i, j, temp; i = left; j = right; temp = a[left]; while (i != j) { while (a[j] >= temp && i < j) j--; while (a[i] <= temp && i < j) i++; if (i < j) { int t = a[i]; a[i] = a[j]; a[j] = t; j--; } } a[left] = a[i]; a[i] = temp; if (left < i - 1) quickSort(a, left, i - 1); if (i + 1 < right) quickSort(a, i + 1, right); } /** * 選擇排序<br/> * 不穩定排序,時間複雜度為O(n2) * * @param a * @return */ public static void choseSort(int[] a) { for (int i = 0; i < a.length - 1; i++) { int min_index = i; for (int j = i + 1; j < a.length; j++) { if (a[min_index] > a[j]) { min_index = j; } } if (i != min_index) { int temp = a[i]; a[i] = a[min_index]; a[min_index] = temp; } } } /** * 冒泡排序<br/> * 穩定排序,時間複雜度為O(n2) * * @param a * @return */ public static void bubbleSort(int[] a) { for (int i = 1; i < a.length; i++) { for (int j = 0; j < a.length - i; j++) { if (a[j] > a[j + 1]) { int temp = a[j]; a[j] = a[j + 1]; a[j + 1] = temp; } } } } /** * 直接插入排序<br/> * 穩定排序,時間複雜度O(n2) * * @param a * @return */ public static void insertSort(int[] a) { for (int i = 1; i < a.length; i++) { int temp = a[i]; int pos = i - 1; while (pos >= 0 && a[pos] > temp) { a[pos + 1] = a[pos]; pos--; } a[pos + 1] = temp; } } /** * 希爾排序<br/> * 不穩定排序,時間複雜度O(nlogn) * * @param a * @return */ public static void shellSort(int[] a) { int d = a.length / 2; while (d >= 1) { for (int i = 0; i < d; i++) { for (int j = i + d; j < a.length; j = j + d) { int temp = a[j]; int pos = j - d; while (pos >= 0 && a[pos] > temp) { a[pos + d] = a[pos]; pos -= d; } a[pos + d] = temp; } } d = d / 2; } } /** * 歸併排序<br/> * 穩定排序,時間複雜度O(nlogn),速度僅次於快速排序 * * @param a * @param left * @param right * @return */ public static void mergeSort(int[] a, int left, int right) { if (left < right) { int middle = (left + right) / 2; // 對左邊進行遞迴 mergeSort(a, left, middle); // 對右邊進行遞迴 mergeSort(a, middle + 1, right); // 合并 merge(a, left, middle, right); } } private static void merge(int[] a, int left, int middle, int right) { int[] tmpArr = new int[right - left + 1]; int pos = 0; int i = left;// 左邊起始位置 int j = middle + 1; // 右邊起始位置 while (i <= middle && j <= right) { // 從兩個數組中選取較小的數放入中間數組 if (a[i] <= a[j]) { tmpArr[pos++] = a[i++]; } else { tmpArr[pos++] = a[j++]; } } // 將剩餘的部分放入中間數組 while (i <= middle) { tmpArr[pos++] = a[i++]; } while (j <= right) { tmpArr[pos++] = a[j++]; } // 將中間數組複製回原數組 int start = 0; while (left <= right) { a[left++] = tmpArr[start++]; } } /** * 堆排序<br/> * 不穩定排序,時間複雜度O(nlogn) * @param a * @return */ public static void heapSort(int[] a) { int lastIndex = a.length - 1; for (int i = 0; i < lastIndex; i++) { // 建堆 buildMaxHeap(a, lastIndex - i); // 交換堆頂和最後一個元素 swap(a, 0, lastIndex - i); // System.out.println(Arrays.toString(a)); } } private static void buildMaxHeap(int[] data, int lastIndex) { // 從lastIndex處節點(最後一個節點)的父節點開始 for (int i = (lastIndex - 1) / 2; i >= 0; i--) { // k儲存正在判斷的節點 int k = i; // 如果當前k節點的子節點存在 while (k * 2 + 1 <= lastIndex) { // k節點的左子節點的索引 int biggerIndex = 2 * k + 1; // 如果biggerIndex小於lastIndex,即biggerIndex+1代表的k節點的右子節點存在 if (biggerIndex < lastIndex) { // 若果右子節點的值較大 if (data[biggerIndex] < data[biggerIndex + 1]) { // biggerIndex總是記錄較大子節點的索引 biggerIndex++; } } // 如果k節點的值小於其較大的子節點的值 if (data[k] < data[biggerIndex]) { // 交換他們 swap(data, k, biggerIndex); // 將biggerIndex賦予k,開始while迴圈的下一次迴圈,重新保證k節點的值大於其左右子節點的值 k = biggerIndex; } else { break; } } } } private static void swap(int[] data, int i, int j) { int tmp = data[i]; data[i] = data[j]; data[j] = tmp; } public static void main(String[] args) { Random random = new Random(); int[] a = new int[20]; for (int i = 0; i < a.length; i++) { a[i] = random.nextInt(20); } //quickSort(a, 0, a.length - 1); //mergeSort(a, 0, a.length - 1); //shellSort(a); //heapSort(a); //choseSort(a); //bubbleSort(a); //insertSort(a); System.out.println(Arrays.toString(a)); }}
各排序演算法比較如
這個是摘自網上的比較,僅供參考。
我對有些項持懷疑態度,例如歸併排序,個人認為空白間複雜度不應該是O(1),而應該是O(nlog2n)。而快速排序的空間複雜度是O(1)。
java實現各種排序演算法及比較