本文使用Java實現這幾種排序算法。
如下是對排序算法整體的介紹。html
時間複雜度:O(n^2),最優時間複雜度:O(n),平均時間複雜度:O(n^2)算法
public static void bubbleSort(Comparable[] a) { int j, flag; Comparable temp; for (int i = 0; i < a.length; i++) { flag = 0; for (j = 1; j < a.length - i; j++) { if (a[j].compareTo(a[j - 1]) < 0) { temp = a[j]; a[j] = a[j - 1]; a[j - 1] = temp; flag = 1; } } // 若是沒有交換,表明已經排序完畢,直接返回 if (flag == 0) { return; } } }
時間複雜度:O(n^2),最優時間複雜度:O(n),平均時間複雜度:O(n^2)shell
下面展現了兩種插入排序的實現,第二種方法減小了交換次數。性能
public static void insertionSort(Comparable[] a) { int length = a.length; Comparable temp; for (int i = 1; i < length; i++) { for (int j = i; j > 0 && a[j].compareTo(a[j - 1]) < 0; j--) { temp = a[j]; a[j] = a[j - 1]; a[j - 1] = temp; } } }
// 對實現Comparable的類型進行排序,先將大的元素都向右移動,減小一半交換次數
public static void insertionSort(Comparable[] a) { int length = a.length; Comparable temp; int j; for (int i = 1; i < length; i++) { temp = a[i]; for (j = i; j > 0 && temp.compareTo(a[j - 1]) < 0; j--) { a[j] = a[j - 1]; } a[j] = temp; } }
首先在未排序序列中找到最小元素,存放到排序序列的起始位置,而後,再從剩餘未排序元素中繼續尋找最小元素,而後放到已排序序列的末尾。優化
時間複雜度:O(n^2),最優時間複雜度:O(n^2),平均時間複雜度:O(n^2)ui
public static void selectionSort1(Comparable[] a) { int length = a.length; int min; Comparable temp; for (int i = 0; i < length; i++) { min = i; for (int j = i + 1; j < length; j++) { if (a[j].compareTo(a[min]) < 0) { min = j; } } temp = a[min]; a[min] = a[i]; a[i] = temp; } }
希爾排序經過將比較的所有元素分爲幾個區域來提高插入排序的性能。這樣可讓一個元素能夠一次性地朝最終位置前進一大步。而後算法再取愈來愈小的步長進行排序,算法的最後一步就是普通的插入排序,可是到了這步,需排序的數據幾乎是已排好的了(此時插入排序較快)。spa
時間複雜度:根據步長而不一樣,最優時間複雜度:O(n),平均時間複雜度:根據步長而不一樣code
public static void shellSort(Comparable[] a) { int length = a.length; int h = 1; Comparable temp; while (h < length / 3) { h = 3 * h + 1; } while (h >= 1) { for (int i = h; i < length; i++) { for (int j = i; j >= h && a[j].compareTo(a[j - h]) < 0; j -= h) { temp = a[j]; a[j] = a[j - h]; a[j - h] = temp; } } h /= 3; } }
時間複雜度:O(nlogn),最優時間複雜度:O(nlogn),平均時間複雜度:O(nlogn)htm
public static void heapSort(Comparable[] a) { int length = a.length; Comparable temp; for (int k = length / 2; k >= 1; k--) { sink(a, k, length); } while (length > 0) { temp = a[0]; a[0] = a[length - 1]; a[length - 1] = temp; length--; sink(a, 1, length); } } private static void sink(Comparable[] a, int k, int n) { Comparable temp; while (2 * k <= n) { int j = 2 * k; if (j < n && a[j - 1].compareTo(a[j]) < 0) { j++; } if (a[k - 1].compareTo(a[j - 1]) >= 0) { break; } temp = a[k - 1]; a[k - 1] = a[j - 1]; a[j - 1] = temp; k = j; } }
歸併操做(merge),也叫歸併算法,指的是將兩個已經排序的序列合併成一個序列的操做。歸併排序算法依賴歸併操做。blog
時間複雜度:O(nlogn),最優時間複雜度:O(n),平均時間複雜度:O(nlogn),空間複雜度O(n)
自頂向下的歸併排序
private static Comparable[] aux; // 自頂向下 public static void mergeSort(Comparable[] a) { aux = new Comparable[a.length]; mergeSort(a, 0, a.length - 1); } public static void mergeSort(Comparable[] a, int lo, int hi) { if (hi <= lo) { return; } int mid = (lo + hi) >>> 1; mergeSort(a, lo, mid); mergeSort(a, mid + 1, hi); merge(a, lo, mid, hi); } public static void merge(Comparable[] a, int lo, int mid, int hi) { int i = lo, j = mid + 1; for (int k = lo; k <= hi; k++) { aux[k] = a[k]; } for (int k = lo; k <= hi; k++) { if (i > mid) { a[k] = aux[j++]; } else if (j > hi) { a[k] = aux[i++]; } else if (aux[j].compareTo(aux[i]) < 0) { a[k] = aux[j++]; } else { a[k] = aux[i++]; } } }
自底向上的歸併排序
private static Comparable[] aux; // 自底向上 public static void mergeSort(Comparable[] a) { int length = a.length; aux = new Comparable[length]; for (int sz = 1; sz < length; sz = sz + sz) { for (int lo = 0; lo < length - sz; lo += sz + sz) { merge(a, lo, lo + sz - 1, Math.min(lo + sz + sz - 1, length - 1)); } } } public static void merge(Comparable[] a, int lo, int mid, int hi) { int i = lo, j = mid + 1; for (int k = lo; k <= hi; k++) { aux[k] = a[k]; } for (int k = lo; k <= hi; k++) { if (i > mid) { a[k] = aux[j++]; } else if (j > hi) { a[k] = aux[i++]; } else if (aux[j].compareTo(aux[i]) < 0) { a[k] = aux[j++]; } else { a[k] = aux[i++]; } } }
時間複雜度:O(n^2),最優時間複雜度:O(nlogn),平均時間複雜度:O(nlogn)
快排的時間複雜度跟選取基準的方法有關,一下是默認選擇了第一個元素做爲基準,隨機性較大。
能夠在序列中選取開始中間結尾三個數的中位數做爲基準,進行優化。
public static void quickSort(Comparable[] a) { quickSort(a, 0, a.length - 1); } public static void quickSort(Comparable[] a, int lo, int hi) { if (hi <= lo) { return; } int j = partition(a, lo, hi); quickSort(a, lo, j - 1); quickSort(a, j + 1, hi); } public static int partition(Comparable[] a, int lo, int hi) { int i = lo, j = hi + 1; Comparable temp; Comparable v = a[lo]; while (true) { while (a[++i].compareTo(v) < 0) { if (i == hi) { break; } } while (v.compareTo(a[--j]) < 0) { if (j == lo) { break; } } if (i >= j) { break; } temp = a[i]; a[i] = a[j]; a[j] = temp; } temp = a[lo]; a[lo] = a[j]; a[j] = temp; return j; }