基数排序编程实现(C/C++)

1.基于静态链表:

#include<iostream>
using namespace std;

#define MAX_NUM_OF_KEY 8
#define RADIX 10
#define MAX_SPACE 100
#define KeysType int
typedef struct
{
 KeysType keys[MAX_NUM_OF_KEY];
 int next;
}SLCell;
typedef struct{
 SLCell r[MAX_SPACE];
 int keynum;
 int recnum;
}SLList;
typedef int ArrType[RADIX+2];

int Get_thousand(int a)
{
 return (a/1000);
}

int Get_hundred(int a)
{
 return (a-Get_thousand(a)*1000)/100;
}

int Get_ten(int a)
{
 return (a-Get_thousand(a)*1000-Get_hundred(a)*100)/10;
}

int Get_one(int a)
{
  return a%10;
}

void Distribute(SLCell *r,int i,ArrType &f,ArrType &e)//完成一趟排序
{
 for(int j=0;j<RADIX+2;j++)f[j]=0,e[j]=0;
 for(int p=r[0].next;p;p=r[p].next)
 {
  int j=r[p].keys[i];
  if(!f[j])f[j]=p;
  else r[e[j]].next=p;
  e[j]=p;               //将p所指的结点插入第j个字表中
 }
}

void Collect(SLCell *r,int i,ArrType f,ArrType e)//完成一趟收集
{
 int j;
 for(j=0;!f[j];j++);
 r[0].next=f[j];
 int t=e[j];
 while(j<RADIX)
 {
  for(j=j+1;(j<RADIX-1)&(!f[j]);j++); //寻找下一个非空子表
  if(f[j])
  {
   r[t].next=f[j];t=e[j]; //连接两个非空子表
  }
 }
 r[t].next=0;
}

void RadixSort(SLList &L)//基数排序
{
 for(int i=0;i<L.recnum;i++)L.r[i].next=i+1;
 L.r[L.recnum].next=0;      //把顺序表改造成真正的静态链表
 ArrType f,e;
 for(int i=0;i<L.keynum;i++)
 {
  Distribute(L.r,i,f,e);//一趟排序
  Collect(L.r,i,f,e);//一趟收集
 }
}

void InitList(SLList &L)//初始化顺序表
{
 L.keynum=0;
 L.recnum=0;
 for(int i=0;i<MAX_SPACE;i++)
 {
  L.r[i].next=0;
  for(int j=0;j<MAX_NUM_OF_KEY;j++)
     L.r[i].keys[j]=0;
 }
}

void ShowList(SLList L)
{
 printf("\n输出排序结果:\n");
 for(int p=L.r[0].next;p;p=L.r[p].next)
 {
  printf("%d%d%d%d ",L.r[p].keys[3],L.r[p].keys[2],L.r[p].keys[1],L.r[p].keys[0]);
 }
 cout<<endl;
}

int main()
{
 int p[8]={0};
 printf("\n请输入8个千位数:\n");
 
 for(int i=0;i<8;i++)
 {
   scanf("%d",&p[i]);
 }
  
 SLList L;
 InitList(L);//初始化
 L.keynum=4;
 L.recnum=8;
 for(int i=1;i<=L.recnum;i++)
 {
  L.r[i].keys[3]=Get_thousand(p[i-1]);
  L.r[i].keys[2]=Get_hundred(p[i-1]);
  L.r[i].keys[1]=Get_ten(p[i-1]);
  L.r[i].keys[0]=Get_one(p[i-1]);
 }
 
 RadixSort(L); 
 ShowList(L);
}

参考资料:严蔚敏《数据结构》、C语言实现基数排序 (数据结构 严蔚敏版)

运行结果:
在这里插入图片描述
有一点需要值得注意,严蔚敏所写的伪代码如果直接写在机器上会发生段错误,该错误发生在执行collect函数中的while循环的if语句中,由于ArrType数组越界导致。对此有两种改法:
(1)

typedef int ArrType[RADIX];

改为:

typedef int ArrType[RADIX+2];

(2)在Collect函数中:

while(j<RADIX)

改为:

while(j<RADIX-1)

2.基于常规单链表:

在这里先做出一个假设,我们事先知道单链表中所存的数的范围大于0

#include<iostream>
#include<cmath>
using namespace std;

#define ElemType int
typedef struct LNode
{
 ElemType data;
 struct LNode* next;
}LNode,*LinkList;

//算法整体设计.............................................
#define RADIX 10
typedef LNode* ArrType[RADIX];
int keynum;//一个记录中的关键字个数
int Calculate_keynum(LinkList L)//为每个记录确定统一的关键字个数
{
 LNode* p=L->next;
 int biggest=p->data;
 for(p=p->next;p;p=p->next)
 {
  if(p->data>biggest)biggest=p->data;
 }
 for(int i=1;;i++)
   if(biggest%(int)pow(10,i)==biggest)
      return i;
}

void Distribute(LinkList &L,int i,ArrType &f,ArrType &e)//一趟分配
{
 for(int i=0;i<RADIX;i++)f[i]=NULL,e[i]=NULL;
 for(LNode* p=L->next;p;p=p->next)
 {
  int j=(p->data)%(int)pow(10,i)/(int)pow(10,i-1);//锁定每个链表结点中存的数的第i位上的数
  if(!f[j])
    f[j]=p;
  else
    e[j]->next=p;
  e[j]=p;                 //e[j]和f[j]所形成的队列中的所有数的第i位上的数都是j
 }
}

void Collect(LinkList &L,int i,ArrType &f,ArrType &e)//一趟收集
{
 int j;
 for(j=0;!f[j];j++);
 L->next=f[j];
 LNode* t=e[j];
 while(j<RADIX-1)
 {
  for(j=j+1;j<(RADIX-1)&&(!f[j]);j++);
  if(f[j])
  {
   t->next=f[j];
   t=e[j];
  }
 }
 t->next=NULL;
}

void RadixSort(LinkList &L)//对常规单链表实施基数排序
{
 ArrType f,e;
 keynum=Calculate_keynum(L);//为每个记录确定统一的关键字个数
 for(int i=1;i<=keynum;i++)
 {
  Distribute(L,i,f,e);//一趟分配
  Collect(L,i,f,e);   //一趟收集
 }  
}
//.................................................................................

void CreateList_R(LinkList &L,int n)//尾插法创建单链表
{
 L=new LNode;
 L->next=NULL;
 LNode* r=L;
 for(int i=0;i<n;i++)
 {
  LNode* p=new LNode;
  cin>>p->data;
  p->next=NULL;
  r->next=p;
  r=p;
 }
}

void ShowList(LinkList L)
{
 printf("\n输出基数排序后的单链表:\n");
 for(LNode* p=L->next;p;p=p->next)
    printf("%d ",p->data);
 printf("\n");
}

void DestroyList(LinkList &L)//销毁链表
{
 LNode* p=L;
 LNode* q=L->next;
 while(p)
 {
  printf("\n成功删除%d\n",p->data);
  delete p;
  p=q;
  if(q!=NULL)q=q->next;
 }
}

int main()
{
 LinkList L;
 int n;
 printf("\n输入单链表元素个数:\n");
 scanf("%d",&n);
 printf("\n创建单链表:\n");
 CreateList_R(L,n);//尾插法创建单链表
 
 RadixSort(L);
 ShowList(L);
 DestroyList(L);
}

运行效果展示:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值