数据结构基础(15) --基数排序

简介:     基数排序是一种借助“多关键字排序”的思想来实现“单关键字排序”的内部排序算法。实现多关键字排序通常有两种作法:   最低位优先法(LSD)    先对K[0]{基数的最低位}进行排序,并按 K(0) 的不同值将记录序列分成若干子序列之后,分别对 K[1] 进行排序,..., K[d-1]依次类推,直至最后对最次位关键字排序完成为止。

    基数排序是一种借助“多关键字排序”的思想来实现“单关键字排序”的内部排序算法。

实现多关键字排序通常有两种作法:

   最低位优先法(LSD)

    先对K[0]{基数的最低位}进行排序,并按 K(0) 的不同值将记录序列分成若干子序列之后,分别对 K[1] 进行排序,..., K[d-1]依次类推,直至最后对最次位关键字排序完成为止。

  最高位优先法(MSD)

    先对 K[d-1]{基数的最高位}进行排序,然后对 K[d-2]进行排序,依次类推,直至对最主位关键字 K[0] 排序完成为止。

 

百度百科对基数排序做了如下介绍:

    基数排序(radix sort)是属于“分配式排序”(distribution sort),基数排序法又称“桶子法”(bucket sort),顾名思义,它是透过键值的部份资讯,将要排序的元素分配至某些“桶”中,藉以达到排序的作用,基数排序法是属于稳定性的排序,在某些时候,基数排序法的效率高于其它的稳定性排序法。

 

链式基数排序基本步骤如下

    1.将待排序记录以数组存储[或者以指针相链,构成一个链表]

    2.”分配”时,按当前”关键字位”所取值,将记录分配到不同的”链表/链队列”(即不同的桶或堆中)中,每条链表中记录的”关键字位”相同;

    3.”收集”时,按当前关键字位取值从小到大(即将这n条链表(n的大小为基数的大小)按照编号, 依次将其中所有的元素取出)将各链表中的元素取出放入到原先的数组或链表中;

    4.对每个关键字位均重复 2) 和 3) 两步n次。

 

如采用LSD对{179, 208, 306, 93, 859, 984, 55, 9, 271, 33}(构成一个链表或者是数组)进行基数排序:

[第一步:按个位排]

 

[第二步:按十位排]


[第三步:按百位排]

 

代码实现(LSD为例):

//寻找数组中最大数字的位数
template <typename Type>
unsigned int maxBits(Type *begin, Type *end)
{
    unsigned int bits = 1;
    //standard作为基准, 如果array中的元素
    //大于standard, 则bits+1
    int standard = 10;

    for (Type *current = begin; current != end; ++current)
    {
        while (*current >= standard)
        {
            standard *= 10;
            ++ bits;
        }
    }

    return bits;
}
/**说明:
  begin:数组起始
  end:数组结尾
  radix:基数

*/
#define DEBUG
template <typename Type>
void radixSort(Type *begin, Type *end, int radix)
{
    //找到数组中最大数字的位数
    int bits = maxBits(begin, end);

    //基数为radix, 则需要radix个链表
    std::list<Type> lists[radix];

    // 需要循环bits次
    for (int d = 0, factor = 1; d < bits; ++d, factor*=10)
    {
        //分配...
        for (Type *current = begin; current != end; ++current)
        {
            //取出相应位置上的数 (比如个位是1)
            int number = ((*current)/factor)%10;
            //则需要将之放到(分配到)标号为1的链表中
            lists[number].push_back(*current);
        }

        //收集...
        Type *current = begin;
        //对radix个链表中的元素进行收集
        for (int i = 0; i < radix; ++i)
        {
            while (!lists[i].empty())
            {
                *current = lists[i].front();

                ++ current;
                lists[i].pop_front();
            }
        }
#ifdef DEBUG
        //打印排序的中间结果
        for (current = begin; current != end; ++ current)
        {
            cout << *current << ' ';
        }
        cout << endl;
#endif // DEBUG
    }
}

template <typename Type>
void radixSort(Type *array, int arraySize, int radix)
{
    return radixSort(array, array+arraySize, radix);
}

时间复杂度分析:

    设待排序列为n个记录,d个关键码,关键码的取值范围为radix,则进行链式基数排序的时间复杂度为O(d(n+radix)),其中,一趟分配时间复杂度为O(n),一趟收集时间复杂度为O(radix),共进行d趟分配和收集.


-测试代码:

int main()
{
    int array[10];
    for (int i = 0; i < 10; ++i)
    {
        array[i] = rand()%1000;
    }
    for (int i = 0; i < 10; ++i)
    {
        cout << array[i] << ' ';
    }
    cout << endl;

    radixSort(array, 10, 10);

    for (int i = 0; i < 10; ++i)
    {
        cout << array[i] << ' ';
    }
    cout << endl;

    return 0;
}

目录
相关文章
|
2月前
|
算法 搜索推荐 Java
数据结构与算法学习十三:基数排序,以空间换时间的稳定式排序,速度很快。
基数排序是一种稳定的排序算法,通过将数字按位数切割并分配到不同的桶中,以空间换时间的方式实现快速排序,但占用内存较大,不适合含有负数的数组。
36 0
数据结构与算法学习十三:基数排序,以空间换时间的稳定式排序,速度很快。
|
6月前
|
算法 C语言
数据结构和算法——桶排序和基数排序(图示、伪代码、多关键字排序,基数排序代码)
数据结构和算法——桶排序和基数排序(图示、伪代码、多关键字排序,基数排序代码)
41 0
|
7月前
|
搜索推荐 算法 Java
【数据结构排序算法篇】----基数排序【实战演练】
【数据结构排序算法篇】----基数排序【实战演练】
59 3
|
存储 算法 搜索推荐
数据结构各内部排序算法总结对比及动图演示(插入排序、冒泡和快速排序、选择排序、堆排序、归并排序和基数排序等)2
数据结构各内部排序算法总结对比及动图演示(插入排序、冒泡和快速排序、选择排序、堆排序、归并排序和基数排序等)2
287 0
|
7月前
|
算法 搜索推荐 Java
数据结构与算法面试:基于比较的排序算法时间复杂度最坏情况下是 O(nlogn),请问有没有更快的算法?(提示:计数排序、基数排序)
数据结构与算法面试:基于比较的排序算法时间复杂度最坏情况下是 O(nlogn),请问有没有更快的算法?(提示:计数排序、基数排序)
54 0
|
7月前
|
算法 搜索推荐 C语言
【408数据结构与算法】—基数排序(桶排序)(二十三)
【408数据结构与算法】—基数排序(桶排序)(二十三)
|
存储 算法 搜索推荐
数据结构各内部排序算法总结对比及动图演示(插入排序、冒泡和快速排序、选择排序、堆排序、归并排序和基数排序等)1
数据结构各内部排序算法总结对比及动图演示(插入排序、冒泡和快速排序、选择排序、堆排序、归并排序和基数排序等)1
219 0
|
算法
408数据结构学习笔记——归并排序、基数排序
408数据结构学习笔记——归并排序、基数排序
160 1
408数据结构学习笔记——归并排序、基数排序
|
算法 搜索推荐 C语言
【408数据结构与算法】—基数排序(桶排序)(二十三)
基数排序也叫桶排序或箱排序,设置若干箱子,将关键字为k的记录放入第k个箱子,然后按序号将非空的连接。
【408数据结构与算法】—基数排序(桶排序)(二十三)
|
存储 Java
Java基础数组模仿栈数据结构案例
Java基础数组模仿栈数据结构案例
Java基础数组模仿栈数据结构案例