计数排序数组值不会更改

时间:2015-03-29 02:32:30

标签: javascript arrays sorting array-algorithms counting-sort

我正在尝试实施计数排序算法。基于算法导论中的伪代码(如果你不知道它只是一本书),我想出了这个代码:

var countingSort = function(array, array2, k){
    var a = [];
    a.length = k;
    for(var i in a){
        a[i] = 0;
    }
    for(var j in array){
        a[array[j]] += 1;
    }
    for(var i in a){
        a[i] += a[i - 1];
    }
    for(var j = array.length; j >= 0; j--){
        array2[a[array[j]]] = array[j];
        a[array[j]] -= 1;
    }
};

但是,当我使用该函数时,我的数组保持不变(我输入所有参数!)如何解决这个问题?有人可以解释一下发生了什么吗?

1 个答案:

答案 0 :(得分:0)

首先,您不应该简单地使用for in循环,因为它不仅遍历数组中的元素,还覆盖Array对象上的所有属性。 Here's more info

在你的情况下,一个简单的for循环就足够了。

此外,您应该使用描述性名称,以便您(现在或稍后查看代码时)或其他人可以更清楚地理解代码。

我认为程序中的变量意味着以下内容:

  1. array存储要排序的初始数据。
  2. array2存储最终的排序列表。
  3. k是数组中的最大值(所有值都在0..k范围内)
  4. a是用于计算array
  5. 中唯一值的值的数组

    这些可以重命名为:

    1. 这个可以array
    2. array2可以重命名为sorted
    3. k可以重命名为max
    4. a可以重命名为count
    5. 你做错的另一件事是在最后一个for循环中。您正在array.length开始循环,但是数组在javascript中被索引为0,因此您的第一个值超出范围。你应该从array.length - 1开始。

      就设置a.length = k而言,这在javascript中不是必需的,因为数组是对象,而对象没有直接的长度概念。您可以在javascript中将数组视为动态列表。

      添加所有声明的更改,以下是代码的外观:

      function countingSort(array, sorted, max){
          var i, j;
      
          var count = [];
      
          // initialize counting array
          for(i = 0; i <= max; i++){
              count[i] = 0;
          }
      
          // count unique occurrences
          for(i = 0; i <= max; i++){
              count[array[i]] += 1;
          }
      
          // compute proper indices
          for(i = 1; i <= max; i++){
              count[i] += count[i - 1];
          }
      
          // sort
          for(i = array.length - 1; i >= 0; i--){
              sorted[count[array[i]] - 1] = array[i];
              count[array[i]] -= 1;
          }
      }
      

      运行示例:

      var countingSort = function(array, sorted, max) {
        var i, j;
      
        var count = [];
      
        // initialize counting array
        for (i = 0; i <= max; i++) {
          count[i] = 0;
        }
      
        // count unique occurrences
        for (i = 0; i <= max; i++) {
          count[array[i]] += 1;
        }
      
        // compute proper indices
        for (i = 1; i <= max; i++) {
          count[i] += count[i - 1];
        }
      
        // sort
        for (i = array.length - 1; i >= 0; i--) {
          sorted[count[array[i]] - 1] = array[i];
          count[array[i]] -= 1;
        }
      }
      
      document.getElementById("button").onclick = function() {
        var i, array, max, sorted = [];
      
        array = document.getElementById("input").value.split(',');
        // convert strings to numbers
        for (i = 0; i < array.length; i++) {
          array[i] = +array[i];
        }
        // find max
        var max = Number.MIN_VALUE;
        for (i = 0; i < array.length; i++) {
          if (max < array[i]) {
            max = array[i];
          }
        }
        countingSort(array, sorted, max);
        document.getElementById("result").value = sorted;
      }
      input {
        width: 100%;  
        margin: 10px 0;
        padding: 10px;
        border: 1px solid #018bbc;
        border-radius: 5px;  
      }
      <input type="text" id="input" placeholder="Enter comma separated list of integers">
      <button type="button" id="button">Sort</button>
      <input type="text" id="result" disabled placeholder="Sorted array is displayed here...">


      此外,这里有一个计数排序的版本,恕我直言似乎比上面的一般方法更直观,更简单:

      var countingSort = function(array, sorted, max) {
        var i, j, count = [];
      
        // initialize counting array
        for (i = 0; i <= max; i++) {
          count[i] = 0;
        }
      
        // count unique occurences
        for (i = 0; i < array.length; i++) {
          count[array[i]] ++;
        }
      
        // sort
        for (i = 0, j = 0; i <= max; i++) {
          while (count[i] > 0) {
            sorted[j++] = i;
            count[i] --;
          }
        }
      };