算法学习-6

三种最基本的线性排序算法

计数排序

计数排序是假设数组A中的元素都是在0到K区间内的整数。构建一个数组C[0,..,k]初始化为-1,如果数组A中的元素互异的话,那么把A的元素拷贝到C中:C[A[i]] = A[i],然后遍历C,把非-1的元素依次拷贝到数组A中即可完成排序。但数组有元素相等要怎么处理了。

元素互异的做法,还可以是C[0,..,k]初始化为0,使C[A[i]] = 1,然后遍历C如果C[i]等于1,就把下标i依次放到A中,这样好像更好。如果有相同的元素,也就是会有C[A[i]] > 1,把下标i连续在A中放入C[A[i]]就行了。

伪代码

COUNTING-SORT(A)
    let C[0..k] be a new array
    for i=0 to k
        c[i] = 0
    for i=1 to A.length
        C[A[i]] = C[A[i]] + 1

    j = 1
    for i=0 to k
        while c[i] >= 1
            A[j] = i
            j = j + 1
            c[i] = c[i] - 1 

对于整数串排序很显然可以得到正确的结果。

上述过程显然只能存粹的排序一个整数串,不能推广到一般化,不能排序数据记录或对象,当一组对象某个属性可以用0到k的整数表示时,则我们可以基于这个属性对对象排序,使用计数排序来排序数组,上面的过程就是错误的。

这里我们依然要假设A[i]表示元素,表示对象,同时A[i]表示某个属性的值且是0到k区间的整数。

先定义一个数组B来存放输出结果,B.length=A.length,当然也可以在数组A上移动元素的位置来排序,但不适合计数排序方法。

思路是通过A[i]的值对应C[0,..,k]中的值来确定放在B[?]的位置,A[i]对应C的下标,如何确定C[A[i]]值,然后通过C[A[i]]的值来确定B[?]的下标?
显然B[?]的下标就是C[A[i]]或者C[A[i]]的表达式。然是如果2个相同的A[i]值,就不好处理了。

可以猜想如果B是A排好序的数组,那么B的下标j就是表示小于数组中元素小于等于B[j]的个数

那么C[A[i]]的值如果==小于等于A[i]值的个数

则B[C[A[i]]] = A[i]就是把A[i]放到排好序对应的位置。

如何计数C[A[i]]

for i=1 to A.length
        C[A[i]] = C[A[i]] + 1
//到这里只是算出了C[A[i]]的值==等于A[i]值的个数

//把小于A[i]值的个数也加上
for j=1 to k
    C[j] = C[j-1] + C[j] 

计算B[C[A[i]]] = A[i]

for i=1 to A.length
    B[C[A[i]]] = A[i]//如果i后面有相同的值会覆盖之前的,C[A[i]]可以减去1来解决
    C[A[i]] = C[A[i]] - 1

这里有一个问题就是相同的值A[i]和A[j],i

for i = A.length to 1
    B[C[A[i]]] = A[i]
    C[A[i]] = C[A[i]] - 1

显然是的。

合并一下,完整代码如下:

COUNTING-SORT(A,B,k)
    let C[0..k] be a new array
    for i=0 to k
        c[i] = 0

    for i=1 to A.length
        C[A[i]] = C[A[i]] + 1
    //到这里只是算出了C[A[i]]的值==等于A[i]值的个数

    //把小于A[i]值的个数也加上
    for j=1 to k
        C[j] = C[j-1] + C[j] 

    for i = A.length downto 1
        B[C[A[i]]] = A[i]
        C[A[i]] = C[A[i]] - 1
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值