基数排序

首先,介绍箱排序。

箱排序的基本思想是:设置若干个箱子,依次扫描待排序的记录,把关键字等于k的记录全部都装入第k个箱子里,然后按序号依次将各非空的箱子首位连接起来。
箱排序的抽象算法:假设关键字的取值范围是0..m-1的整数,并设B[0..m-1]是一个记录数组,它的每一个分量都是一个链队列,代表一个箱子,B[i].f和B[i].e分别表示该队列的头指针和尾指针。
箱排序缺点:只适用于关键字取值范围较小的情况,否则所需要箱子的数目m太多,会导致存储空间的浪费和计算时间的增长。


其次,基数排序
排序子结点:BoxNode
单个箱子:Box
箱子队列:基数个箱子的数组,组成基数排序的辅助数组.typedef Box Boxes[RadixNum];
基数排序:要求关键码是大于等于0的整数,即自然数.

#if ! defined(RADIXSORT_H)
#define RADIXSORT_H

#include<stdio.h>
#include<stdlib.h>

#define MAXSIZE 100

typedef int KeyType;//关键字类型用来比较
typedef char InfoType;//其他类型的信息
typedef struct{
	KeyType key;//排序用的关键字
	InfoType other;//其他附属信息
}RecType;//记录类型
typedef RecType SeqList[MAXSIZE+1];//+1用来使[0]作为哨兵,但是在实际使用中往往不能使[0]作为哨兵

/*
箱排序
箱排序的基本思想是:设置若干个箱子,依次扫描待排序的记录,把关键字等于k的记录全部都装入第k个箱子里,然后按序号依次将各非空的箱子首位连接起来。
箱排序的抽象算法:假设关键字的取值范围是0..m-1的整数,并设B[0..m-1]是一个记录数组,它的每一个分量都是一个链队列,代表一个箱子,B[i].f和B[i].e分别表示该队列的头指针和尾指针。
箱排序缺点:只适用于关键字取值范围较小的情况,否则所需要箱子的数目m太多,会导致存储空间的浪费和计算时间的增长。

基数排序
排序子结点:BoxNode
单个箱子:Box
箱子队列:基数个箱子的数组,组成基数排序的辅助数组.typedef Box Boxes[RadixNum]; 
基数排序:要求关键码是大于等于0的整数,即自然数.

*/
//基数值
#define RadixNum 10

//箱子节点
typedef struct boxnode{
	RecType data;//存放记录数据
	struct boxnode* next;//下一个节点
}BoxNode;

//单个箱子队列
typedef struct box{
	BoxNode *front;//队头指针
	BoxNode *rear;//队尾指针
}Box;

//基数个箱子队列
typedef Box Boxes[RadixNum];

//初始化队列
void InitBoxes(Boxes boxes){
	int i;
	BoxNode *p;
	for(i=0;i<RadixNum;i++){
		p=(BoxNode*)malloc(sizeof(BoxNode));
		p->next=NULL;
		boxes[i].front=boxes[i].rear=p;
	}
}
//进箱
void InBox(Box *b,RecType *rec){
	BoxNode *node;
	node=(BoxNode*)malloc(sizeof(BoxNode));
	node->data=*rec;//不能存储存储地址,若使用地址在出栈过程中会存在数据丢失现象。有些数据项存在引用排序后的地址,存在重复数据项。
	node->next=NULL;
	b->rear->next=node;
	b->rear=node;
}
int BoxIsEmpty(Box *b){
	return NULL==b->front->next;
}
//出箱
RecType OutBox(Box *b){
	BoxNode *bp;
	bp=b->front;
	b->front=b->front->next;
	free(bp);
	return b->front->data;
}


//求元素的最大值,并求出位数
int MaxKeyLength(RecType R[],int n){
	int max=0,i;
	int maxkey;
	for(i=1;i<n;i++){
		if(R[i].key>R[max].key){
			max=i;
		}
	}

	maxkey=R[max].key;
	i=0;
	while(maxkey){
		i++;
		maxkey=maxkey/RadixNum;
	}

	return i;

}

//求元素关键码指定位置的数值从低到高.例如1是个位,2是十位等等
int NumOfKP(KeyType key,int p,int n){//key是关键码,p是所求的位数,n是最大的位数
	int i;
	int num=key;
	for(i=1;i<=n;i++){
		if(i==p){
			return num%RadixNum;
		}
		num=num/RadixNum;
	}
	return -1;

}

void RadixSort(RecType R[],int n){
	
	int nbits;//最大关键字的位数
	Boxes boxes;//辅助箱子数组
	int i,cpos,j;
	

	nbits=MaxKeyLength(R,n);//计算最大位数
	InitBoxes(boxes);//初始化箱子
	
	cpos=1;
	while(cpos<=nbits){

		//1.按照当前cpos位的值入栈
		for(i=0;i<n;i++){
			//NumOfKP((R+i)->key,cpos,nbits);这是关键码指定位置cpos的值
			InBox(&boxes[NumOfKP((R+i)->key,cpos,nbits)],R+i);
		}


		//2.按照当前cpos位的值出栈
		j=0;
		for(i=0;i<RadixNum;i++){//遍历基数箱子
			while(!BoxIsEmpty(&boxes[i])){

				R[j++]=OutBox(&boxes[i]);
			}
		}

		//3.增加位数
		cpos++;
	}
	
}
void RadixSortTest(){
	RecType SeqList[]={{987,'A'},{4,'B'},{3,'C'},{2,'D'},{1,'E'},{6,'F'},{7,'G'},{5,'H'},{2,'I'},{8,'J'},
						 {9,'K'},{10,'L'},{11,'M'},{12,'N'},{13,'O'},{14,'P'},{1,'Q'},{2,'R'},{3,'S'},{20,'T'}};
	int i,n=20;
	printf("基数排序前:\n");
	for(i=0;i<n;i++){
		printf("%2d,%c ",SeqList[i].key,SeqList[i].other);
		if(i%10 == 9) 
			printf("\n");
	}
	printf("\n");

	RadixSort(SeqList,n);

	printf("基数排序后:\n");
	for(i=0;i<n;i++){
		printf("%2d,%c ",SeqList[i].key,SeqList[i].other);
		if(i%10 == 9) 
			printf("\n");
	}
}

void main(){
	RadixSortTest();
}



#endif
注意文件结尾为.c
运行结果:


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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值