首先,介绍箱排序。
箱排序的基本思想是:设置若干个箱子,依次扫描待排序的记录,把关键字等于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
运行结果: