排序算法(四):計數排序

概念

以數組元素值爲鍵,出現次數爲值存進一個臨時數組,最後再遍歷這個臨時數組還原回原數組。因爲 JavaScript的數組下標是以字符串形式存儲的,所以計數排序可以用來排列負數,但不可以排列小數。

複雜度

最好:O(n + k),k是最大值和最小值的差。
最壞:O(n + k)
平均:O(n + k)

分類

常規計數排序

代碼


 function counting_sort(nums) {
  let arr = []
  let leg = nums.length;
  let max = Math.max(...nums)
  let min = Math.min(...nums)

  for (let i = 0; i < leg; i++) {
    let temp = nums[i]
    arr[temp] = arr[temp] + 1 || 1
  }
  
  let index = 0
  for (let i = min; i < max; i++) {
    while (arr[i] > 0) {
      nums[index++] = i
      arr[i]--
    }
  }
}

var sortArr = [9, 6, 3, 5, 2, 1, 7, 343, 6, 643, 243, 544, 5, 63, 234, 0, 56, 123]
counting_sort(sortArr)
console.log(sortArr)
// [0, 1, 2, 3, 5, 5, 6, 6, 7, 9, 56, 63, 123, 234, 243, 343, 544, 123]

缺點

在這裏插入圖片描述

優化計數排序

把每一個數組元素都加上 min 的相反數,來避免特殊情況下的空間浪費,通過這種優化可以把所開的空間大小從 max+1 降低爲 max-min+1,max 和 min 分別爲數組中的最大值和最小值。

比如數組 [103, 102, 101, 100],普通的計數排序需要開一個長度爲 104 的數組,而且前面 100 個值都是 undefined,使用該優化方法後可以只開一個長度爲 4 的數組。

    function counting_sort(nums) {
      let arr = []
      let leg = nums.length;
      let max = Math.max(...nums)
      let min = Math.min(...nums)

      let mark = 0
      let add = -min
      // 加上最小值的相反數來縮小數組範圍
      for (let i = 0, len = nums.length; i < len; i++) {
        mark += 1
        let temp = nums[i];
        temp += add;
        arr[temp] = arr[temp] + 1 || 1;
      }
      console.log(arr)
      let index = 0
      for (let i = min; i <= max; i++) {
        let temp = arr[i + add];
        mark += 1
        while (temp > 0) {
          mark += 1
          nums[index++] = i;
          temp--;
        }
      }
      console.log(mark)
    }
    var sortArr = [9, 6, 3, 5, 2, 1, 7, 343, 6, 643, 243, 544, 5, 63, 234, 0, 56, 123, 9999]
    counting_sort(sortArr)
    console.log(sortArr)
    // 10038
    // [0, 1, 2, 3, 5, 5, 6, 6, 7, 9, 56, 63, 123, 234, 243, 343, 544, 643, 9999]

使用感受

就計數排序而言,最好數的最大最小差異不是很大,如果比較值本身差異很大,創建的數據空間就會越大,遍歷數也會變多, 而且這個優化的計數排序如果數是正負都有的 那個 空間大小從 max+1 降低爲 max-min+1 這個就會變成相加的,反而會讓性能變差,而且這種優化感覺沒什麼大的用處

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章