【问题标题】:Counting sort - implementation differences计数排序 - 实现差异
【发布时间】:2011-04-14 21:08:41
【问题描述】:

我听说了计数排序,并根据我的理解编写了我的版本。

public void my_counting_sort(int[] arr)
    {
        int range = 100;
        int[] count = new int[range];
        for (int i = 0; i < arr.Length; i++) count[arr[i]]++;
        int index = 0;
        for (int i = 0; i < count.Length; i++)
        {
            while (count[i] != 0)
            {
                arr[index++] = i;
                count[i]--;
            }
        }
    }

以上代码完美运行。

但是,CLRS 中给出的算法是不同的。下面是我的实现

public int[] counting_sort(int[] arr)
    {
        int k = 100;
        int[] count = new int[k + 1];
        for (int i = 0; i < arr.Length; i++)
            count[arr[i]]++;
        for (int i = 1; i <= k; i++)
            count[i] = count[i] + count[i - 1];
        int[] b = new int[arr.Length];
        for (int i = arr.Length - 1; i >= 0; i--)
        {
            b[count[arr[i]]] = arr[i];
            count[arr[i]]--;
        }
        return b;
    }

我已直接将其从伪代码翻译成 C#。代码不起作用,我得到一个 IndexOutOfRange 异常。

所以我的问题是:

  • 第二段代码有什么问题?
  • 在我的幼稚实现与书中给出的实现之间,算法方面的区别是什么?

【问题讨论】:

  • 你用什么来输入counting_sort的第二个版本?该算法有一些限制,允许输入值。
  • int[] arr 包含 0-100 范围内的整数。我知道如果存在重复元素,该算法将不起作用。

标签: c# algorithm sorting


【解决方案1】:

您的版本的问题是,如果元素有卫星数据,它将无法工作。

CLRS 版本可以工作并且很稳定。

编辑:

这是一个用 Python 实现的 CLRS 版本,它按键对(键、值)进行排序:

def sort(a):
  B = 101
  count = [0] * B
  for (k, v) in a:
    count[k] += 1
  for i in range(1, B):
    count[i] += count[i-1]
  b = [None] * len(a)
  for i in range(len(a) - 1, -1, -1):
    (k, v) = a[i]
    count[k] -= 1
    b[count[k]] = a[i]
  return b    


>>> print sort([(3,'b'),(2,'a'),(3,'l'),(1,'s'),(1,'t'),(3,'e')])
[(1, 's'), (1, 't'), (2, 'a'), (3, 'b'), (3, 'l'), (3, 'e')]

【讨论】:

    【解决方案2】:

    应该是

    b[count[arr[i]]-1] = arr[i];
    

    我会留给你找出原因;-)。

    我不认为他们的表现有什么不同。第二个只是将计数的相关性推到循环之外,以便在最终循环中稍微简化一下。就我而言,这不是必需的。您的方式同样简单明了,可能更具可读性。事实上(我不知道 C#,因为我是 Java 人)我希望你可以用库数组填充替换那个内部 while 循环;像这样:

           for (int i = 0; i < count.Length; i++)
        {
            arrayFill(arr, index, count[i], i);
            index += count[i];
        }
    

    在 Java 中,方法是 java.util.Arrays.fill(...)

    【讨论】:

      【解决方案3】:

      问题在于您已将所用数组的长度硬编码为 100。数组的长度应为m + 1,其中 m 是原始数组中的最大元素。这是您认为使用计数排序的第一个原因,如果您有关于数组元素的信息都是次要的,那么它会很好用。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-09-18
        • 1970-01-01
        • 2010-10-25
        • 1970-01-01
        • 2020-07-04
        • 2019-06-14
        相关资源
        最近更新 更多