开发者

Counting sort - implementation differences

I heard about Counting Sort and wrote my version of it based on what I understood.

public开发者_C百科 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]--;
            }
        }
    }

The above code works perfectly.

However, the algorithm given in CLRS is different. Below is my implementation

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;
    }

I've directly translated this from pseudocode to C#. The code doesn't work and I get an IndexOutOfRange Exception.

So my questions are:

  • What's wrong with the second piece of code ?
  • What's the difference algorithm wise between my naive implementation and the one given in the book ?


The problem with your version is that it won't work if the elements have satellite data.

CLRS version would work and it's stable.

EDIT:

Here's an implementation of the CLRS version in Python, which sorts pairs (key, value) by key:

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')]


It should be

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

I'll leave it to you to track down why ;-).

I don't think they perform any differently. The second just pushes the correlation of counts out of the loop so that it's simplified a bit within the final loop. That's not necessary as far as I'm concerned. Your way is just as straightforward and probably more readable. In fact (I don't know about C# since I'm a Java guy) I would expect that you could replace that inner while-loop with a library array fill; something like this:

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

In Java the method is java.util.Arrays.fill(...).


The problem is that you have hard-coded the length of the array that you are using to 100. The length of the array should be m + 1 where m is the maximum element on the original array. This is the first reason that you would think using counting-sort, if you have information about the elements of the array are all minor that some constant and it would work great.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜