最重要的v.s.最不重要的基数排序

时间:2016-02-22 01:20:12

标签: algorithm sorting radix-sort

如果我只需要对由ASCII字符组成的字符串进行排序,那么想知道使用最重要的vs.s之间有什么区别。最不重要的基数排序?我认为他们应该有相同的结果,但是下面链接中的以下陈述会让我感到困惑,如果有人可以帮助澄清,那就太棒了。

https://en.wikipedia.org/wiki/Radix_sort

最高位数(MSD)基数排序可用于按字典顺序对键进行排序。与最低有效位(LSD)基数排序不同,最重要的数字基数排序不一定保留重复键的原始顺序。

提前谢谢, 林

2 个答案:

答案 0 :(得分:5)

LSD基数排序可以在每次传递后在逻辑上连接已排序的二进制数(如果使用计数/基数排序,则将它们视为单个二进制数)。 MSD基数排序必须在每次传递后独立地递归排序每个bin。如果按字节排序,第一次传递后为256个二进制位,第二次传递后为65536个二进制位,第三次传递后为16777216(1600万个)二进制位,....

这就是旧卡分类器首先对数据LSD进行排序的原因。链接到其中一个实际的视频。这些卡片被送入并向下滑入滑槽。在视频中,卡片分类器将卡片放入垃圾箱中#0; 0"到" 9"然后操作员从0箱中取出卡,然后从1箱中取出卡并将它们放在0箱卡的顶部(后面),然后将2个箱卡放在后面。甲板,等等,"连接"箱子里的卡片。对于大型卡片组,卡片分拣机上方将设置每个箱子上方的架子,以便在甲板太大而无法用手握住时放置卡片。

http://www.youtube.com/watch?v=jJH2alRcx4M

示例C ++ LSD基数排序,用于32位无符号整数,其中每个"数字"是一个字节。大多数代码生成一个计数矩阵,这些计数矩阵被转换为标记可变大小区间之间边界的索引。实际的基数排序在最后一个嵌套循环中。

//  a is input array, b is working array
uint32_t * RadixSort(uint32_t * a, uint32_t *b, size_t count)
{
size_t mIndex[4][256] = {0};            // count / index matrix
size_t i,j,m,n;
uint32_t u;
    for(i = 0; i < count; i++){         // generate histograms
        u = a[i];
        for(j = 0; j < 4; j++){
            mIndex[j][(size_t)(u & 0xff)]++;
            u >>= 8;
        }       
    }
    for(j = 0; j < 4; j++){             // convert to indices
        m = 0;
        for(i = 0; i < 256; i++){
            n = mIndex[j][i];
            mIndex[j][i] = m;
            m += n;
        }       
    }
    for(j = 0; j < 4; j++){             // radix sort
        for(i = 0; i < count; i++){     //  sort by current lsb
            u = a[i];
            m = (size_t)(u>>(j<<3))&0xff;
            b[mIndex[j][m]++] = u;
        }
        std::swap(a, b);                //  swap ptrs
    }
    return(a);
}

答案 1 :(得分:2)

令你困惑的部分是几乎所有LSD基数排序都保留了重复键的顺序。那是因为他们依靠这个属性来工作。例如,如果您有2次这样的迭代,首先排序一个位置,然后排序十位:

22        21        11
21   ->   11   ->   21
11        22        22

当我们按十位排序时,我们需要保留我们在按1排序时得到的打破平局顺序,这样即使它们在10s位置具有相同的数字,21和22也会以正确的顺序出现。如果你实现第一种排序(按一种方式),你拥有来执行所有其他排序(以及为什么不呢?),那么排序是稳定的。

MSD基数排序可以使用与LSD基数排序相同的排序步骤编写,在这种情况下它也将是稳定的。但是,还有其他通常更有效的方法来实现没有此属性的MSD基数排序。

保留订单或重复项的MSD-第一基数排序通常是就地的,即它们无需分配单独的数组来保存已排序的元素。

请注意,如果您只是通过比较ASCII代码点来对字符串列表进行排序,则这些都没有任何区别。 “保留重复键的顺序”仅在附加了额外信息时才有意义。例如,如果键具有关联的值,或者您是以与案例无关的方式排序,并且您希望“Abe”和“abE”以与它们相同的顺序排出。