基数排序是一种不需要比较就能实现排序的算法思维,主要步骤为分配和收集的过程,重复这个过程于最大数的位数后,排序结束。
以下是完全以队列模拟桶的分配收集过程。
头文件(单链表部分):
typedef int ElemType;
typedef struct LNode
{
ElemType data;
struct LNode *next;
}LNode,*LinkList;
int InitList_link(LinkList *head) //初始化函数
{
*head=(LinkList)malloc(sizeof(LNode)); //产生头结点
if(NULL==*head)
return -1; //初始化失败
(*head)->next=NULL;
return 0; //初始化成功
}
int ListEmpty_link(LinkList head) //判空函数
{
if(NULL==head->next)
return 1; //单链表为空
return 0; //单链表不为空
}
int ListLength_link(LinkList head) //求长度函数
{
int len=0;
LNode *p=head->next;
while(NULL!=p)
{
len++;
p=p->next;
}
return len;
}
int ListGet_link(LinkList head, int i, ElemType *x) //取单链表中的某一个元素
{
LNode *p;
int j;
p=head;
j=-1;
while(p->next!=NULL&&j<i) //查找返回
{
p=p->next;
j++;
}
if(j!=i)
{
printf("取元素位置参数错");
return 0;
}
*x=p->data;
return 1;
}
int ListInsert_link(LinkList head,int i,ElemType e) //在任意位置进行插入
{
int count=0;
LNode *p=head,*q=NULL;
while(count<i-1&&NULL!=p)
{
p=p->next;
count++;
}
if(count>i-1||NULL==p)
return -1;
q=(LNode *)malloc(sizeof(LNode));
if(NULL==q)
return -2;
q->data=e;
q->next=p->next;
p->next=q;
return 0;
}
头文件(队列)部分:
#define MAX 100
typedef enum{Empty,Full} StateType;
typedef struct
{
ElemType data[MAX];
int front,rear;
StateType tag;
}CSqQueue;
int InitQueue_csq(CSqQueue *Q) //顺序循环队列---课本代码
{
(*Q).front=0;
(*Q).rear=0;
(*Q).tag=Empty;
return 0;
}
int QueueEmpty_csq(CSqQueue Q)
{
if(Q.front==Q.rear&&Empty==Q.tag)
return 1;
return 0;
}
int QueueFull_csq(CSqQueue Q)
{
if(Q.front==Q.rear&&Full==Q.tag)
return 1;
return 0;
}
int QueueLength_csq(CSqQueue Q)
{
if(QueueEmpty_csq(Q))
return 0;
else if(QueueFull_csq(Q))
return MAX;
return (Q.rear-Q.front+MAX)%MAX;
}
int EnQueue_csq(CSqQueue *Q,ElemType e)
{
if(QueueFull_csq(*Q))
return -1;
(*Q).data[(*Q).rear]=e;
(*Q).rear=((*Q).rear+1)%MAX;
(*Q).tag=Full;
return 0;
}
int DeQueue_csq(CSqQueue *Q,ElemType *e)
{
if(QueueEmpty_csq(*Q))
return -1;
*e=(*Q).data[(*Q).front];
(*Q).front=((*Q).front+1)%MAX;
(*Q).tag=Empty;
return 0;
}
头文件(桶排)部分:
typedef int KeyType;
ElemType MaxList_link(LinkList head)
{
ElemType e;
ElemType a[MAX];
int i;
for(i=0;i<ListLength_link(head);i++)
{ //假设输入为3\1\2
ListGet_link(head,i,&a[i]); //依次取元素3、1、2
}
e=a[0];
for(i=1;i<ListLength_link(head);i++)
{
if(e<a[i])
e=a[i]; //e取最大值
}
return e;
}
int Num(ElemType e)
{
int i=0;
while(e)
{
e/=10;
i++;
}
return i;
}
void RadixSort(LinkList *head,KeyType key)
{
CSqQueue q[10]; //10个队列模拟桶操作过程
ElemType x;
int i,j,k;
ElemType tag;
for(i=0;i<10;i++)
InitQueue_csq(&q[i]); //初始化10桶
for(i=0;i<ListLength_link(*head);i++) //待排的个数
{
ListGet_link(*head,i,&x); //顺序取单链表元素
tag=x;
j=key; //n位数 //这里应该用LSD,而不是MSD
j--;
while(j--) //没有高位补0操作
{
tag/=10;
}
switch(tag%10) //入相应的桶
{
case 0:
EnQueue_csq(&q[0],x);
break;
case 1:
EnQueue_csq(&q[1],x);
break;
case 2:
EnQueue_csq(&q[2],x);
break;
case 3:
EnQueue_csq(&q[3],x);
break;
case 4:
EnQueue_csq(&q[4],x);
break;
case 5:
EnQueue_csq(&q[5],x);
break;
case 6:
EnQueue_csq(&q[6],x);
break;
case 7:
EnQueue_csq(&q[7],x);
break;
case 8:
EnQueue_csq(&q[8],x);
break;
default:
EnQueue_csq(&q[9],x);
break;
}
}
k=1;
InitList_link(head);
for(i=0;i<10;i++) //10个桶收集过程
{
for(j=0;j<QueueLength_csq(q[i]);) //这里有个陷阱
{
DeQueue_csq(&q[i],&x);
ListInsert_link(*head,k,x);
k++;
}
}
}
源文件部分:
#include<stdio.h>
#include<stdlib.h>
#include"LinkList.h"
#include"Queue.h"
#include"RadixSort.h"
int main()
{
LinkList list;
int i,x;
KeyType key;
InitList_link(&list);
printf("请输入一组无序的数据以负数结束:");
i=1;
while(scanf("%d",&x)&&x>0)
{
ListInsert_link(list,i,x); //入表
i++;
}
key=Num(MaxList_link(list)); //获得最大数的位数以确定分配收集的次数
int flag=1;
for(i=1;flag<=key;i++)
{
RadixSort(&list,flag);
flag++;
}
printf("基数排序后,该组数据依次为:");
for(i=0;i<ListLength_link(list);i++)
{
ListGet_link(list,i,&x);
printf("%d ",x);
}
return 0;
}
以上代码可以实现基数排序,但是待排的序列中不能含有0,具体没来得及看,嘿嘿~