我读过一个计数排序算法,如下所示:
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
我想知道,如果我将最后一个更改为:for j<--1 to n
,算法也将是正确的???(有没有办法证明这个“for”算法将是正确的???)
这样算法也是稳定的吗?
感谢
答案 0 :(得分:4)
算法两种方式都是正确的。它现在也很稳定。
如果您将上一个for
更改为您所说的内容,它将会停止稳定。
基本上,C[i] = how many elements <= i exist
在第三个for
循环结束后。因此,C[A[j]]
会按排序顺序为您提供值为A[j]
的元素的最后位置,C[A[j]] - 1
倒数第二个位置值为A[j]
的元素,依此类推。这就是你减少C
中值的原因。
因此,如果您关心稳定性,则必须以相反的顺序开始迭代原始数组:以便原始数组中具有值x
的最后一个元素首先放入新数组中。反向迭代原始数组将保证x
在所有其他值等于x
之后,从而使算法稳定。
答案 1 :(得分:2)
好的,简短解释算法:
因为您在C数组中存储了不同数字的最后位置,所以您也必须在A数组的末尾开始。如果您只使用整数,那么如果从j < - 1到n
开始,算法也是正确的 没有给出稳定性:例如1s将按逆序示例:(我添加了一次索引,两次显示顺序)
A [1a,2,1b]
首先进行循环
第二个循环
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
第三个循环
C [2] = 3
第四个循环
J = B [2] = 1A C [1] = 1
J = 2 B [3] = 2 C [2] = 2
J = 3 B [1] = 1b的 C [1] = 0
由于:
=&GT;不稳定
答案 2 :(得分:0)
这个算法对我来说似乎很稳定。
如果您更改了上一个for
,那么它仍然是正确的,但不会稳定。 (将颠倒相等元素的顺序)。
答案 3 :(得分:0)
是的,1 to n
仍会正确排序,但您会使用n downto 1
的稳定性。
在第二个循环C
包含推理总和之后,这些值恰好是最终数组中每个数字的 last 元素的标记。这就是为什么倒退会带来稳定性。
您也可以获得1 to n
的稳定性:
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
累积金额有点难看。但我相信这可以做得更好。