算法導論筆記 第8章 線性時間排序

任何比較排序在最好狀況下都要通過Ω(nlgn),即比較排序的下界爲Ω(nlgn)。ios

合併排序和堆排序都是漸進最優的。算法

要突破Ω(nlgn),就要進行非比較排序。計數排序、基數排序和桶排序都有非比較的一些操做來肯定排序順序,它們能夠達到線性運行時間。數組

 

計數排序法:spa

計數排序的基本思想是對每個輸入元素x,肯定出小於x的元素個數。有了這個信息就能夠把x直接放到他在最終輸出數組中的位置上。code

計數排序適用於小範圍集合的排序。它的複雜度爲Ο(n+k)(其中k是整數的範圍),快於任何比較排序算法。 可是當O(k)>O(n*log(n))的時候其效率反而不如基於比較的排序。orm

代碼以下:blog

#include <iostream>
#include <limits.h>

//輸入 A,輸出B
void count_sort(int A[], int B[], int nLen) {
  //1.找出待排序的數組中最大和最小的元素
  int k = INT_MIN;
  for (int i = 0; i < nLen; i++) {
    if (A[i] > k) {
      k = A[i];
    }
  }
  //===============
  int *C = new int [k];//統計的暫存數組
  //初始化C
  for (int i = 0; i < k; i ++) {
    C[i] = 0;
  }
  //2.統計數組中每一個值爲i的元素出現的次數,存入數組C的第i項

  //統計j的次數
  for (int j = 0; j < k; j++){
    C[A[j]] = C[A[j]] + 1;//統計A[j]出現了多少次
  }

  //3.對全部的計數累加(從C中的第一個元素開始,每一項和前一項相加)
  for (int i = 0; i < k; i++) {
    C[i] = C[i] + C[i-1];//對於給定的輸入序列中的每個元素x,肯定該序列中值小於x的元素的個數
  }

  //4.反向填充目標數組:將每一個元素i放在新數組的第C(i)項,每放一個 元素就將C(i)減去1
  //逆向遍歷源數組(保證穩定性),根據計數數組中對應的值填充到先的數組中
  for (int j = nLen; j>=0; j++) {
    B[C[A[j]]] = A[j];
    C[A[j]] = C[A[j]] -1;
  }
  delete[] C;
}
int main()
{
  int a[] = {5,9,3,9,10,9,2,4,13,10};
  const size_t sz = sizeof(a)/sizeof(a[0]);
  for (int i = 0; i < sz;  i++ ) {
    std::cout << a[i] << " ";
  }
}

 

基數排序:排序

基數排序是首先按最低有效位數字進行排序的,它從低位到高位進行排序。它是一種穩定性的算法。it

相關文章
相關標籤/搜索