6-1 基数排序 分数 10 作者 王东 单位 贵州师范学院

        题目:

实现基数排序。

函数接口定义:

void Distribute(SLCell *r,int i,int *f,int *e); 
//静态链表L的r域中记录已按(keys[0], …, keys[i-1])有序 
//该函数按第i个关键字keys[i]建立RADIX个子表,使同一子表中记录的keys[i]相同。 
//f[0..RADIX-1]和e[0..RADIX-1]分别指向各子表中第一个和最后一个记录
void Collect (SLCell *r,int i,int *f,int *e);
//该函数按keys[i]自小至大地将f[0..RADIX-1]所指各子表依次链接成一个链表 
//e[0..RADIX-1]为各子表的尾指针

裁判测试程序样例:

#include <iostream>
#define MAXNUM_KEY 8  //关键字项数的最大值 
#define RADIX 10      //关键字基数,此时是十进制整数的基数 
#define MAX_SPACE 10000 
using namespace std;

typedef struct
{ 
  char keys[MAXNUM_KEY];   //关键字 
  int next; 
}SLCell;              //静态链表的结点类型 
typedef struct
{ 
  SLCell r[MAX_SPACE];  //静态链表的可利用空间,r[0]为头结点 
  int keynum;           //记录的当前关键字个数 
  int recnum;          //静态链表的当前长度 
}SLList;              //静态链表类型 

void InitList(SLList *L)
{ 
  int i,n,keynum;     
  cin>>n>>keynum;
  (*L).keynum=keynum;
  (*L).recnum=n;
  for(i=1;i<=n;i++)
    cin>>(*L).r[i].keys;
}

void Distribute(SLCell *r,int i,int *f,int *e); 
void Collect (SLCell *r,int i,int *f,int *e);

void RadixSort(SLList &L)
{ 
   int i;
   int f[RADIX],e[RADIX];
   for(i=0;i<L.recnum;++i)  L.r[i].next=i+1; 
   L.r[L.recnum].next = 0; //将L改造为静态链表
   for(i=L.keynum-1;i>=0;i--) 
   {           
     Distribute(L.r,i,f,e); //第i趟分配
     Collect(L.r,i,f,e);    //第i趟收集
   }
}
 
void print(SLList L)
{  
  int p,flag=1;
  for(p=L.r[0].next;p;p=L.r[p].next)
  {if(flag)
   {cout<<L.r[p].keys;flag=0;}
   else
    cout<<" "<<L.r[p].keys;
   }
}

int main()
{
  SLList l;
  InitList(&l);
  RadixSort(l);
  print(l);
  return 0;
}
/* 请在这里填写答案 */

输入样例:

第一行输入待排序个数n和关键字个数keynum,接下来输入n个数(字符串)。

10 3
278 109 063 930 589 184 505 269 008 083

输出样例:

输出排序结果。

008 063 083 109 184 269 278 505 589 930

思路:

基数排序原理略

本题中,储存待排序的数据使用的是静态链表,它以数组实现,数组每一个元素是SLCell的结构体。它包含两个部分,数据域(char类型数组)和下一个元素的数组下标(int类型)。头节点为r[0],尾结点next为0。

用于根据关键字分配的每一个子表使用f数组和e数组分别标定开头和结尾的元素的数组下标,中间的则是使用链表链接。例如,在测试样例中,最后一位关键字是9的有109、589和269,一开始将109放入9对应的子表中时,需要令f[9] = 2(109的数组下标是2) e[9] = 2(只有一个元素时头和尾相同),接下来,放入589,则需要让109.next = 589并更新e[9] = 5,同理放入269。

在收集时,只需要把这些子表按从小到大链接起来即可,比如e[2].next = f[3]。此处要注意空子表不需要链接,头节点应该指向第一个不为空的子表

代码:

void Distribute(SLCell *r,int i,int *f,int *e)
{
    //初始化分配表格,指向为0代表空
    for(int j = 0;j<RADIX;j++)
        f[j] = e[j] = 0;
    //根据头节点,遍历静态链表,直到为空
    int j = r[0].next;
    while(j!=0)
    {
        int loc = r[j].keys[i] - '0';//他在数组的哪个位置
        if(f[loc] == 0)//当前这个格是空,就把这个数放进去
        //并让开始和最后同时指向它
        {
            f[loc] = j;
            e[loc] = j;
        }
        else//否则就让末尾元素指向这个数,并把末尾也指向这个数
        {
            r[e[loc]].next = j;
            e[loc] = j;
        }
        j = r[j].next;
    }
    //让最后一个的next指向0
    int k = 9;
    while(e[k]==0)
        k--;
    r[e[k]].next = 0;
}

void Collect (SLCell *r,int i,int *f,int *e)
{
    //找到第一个不为零的小链表开始赋给头节点
    int j = 0;
    while(f[j]==0)
        j++;
    r[0].next = f[j];
    //前一个小链表的结尾对应的元素连接下一个小链表的开头
    for(;j<RADIX-1;j++)
    {
        //如果下一个小链表是空,就把这一个end的值赋给下一个的end
        if(f[j+1] == 0)
        {
            e[j+1] = e[j];
        }
        else//即使这个小链表是空,他所记录的end也不是0,而是上一个不为0的end值
        {
            r[e[j]].next = f[j+1];
        }
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值