1. 程式人生 > >線性排序演算法

線性排序演算法

桶排序:
1. 原理: 根據資料範圍,分成若干個資料段的桶,通過遍歷講資料放到對應的桶中。每個桶裡都進行快排或歸併。
2. 時間複雜度: 最好o(n), 最壞o(nlogn), 平均o(n),一般桶分的越細越多複雜度就會最好。
3. 記憶體消耗: o(n)
4. 穩定性: 取決於每個桶的排序方式,快排就不穩定,歸併就穩定。
5. 適用場景: 資料範圍不大的。記憶體吃緊的,如磁碟的讀寫可以分成多個小檔案並對每個小檔案排序,然後直接寫到大檔案裡,這個時候記憶體消耗不再是o(n)了。

計數排序:
1. 原理: 特殊的桶排序,即每個下標代表一個數據範圍,其值就是這個資料的個數。
2. 時間複雜度: 都是o(n)
3. 記憶體消耗: o(n)
4. 穩定性: 穩定,只要整理最後結果時從後開始遍歷即可。
5. 適用場景: 資料範圍不大的,如年齡排序。

// 計數排序,a 是陣列,n 是陣列大小。假設陣列中儲存的都是非負整數。
public void countingSort(int[] a, int n) {
  if (n <= 1) return;   // 查詢陣列中資料的範圍
  int max = a[0];
  for (int i = 1; i < n; ++i) {
    if (max < a[i]) {
      max = a[i];
    }
  }   int[] c = new int[max + 1]; // 申請一個計數陣列 c,下標大小 [0,max]
  for (int i = 0; i <= max; ++i) {
    c[i] = 0;
  }   // 計算每個元素的個數,放入 c 中
  for (int i = 0; i < n; ++i) {
    c[a[i]]++;
  }   // 依次累加
  for (int i = 1; i <= max; ++i) {
    c[i] = c[i-1] + c[i];
  }   // 臨時陣列 r,儲存排序之後的結果
  int[] r = new int[n];
  // 計算排序的關鍵步驟,有點難理解
  for (int i = n - 1; i >= 0; --i) {
    int index = c[a[i]]-1;
    r[index] = a[i];
    c[a[i]]--;
  }   // 將結果拷貝給 a 陣列
  for (int i = 0; i < n; ++i) {
    a[i] = r[i];
  }
}



基數排序:
1. 原理: 對資料的每一位進行桶排序或計數排序,對每位排序後結果就是有序的。
2. 時間複雜度: 最好o(n), 最壞o(nlogn), 平均o(n)
3. 記憶體消耗: o(n)
4. 穩定性: 穩定。否則就排不成的。
5. 適用場景: 是在桶排序和計數排序基礎上進行的,保證每位資料範圍不大,並且位數也不是很多。