(十)1.5_基数排序

在这里插入图片描述

一.相关概念

  基数排序(radix sort)属于“分配式排序”(distribution sort),又称“桶子法”(bucket sort)或bin sort.它是桶排序的扩展,其中基数指得是一个关键字取值的种数,例如十进制的整数,每位的数字都可以取0~9中的一个数,有10种取法,所以十进制整数的基数是10
  基数排序的基本思想是:将整数按位切割成不同的数字,然后将每位的数字进行排序; 具体做法是将所有待排序数值统一为相同数位长度,数位较短的数前面补零。然后从最低位开始,依次进行一次分配排序,以每位的数字为序号分配到对应的序号的队列,全部数字分配完成后,再进行出队收集(从低序号队列开始收集).然后再以同样的原理分配和收集下一位,直到最高位也完成分配和收集,则排序完成
  该算法一共需要分配收集d趟,d为序列中最大的那个数字的位数,如果最大的数字有3位,则需分配和收集3趟,如果有n位,则需要分配收集n趟

  如图:
在这里插入图片描述


二.思路分析

  这里来讲一讲代码中怎么实现基数排序

  1.首先,我们知道基数排序分配和收集需要d趟,而这个d取决于序列中的最大的那个数字位数.所以我们用选择法先对序列进行一次遍历,选出最大的那个数字,然后我们对那个数字取10的对数,就得到了数字有多少位,也就是算出了d

  2.为了实现分配和收集,我们可以创建一个容量为10的数组来存储10个队列(队头指针),数组的索引就是队列的序号,分配时以每位的数字为序号,分配到对应序号的队列(入队),收集时按队列从小到大的序号顺序进行出队收集

  3.怎么切割一个数字的每位数字?这个也容易,假如我们要分离数字X的个位,我们只需使X除以1取整然后模以10就能得到个位数字,即(X/1)%10,要分离十位,我们就使X除以10取整然后模以10就能得到十位数字,即(X/10)%10;同理,百位就是(X/100)%10,千位就是(X/1000)%10,万位,百万位,千万位…也是同样的原理

  好了,知道了上面几个知识点我们就可以写代码了



三.代码实现

注意:顺序表中零单元不用,从索引1开始存储元素

//基数排序(排列为递增序列) 
void RadixSort(SqList &L)
{
	int max=L.elem[1];
	for(int i=1;i<=L.length;i++)         //找出最大元素 
	   max=max>L.elem[i]?max:L.elem[i];
	int d=log(max)/log(10)+1;       //十进制元素的位数
	typedef struct Node    //链结点 
	{
		ElemType e;
		struct Node *next;		
	}*LinkList,LNode;
		
	LinkList front[10]; //10个队头指针,构建10个链队列 
	LinkList rear[10];  //10个队尾指针 
	for(int i=0;i<=9;i++)      //给队头申请内存 
	{
		front[i]=(LinkList)malloc(sizeof(LNode));
		front[i]->next=NULL;	
	}
	int i,n;          //i线性表遍历位置,n队列序号 
	LinkList node;    //链结点指针 
   for(int count=1,x=1;count<=d;count++,x*=10)  //count排序趟数,x除数 
   {	
   		for(n=0;n<=9;n++)      //初始队尾指针指向队头 
			rear[n]=front[n];
   		for(i=1;i<=L.length;i++)   //分配 
		{	
			n=(L.elem[i]/x)%10;    //数字其中一位的数   
			node=(LinkList)malloc(sizeof(LNode));  //创建新结点 
			node->e=L.elem[i];		//存入数据 
			node->next=NULL;    
 			rear[n]->next=node;     //入队(后接法),分配到对应序号的队列 
			rear[n]=node;			
		}					
		for(n=0,i=1;n<=9;n++)		//收集 
		{
			for(node=front[n]->next;node!=NULL;node=front[n]->next,i++) //依次把0~9号队列的元素收集起来 
			{
				L.elem[i]=node->e;			//读取数据 
				front[n]->next=node->next;   //出队 
				free(node);			      //删除出队结点 
			}		
		}  	
   }	
}

操作结果:
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值