问题
I have read a counting sort algorithm which is like this:
Counting Sort(A[1,..n]) //C[1,...k] is the temporary memory and k is the range of integers
for i<-- 1 to k
C[i]<-- 0
for j<-- 1 to n
C[A[j]]<--C[A[j]]+1
for i<--2 to k
C[i]<--C[i]+C[i-1]
for j<--n downto 1
B[C[A[j]]]<--A[j]
C[A[j]]<--C[A[j]]-1
I want to know that if I change the last for to this:for j<--1 to n
,the algorithm will be correct too???(is there any way to show that with this "for" the algorithm will be correct??? )
also in this way the algorithm is stable too?
thanks
回答1:
The algorithm is correct both ways. It is also stable as you have it right now.
If you change the last for
to what you said, it will stop being stable.
Basically, C[i] = how many elements <= i exist
after the end of the third for
loop. So C[A[j]]
gives you the the last position of an element with value A[j]
in sorted order, C[A[j]] - 1
the second last position of an element with value A[j]
and so on. This is why you decrement the values in C
.
Because of this, you have to start iterating your original array in reverse order if you care about stability: so that the last element with value x
in your original array gets put first in the new array. Iterating your original array in reverse will guarantee that x
is put after all other values equal to x
, thus making the algorithm stable.
回答2:
Ok, short explaination of the algorithm:
- for loop: initialize the C array with 0 and the size k (the range of integers)
- for loop: count the integer and store the number in C
- for loop: sum up the total number of values less equal the given one Example: there are five 1, three 2, two 3 => c[1] = 5, c[2] = 8, c[3] = 10
- for loop: starting at the end of the A array and putting it to the corresponding C value in the B value and decreasing the value in C
Because you store the last position for the different numbers in the C array, you have to start an the end of the A array, too. If you just work with integers the algorithm would also be correct if you start with j<--1 to n
stability is not given: e.g. the 1s would be in inverse order
Example: (I added indexes to the once, two show the order)
A[1a, 2, 1b]
first for loop
- C[1] = 0
- C[2] = 0
second for loop
j=1: A[1] = 1a
C[1] = 1
C[2] = 0
j=2: A[2]=2
C[1] = 1
C[2] = 1
j=3: A[3]=1b
C[1] = 2
C[2] = 1
third for loop
C[2] = 3
fourth for loop
j=1 b[2]=1a c[1]=1
j=2 b[3]=2 c[2]=2
j=3 b[1]=1b c[1]=0
Resulting:
- b[1] = 1b
- b[2] = 1a
- b[3] = 2
=> not stable
回答3:
The algorithm seems to be stable as it is to me.
If you change the last for
, then it will still be correct, but won't be stable. (will reverse the order of equal elements).
回答4:
Yes, 1 to n
would still sort correctly, but you'll use stability that n downto 1
has.
After the second loop C
contains the comulative sum, those values are exactly the indicies of the last element of each number in the final array. That's why going backwards gives stability.
You can get stability for 1 to n
too:
Counting Sort(A[1,..n]) //C[1,...k] is the temporary memory and k is the range of integers
for i<-- 1 to k
C[i]<-- 0
for j<-- 1 to n
C[A[j]]<--C[A[j]]+1
last <-- C[1]
C[1] <-- 0
for i<--2 to k
tmp <-- C[i]
C[i]<--C[i-1]+last
last <-- tmp
for j<--n downto 1
B[C[A[j]]]<--A[j]
C[A[j]]<--C[A[j]]-1
the cumulative sum gets a bit ugly. But I'm sure this could be done nicer.
来源:https://stackoverflow.com/questions/3076037/about-counting-sort-algorithm