【排序算法】基数排序:LSD 与 MSD

【排序算法】基数排序:LSD 与 MSD1.算法原理基数排序是通过“分配”和“收集”过程来实现排序。1)分配,先从个位开始,根据位值(0-9)分别放到0~9号桶中(比如53,个位为3,则放入3号桶中)2)收集,再将放置在0~9号桶中的数据按顺序放到数组中重复(1)(2)过程,从个位到最高位(比如32位无符号整形最大数4294967296,最高位10位)。而这个思想该如何理解呢?请看以下例子。(1)

大家好,又见面了,我是你们的朋友全栈君。1.算法原理

基数排序是通过“分配”和“收集”过程来实现排序。

1)分配,先从个位开始,根据位值(0-9)分别放到0~9号桶中(比如53,个位为3,则放入3号桶中)

2)收集,再将放置在0~9号桶中的数据按顺序放到数组中

重复(1)(2)过程,从个位到最高位(比如32位无符号整形最大数4294967296,最高位10位)。而这个思想该如何理解呢?请看以下例子。

(1)假设有欲排数据序列如下所示:

73 28 93 43 55 14 22 65 26 81

首先根据个位数的数值,在遍历数据时将它们各自分配到编号0至9的桶(个位数值与桶号一一对应)中。

从低位到高位分配收集过程:

【排序算法】基数排序:LSD 与 MSD

观察可以看到,此时原无序数据序列已经排序完毕。如果排序的数据序列有三位数以上的数据,则重复进行以上的动作直至最高位数为止。
基于两种不同的排序顺序,我们将基数排序分为

    LSD(Least significant digital):排序方式由数值的最右边(低位)开始

    MSD(Most significant digital):由数值的最左边(高位)开始。

注意一点:

LSD的基数排序适用于位数少的数列,如果位数多的话,使用MSD的效率会比较好。

MSD的方式由高位数为基底开始进行分配,但在分配之后并不马上合并回一个数组中,而是在每个“桶子”中建立“子桶”,将每个桶子中的数值按照下一数位的值分配到“子桶”中。在进行完最低位数的分配后再合并回单一的数组中。

由高位到低位分配收集过程:

     73 28 93 43 55 14 22 65 26 81


【排序算法】基数排序:LSD 与 MSD

(2)我们把扑克牌的排序看成由花色和面值两个数据项组成的主关键字排序。要求如下:

     花色顺序:梅花<方块<红心<黑桃

     面值顺序:2<3<4<…<10<J<Q<K<A

那么,若要将一副扑克牌排成下列次序:

     梅花2,…,梅花A,方块2,…,方块A,红心2,…,红心A,黑桃2,…,黑桃A。

有两种排序方法:

<1>先按花色分成四堆,把各堆收集起来;然后对每堆按面值由小到大排列,再按花色从小到大按堆收叠起来。—-称为”最高位优先”(MSD)法。

<2>先按面值由小到大排列成13堆,然后从小到大收集起来;再按花色不同分成四堆,最后顺序收集起来。—-称为”最低位优先”(LSD)法。

2.算法分析

平均时间复杂度:O(dn)(d即表示整形的最高位数)

空间复杂度:O(10n) (10表示0~9,用于存储临时的序列) 

稳定性:稳定

3.程序实现

(1)LSD法实现

最低位优先法首先依据最低位关键码Kd对所有对象进行一趟排序,

再依据次低位关键码Kd-1对上一趟排序的结果再排序,

依次重复,直到依据关键码K1最后一趟排序完成,就可以得到一个有序的序列。

使用这种排序方法对每一个关键码进行排序时,不需要再分组,而是整个对象组。

因为分配和收集阶段,数字符合先入先出的关系。因此可以用10个队列来保存 0-9 上分配的数字,在收集阶段,按先入先出的顺序取出每个桶中的数字,依次放到原数组中。

/********************************************************
*函数名称:GetNumInPos
*参数说明:num 一个整形数据
*     pos 表示要获得的整形的第pos位数据
*说明:    找到num的从低到高的第pos位的数据
*********************************************************/
int GetNumInPos(int num, int pos)
{
	int temp = 1;
	for (int i = 0; i < pos - 1; i++)
		temp *= 10;

	return (num / temp) % 10;
}

#define MAXPOS 10    //最高位的位数
void RadixSort(vector<int> &A)
{
	int len = A.size();
	vector<vector<int>> radixArray(10);  //分为0~9的序列空间

	for (int pos = 1; pos <= MAXPOS; pos++)    //从个位开始到最高位数
	{
		for (int i = 0; i < len; i++)    //分配过程
		{
			int num = GetNumInPos(A[i], pos);
			radixArray[num].push_back(A[i]);
		}

		for (int i = 0, j = 0; i < 10; i++)    //收集
		{
			while (!radixArray[i].empty())
			{
				A[j++] = radixArray[i].front();  //取首部数据依次插入原数组
				radixArray[i].erase(radixArray[i].begin());    //移除首部元素
			}
		}
	}
}

(2)MSD法实现

最高位优先法通常是一个递归的过程:

<1>先根据最高位关键码K1排序,得到若干对象组,对象组中每个对象都有相同关键码K1。

<2>再分别对每组中对象根据关键码K2进行排序,按K2值的不同,再分成若干个更小的子组,每个子组中的对象具有相同的K1和K2值。

<3>依此重复,直到对关键码Kd完成排序为止。

<4> 最后,把所有子组中的对象依次连接起来,就得到一个有序的对象序列。

/********************************************************
*函数名称:GetNumInPos
*参数说明:num 一个整形数据
*     pos 表示要获得的整形的第pos位数据
*说明:    找到num的从低到高的第pos位的数据
*********************************************************/
int GetNumInPos(int num, int pos)
{
 int temp = 1;
 for (int i = 0; i < pos - 1; i++)
  temp *= 10;
 return (num / temp) % 10;
}
//MSD,调用时指定最高位数d
void RadixSort(vector<int> &A, int d)
{
 int len = A.size();
 vector<vector<int>> radixArray(10);  //分为0~9的序列空间,用队列保存每个桶分配的数据
 //位数大于0,且数组长度大于1
 if (d >= 1 && len > 1)
 {
  for (int i = 0; i < len; i++)    //分配过程
  {
   int num = GetNumInPos(A[i], d);
   radixArray[num].push_back(A[i]);
  }
  cout << endl;
  for (int i = 0, j = 0; i < 10; i++)    //收集
  {
   RadixSort(radixArray[i], d-1);  //递归,对每个子桶从次高位开始分配
   while (!radixArray[i].empty())
   {
    A[j++] = radixArray[i].front();  //取队列首部数据依次插入原数组
    radixArray[i].erase(radixArray[i].begin());
   }
  }
 }
}

参考:http://blog.csdn.net/cjf_iceking/article/details/7943609

http://www.cnblogs.com/Braveliu/archive/2013/01/21/2870201.html





版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/132967.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • linux查看硬盘smart信息_检查中ctl是检查什么

    linux查看硬盘smart信息_检查中ctl是检查什么知识介绍SMART是一种磁盘自我分析检测技术,早在90年代末就基本得到了普及每一块硬盘(包括IDE、SCSI)在运行的时候,都会将自身的若干参数记录下来这些参数包括型号、容量、温度、密度、扇区、寻道时间、传输、误码率等硬盘运行了几千小时后,很多内在的物理参数都会发生变化某一参数超过报警阈值,则说明硬盘接近损坏此时硬盘依然在工作,如果用户不理睬这个报警继续使用那么硬盘将变得非常不可靠,随时可能故障启用SMARTSMART是和主板BIOS上相应功能配合的要使用SMART,必须先进入到主板

    2022年10月8日
    0
  • [Err] 1062 – Duplicate entry ‘0’ for key ‘PRIMARY’

    [Err] 1062 – Duplicate entry ‘0’ for key ‘PRIMARY’

    2021年10月17日
    54
  • phpstorm激活码2021到4月_通用破解码

    phpstorm激活码2021到4月_通用破解码,https://javaforall.net/100143.html。详细ieda激活码不妨到全栈程序员必看教程网一起来了解一下吧!

    2022年3月16日
    49
  • C#学生成绩管理系统「建议收藏」

    C#学生成绩管理系统「建议收藏」##课设不用愁C#学生成绩管理系统>学生选课及成绩查询系统是一个学校不可缺少的部分,传统的人工管理档案的方式存在着很多的缺点,如:效率低、保密性差等,所以开发一套综合教务系统管理软件很有必要

    2022年7月3日
    30
  • int是什么_十进制数16的16进制表示格式是

    int是什么_十进制数16的16进制表示格式是Int16意思是16位整数(16bitinteger),相当于short占2个字节-32768~32767Int32意思是32位整数(32bitinteger),相当于int占4个字节-2147483648~2147483647Int64意思是64位整数(64bitinterger),相当于longlong占8个字节…

    2022年4月19日
    323
  • S3C2440中断介绍

    S3C2440中断介绍1.1   S3C2440系统中断CPU和外设构成了计算机系统,CPU和外设之间通过总线进行连接,用于数据通信和控制,CPU管理监视计算机系统中所有硬件,通常以两种方式来对硬件进行管理监视:l  查询方式:CPU不停的去查询每一个硬件的当前状态,根据硬件的状态决定处理与否。好比是工厂里的检查员,不停的检查各个岗位工作状态,发现情况及时处理。这种方式实现起来简单,通常用在只有少量外设硬件的系

    2022年5月5日
    36

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号