我听说过Counting Sort,并根据我的理解编写了我的版本。
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异常。
所以我的问题是:
答案 0 :(得分:2)
您的版本存在的问题是,如果元素包含卫星数据,则无法使用。
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')]
答案 1 :(得分:1)
应该是
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(...)
。
答案 2 :(得分:0)
问题是您已将所使用的数组的长度硬编码为100.数组的长度应为m + 1
,其中m是原始数组上的最大元素。这是你想到使用count-sort的第一个原因,如果你有关于数组元素的信息都是次要的,那么一些常量并且它会很好。