一篇博文让你理解基数排序

如果我们有M个数,其范围是1~M,我们可以利用其范围的有限性结合数组实现O(m)的一种排序算法。

我们定义一个数组Count,大小为M,初始化为0,于是Count有M个桶,开始都是空的,然后根据输入的内容,刚在相应的数组上加1,

当一躺遍历完后,则按照数组下标的顺序输出即可。

这种排序就是桶排序(bucket sort ),适用于范围有限的数或字符。

基数排序(radix sort)则是根据桶排序推广而来,人为的划分不同的关键字,对不同的关键字进行桶排序,最后获得有序结果。

对于多关键字排序,我们可以先对主位关键字进行排序,将序列分成若干子序列,然后对子序列进行排序,这种方法称为最高位优先(Most Significant Digit first)MSD法,相反,先按最次关键字进行排序,然后对高一位的关键字进行排序,这种方法称为最低位优先(Least Significant Digit first)LSD
感觉两者原理相同,但是在实现的时候有很大的区别:

  如扑克牌排序,可以先按花色排好,再按面值排好,也可以先按面值排好,再按花色排。若先按花色,即MSD法,是先分桶,每桶之间的顺序先出来,再来对桶内按次关键字分桶,这里要换桶。若先按面值,即LSD,则是桶之间的顺序是仍不清楚的,但是能找出最小的几个有顺序的(桶中元素个数为1),然后按大一级的排又找出几个有顺序的,这是逐级有序的。
再举个例子,比如自然数排序,0,14,8,125,64。先按LSD排,按个位排是,0,14-64,125,8,则0和8的顺序已经出来了,最小两位,然后第二躺按十位0-8,14,125,64则14和65顺序出来了排后两位,最后一躺0-8-14-64,125。排序结束。不用保存中间结果,重新划分桶,比较高效。若按MSD,先按百位,125,0-14-8-64,知道125最大,但第二个桶内的顺序是完全混乱的,踢除125,重新分桶,算法上实现较麻烦。
 要使用基数排序,我们首先就是要构造出不同级别的关键字,选择使用MSD法还是LSD法,存储结构是使用数组还是链表。

这里补充一个数据结构:链表的游标(cursor)的实现。

我们知道并不是所有语言都支持指针的,而且使用指针在很多情况下比数组麻烦的多。所以我们考虑数组来模拟链存储。

链表实现有两个重要的特点:

1、数据存储在一组结构体中,每一个结构体包含有数据以及指向下一个结构体的指针。

2、一个新的结构体可以通过调用malloc而从系统全局内存得到,并可通过调用free来释放

                        ------摘自《数据结构与算法分析》

我们要用游标来模拟这两种特性。

首选定义结构体:

 struct Node{
   ElementType element;存储的元素
   int next; //下一个元素的下标
}
初始化数组,结构如图所示:index表示数组下标


每个元素保存下一个元素的索引,一个接一个,但是数组第一位我们通常不用,因为我们要建立空位置的索引,而数组首部做为未使用位置的头结点。

当我们插入第一个元素a时,首先寻找空位置,从data[0].next处即为空,此时为指向1,则将a插入data[1]中,修改data[0]的next为2;

当然数组有上限,所以最后一个元素的next指向0,表示最后一个元素,若空位置索引指向0,表示已满。

最后可形成如下图所示表:两条链

空位置,0-3-5-7-0

已存储位置:1-2-4-6-0(1处要特殊标记为head,我想是可以放在0的element里)


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值