基本排序(後續補充)
阿新 • • 發佈:2018-12-21
1.基本排序演算法:
冒泡(穩定),
// 氣泡排序,a 表示陣列,n 表示陣列大小 public void bubbleSort(int[] a, int n) { if (n <= 1) return; for (int i = 0; i < n; ++i) { // 提前退出冒泡迴圈的標誌位 boolean flag = false; for (int j = 0; j < n - i - 1; ++j) { if (a[j] > a[j+1]) { // 交換 int tmp = a[j]; a[j] = a[j+1]; a[j+1] = tmp; flag = true; // 表示有資料交換 } } if (!flag) break; // 沒有資料交換,提前退出 } }
插入(穩定),
// 插入排序,a 表示陣列,n 表示陣列大小 public void insertionSort(int[] a, int n) { if (n <= 1) return; for (int i = 1; i < n; ++i) { int value = a[i]; int j = i - 1; // 查詢插入的位置 for (; j >= 0; --j) { if (a[j] > value) { a[j+1] = a[j]; // 資料移動 } else { break; } } a[j+1] = value; // 插入資料 } }
(冒泡和插入雖然在逆序度上是相同的,但是,氣泡排序需要3個賦值操作,而插入排序只需要1個)
(衍生於插入排序,在插入上優化)
public static void shellSort(int[] array) { int number = array.length / 2; int i; int j; int temp; while (number >= 1) { for (i = number; i < array.length; i++) { temp = array[i]; j = i - number; while (j >= 0 && array[j] < temp) { array[j + number] = array[j]; j = j - number; } array[j + number] = temp; } number = number / 2; } }
選擇(類插入,不穩定)(O(n^2)),
以上適合於小規模資料的排序,以下幾種適合大規模資料排序
快排:分治思想, 非穩定排序
package sorts;
/**
* Created by wangzheng on 2018/10/16.
*/
public class QuickSort {
// 快速排序,a是陣列,n表示陣列的大小
public static void quickSort(int[] a, int n) {
quickSortInternally(a, 0, n-1);
}
// 快速排序遞迴函式,p,r為下標
private static void quickSortInternally(int[] a, int p, int r) {
if (p >= r) return;
int q = partition(a, p, r); // 獲取分割槽點
quickSortInternally(a, p, q-1);
quickSortInternally(a, q+1, r);
}
private static int partition(int[] a, int p, int r) {
int pivot = a[r];
int i = p;
for(int j = p; j < r; ++j) {
if (a[j] < pivot) {
int tmp = a[i];
a[i] = a[j];
a[j] = tmp;
++i;
}
}
int tmp = a[i];
a[i] = a[r];
a[r] = tmp;
System.out.println("i=" + i);
return i;
}
}
歸併(O(nlogn)):非原地排序演算法,分治思想
package sorts;
/**
* Created by wangzheng on 2018/10/16.
*/
public class MergeSort {
// 歸併排序演算法, a是陣列,n表示陣列大小
public static void mergeSort(int[] a, int n) {
mergeSortInternally(a, 0, n-1);
}
// 遞迴呼叫函式
private static void mergeSortInternally(int[] a, int p, int r) {
// 遞迴終止條件
if (p >= r) return;
// 取p到r之間的中間位置q,防止(p+r)的和超過int型別最大值
int q = p + (r - p)/2;
// 分治遞迴
mergeSortInternally(a, p, q);
mergeSortInternally(a, q+1, r);
// 將A[p...q]和A[q+1...r]合併為A[p...r]
merge(a, p, q, r);
}
private static void merge(int[] a, int p, int q, int r) {
int i = p;
int j = q+1;
int k = 0; // 初始化變數i, j, k
int[] tmp = new int[r-p+1]; // 申請一個大小跟a[p...r]一樣的臨時陣列
while (i<=q && j<=r) {
if (a[i] <= a[j]) {
tmp[k++] = a[i++]; // i++等於i:=i+1
} else {
tmp[k++] = a[j++];
}
}
// 判斷哪個子陣列中有剩餘的資料
int start = i;
int end = q;
if (j <= r) {
start = j;
end = r;
}
// 將剩餘的資料拷貝到臨時陣列tmp
while (start <= end) {
tmp[k++] = a[start++];
}
// 將tmp中的陣列拷貝回a[p...r]
for (i = 0; i <= r-p; ++i) {
a[p+i] = tmp[i];
}
}
}
桶排序,計數排序,基數排序