排序算法(五):基數排序

概念

基數排序是非比較排序算法,算法的時間複雜度是O(n). 相比於快速排序的O(nlgn),從表面上看具有不小的優勢.但事實上可能有些出入,因爲基數排序的n可能具有比較大的係數K.因此在具體的應用中,應首先對這個排序函數的效率進行評估. 基數排序的主要思路是,將所有待比較數值(注意,必須是正整數)統一爲同樣的數位長度,數位較短的數前面補零. 然後, 從最低位開始, 依次進行一次穩定排序(我們常用上一篇blog介紹的計數排序算法, 因爲每個位可能的取值範圍是固定的從0到9).這樣從最低位排序一直到最高位排序完成以後, 數列就變成一個有序序列.

時間複雜度

最好:O(n * k),k表示最大值的位數。

最壞:O(n * k)

平均:O(n * k)

演示

[399 ,298,98,1] 的排序過程

1.先把數據變成相同位數的值

399
298
098
001

2. 從個位數開始遍歷
    
001
298
098
399

3 十位數遍歷

001
298
098
399

4. 百位數遍歷

001
098
298
399

可想而知,如果是數據量特別大的數,這種處理會非常費勁

代碼

  function radix_sort(nums) {
      // 計算位數
      function getDigits(n) {
        let sum = 0;
        while (n) {
          sum++;
          n = parseInt(n / 10);
        }
        return sum;
      }
      // 第一維表示位數即0-9,第二維表示裏面存放的值
      let arr = Array.from(Array(10)).map(() => Array());
      let max = Math.max(...nums);
      //算出來最大的是 幾位數
      let maxDigits = getDigits(max);

      for (let i = 0, len = nums.length; i < len; i++) {
        // 用0把每一個數都填充成相同的位數
        nums[i] = (nums[i] + '').padStart(maxDigits, 0);
        // 先根據個位數把每一個數放到相應的桶裏
        let temp = nums[i][nums[i].length - 1];
        arr[temp].push(nums[i]);
      }
      // 循環判斷每個位數
      for (let i = maxDigits - 2; i >= 0; i--) {
        // 循環每一個桶
        for (let j = 0; j <= 9; j++) {
          let temp = arr[j]
          let len = temp.length;
          // 根據當前的位數i把桶裏的數放到相應的桶裏
          while (len--) {
            let str = temp[0];
            temp.shift();
            arr[str[i]].push(str);
          }
        }
      }
      // 修改回原數組
      let res = [].concat.apply([], arr);
      nums.forEach((val, index) => {
        nums[index] = +res[index];
      })
    }

    var sortArr = [9, 6, 3, 5, 2, 1, 7, 343, 6, 643, 243, 544, 5, 63, 234, 0, 56, 123]
    radix_sort(sortArr)
    console.log(sortArr)
    // [0, 1, 2, 3, 5, 5, 6, 6, 7, 9, 56, 63, 123, 234, 243, 343, 544, 643]
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章