您的位置:首页 > 理论基础 > 数据结构算法

数据结构 排序 基数排序

2007-04-12 17:33 489 查看
基数排序是一种借助多关键字排序思想对单关键字进行排序的方法,它是借助“分配”和“收集”2种操作对单关键字进行排序的。

链式基数排序程序:

c1.h




/**//* c1.h (程序名) */


#include<string.h>


#include<ctype.h>




#include<malloc.h> /**//* malloc()等 */




#include<limits.h> /**//* INT_MAX等 */




#include<stdio.h> /**//* EOF(=^Z或F6),NULL */




#include<stdlib.h> /**//* atoi() */




#include<io.h> /**//* eof() */




#include<math.h> /**//* floor(),ceil(),abs() */




#include<process.h> /**//* exit() */




/**//* 函数结果状态代码 */


#define TRUE 1


#define FALSE 0


#define OK 1


#define ERROR 0


#define INFEASIBLE -1




/**//* #define OVERFLOW -2 因为在math.h中已定义OVERFLOW的值为3,故去掉此行 */




typedef int Status; /**//* Status是函数的类型,其值是函数结果状态代码,如OK等 */




typedef int Boolean; /**//* Boolean是布尔类型,其值是TRUE或FALSE */

c10-3.h




/**//* c10-3.h 基数排序的数据类型 */


#define MAX_NUM_OF_KEY 8 /* 关键字项数的最大值 */


#define RADIX 10 /* 关键字基数,此时是十进制整数的基数 */


#define MAX_SPACE 1000


typedef struct




...{




KeysType keys[MAX_NUM_OF_KEY]; /**//* 关键字 */




InfoType otheritems; /**//* 其它数据项 */


int next;




}SLCell; /**//* 静态链表的结点类型 */




typedef struct




...{




SLCell r[MAX_SPACE]; /**//* 静态链表的可利用空间,r[0]为头结点 */




int keynum; /**//* 记录的当前关键字个数 */




int recnum; /**//* 静态链表的当前长度 */




}SLList; /**//* 静态链表类型 */






typedef int ArrType[RADIX]; /**//* 指针数组类型 */

源文件:




/**//* alg10-11.c 链式基数排序 */




typedef int InfoType; /**//* 定义其它数据项的类型 */




typedef int KeyType; /**//* 定义RedType类型的关键字为整型 */


typedef struct




...{




KeyType key; /**//* 关键字项 */




InfoType otherinfo; /**//* 其它数据项 */




}RedType; /**//* 记录类型(同c10-1.h) */




typedef char KeysType; /**//* 定义关键字类型为字符型 */


#include"c1.h"


#include"c10-3.h"


void InitList(SLList *L,RedType D[],int n)




...{ /**//* 初始化静态链表L(把数组D中的数据存于L中) */


char c[MAX_NUM_OF_KEY],c1[MAX_NUM_OF_KEY];




int i,j,max=D[0].key; /**//* max为关键字的最大值 */


for(i=1;i<n;i++)


if(max<D[i].key)


max=D[i].key;


(*L).keynum=(int)(ceil(log10(max)));


(*L).recnum=n;


for(i=1;i<=n;i++)




...{


(*L).r[i].otheritems=D[i-1].otherinfo;




itoa(D[i-1].key,c,10); /**//* 将10进制整型转化为字符型,存入c */




for(j=strlen(c);j<(*L).keynum;j++) /**//* 若c的长度<max的位数,在c前补'0' */




...{


strcpy(c1,"0");


strcat(c1,c);


strcpy(c,c1);


}


for(j=0;j<(*L).keynum;j++)


(*L).r[i].keys[j]=c[(*L).keynum-1-j];


}


}




int ord(char c)




...{ /**//* 返回k的映射(个位整数) */


return c-'0';


}






void Distribute(SLCell r[],int i,ArrType f,ArrType e) /**//* 算法10.15 */




...{ /**//* 静态键表L的r域中记录已按(keys[0],...,keys[i-1])有序。本算法按 */




/**//* 第i个关键字keys[i]建立RADIX个子表,使同一子表中记录的keys[i]相同。 */




/**//* f[0..RADIX-1]和e[0..RADIX-1]分别指向各子表中第一个和最后一个记录 */


int j,p;


for(j=0;j<RADIX;++j)




f[j]=0; /**//* 各子表初始化为空表 */


for(p=r[0].next;p;p=r[p].next)




...{




j=ord(r[p].keys[i]); /**//* ord将记录中第i个关键字映射到[0..RADIX-1] */


if(!f[j])


f[j]=p;


else


r[e[j]].next=p;




e[j]=p; /**//* 将p所指的结点插入第j个子表中 */


}


}




int succ(int i)




...{ /**//* 求后继函数 */


return ++i;


}




void Collect(SLCell r[],ArrType f,ArrType e)




...{ /**//* 本算法按keys[i]自小至大地将f[0..RADIX-1]所指各子表依次链接成 */




/**//* 一个链表,e[0..RADIX-1]为各子表的尾指针。算法10.16 */


int j,t;




for(j=0;!f[j];j=succ(j)); /**//* 找第一个非空子表,succ为求后继函数 */


r[0].next=f[j];




t=e[j]; /**//* r[0].next指向第一个非空子表中第一个结点 */


while(j<RADIX-1)




...{




for(j=succ(j);j<RADIX-1&&!f[j];j=succ(j)); /**//* 找下一个非空子表 */


if(f[j])




...{ /**//* 链接两个非空子表 */


r[t].next=f[j];


t=e[j];


}


}




r[t].next=0; /**//* t指向最后一个非空子表中的最后一个结点 */


}




void printl(SLList L)




...{ /**//* 按链表输出静态链表 */


int i=L.r[0].next,j;


while(i)




...{


for(j=L.keynum-1;j>=0;j--)


printf("%c",L.r[i].keys[j]);


printf(" ");


i=L.r[i].next;


}


}




void RadixSort(SLList *L)




...{ /**//* L是采用静态链表表示的顺序表。对L作基数排序,使得L成为按关键字 */




/**//* 自小到大的有序静态链表,L.r[0]为头结点。算法10.17 */


int i;


ArrType f,e;


for(i=0;i<(*L).recnum;++i)


(*L).r[i].next=i+1;




(*L).r[(*L).recnum].next=0; /**//* 将L改造为静态链表 */


for(i=0;i<(*L).keynum;++i)




...{ /**//* 按最低位优先依次对各关键字进行分配和收集 */




Distribute((*L).r,i,f,e); /**//* 第i趟分配 */




Collect((*L).r,f,e); /**//* 第i趟收集 */


printf("第%d趟收集后: ",i+1);


printl(*L);


printf(" ");


}


}




void print(SLList L)




...{ /**//* 按数组序号输出静态链表 */


int i,j;


printf("keynum=%d recnum=%d ",L.keynum,L.recnum);


for(i=1;i<=L.recnum;i++)




...{


printf("keys=");


for(j=L.keynum-1;j>=0;j--)


printf("%c",L.r[i].keys[j]);


printf(" otheritems=%d next=%d ",L.r[i].otheritems,L.r[i].next);


}


}






void Sort(SLList L,int adr[]) /**//* 改此句(类型) */




...{ /**//* 求得adr[1..L.length],adr[i]为静态链表L的第i个最小记录的序号 */


int i=1,p=L.r[0].next;


while(p)




...{


adr[i++]=p;


p=L.r[p].next;


}


}






void Rearrange(SLList *L,int adr[]) /**//* 改此句(类型) */




...{ /**//* adr给出静态链表L的有序次序,即L.r[adr[i]]是第i小的记录。 */




/**//* 本算法按adr重排L.r,使其有序。算法10.18(L的类型有变) */


int i,j,k;




for(i=1;i<(*L).recnum;++i) /**//* 改此句(类型) */


if(adr[i]!=i)




...{


j=i;




(*L).r[0]=(*L).r[i]; /**//* 暂存记录(*L).r[i] */


while(adr[j]!=i)




...{ /**//* 调整(*L).r[adr[j]]的记录到位直到adr[j]=i为止 */


k=adr[j];


(*L).r[j]=(*L).r[k];


adr[j]=j;




j=k; /**//* 记录按序到位 */


}


(*L).r[j]=(*L).r[0];


adr[j]=j;


}


}




#define N 10


void main()




...{




RedType d
=...{...{278,1},...{109,2},...{63,3},...{930,4},...{589,5},...{184,6},...{505,7},...{269,8},...{8,9},...{83,10}};


SLList l;


int *adr;


InitList(&l,d,N);


printf("排序前(next域还没赋值): ");


print(l);


RadixSort(&l);


printf("排序后(静态链表): ");


print(l);


adr=(int*)malloc((l.recnum)*sizeof(int));


Sort(l,adr);


Rearrange(&l,adr);


printf("排序后(重排记录): ");


print(l);


}

程序执行结果如下:


排序前(next域还没赋值):


keynum=3 recnum=10


keys=278 otheritems=1 next=-858993460


keys=109 otheritems=2 next=-858993460


keys=063 otheritems=3 next=-858993460


keys=930 otheritems=4 next=-858993460


keys=589 otheritems=5 next=-858993460


keys=184 otheritems=6 next=-858993460


keys=505 otheritems=7 next=-858993460


keys=269 otheritems=8 next=-858993460


keys=008 otheritems=9 next=-858993460


keys=083 otheritems=10 next=-858993460


第1趟收集后:


930 063 083 184 505 278 008 109 589 269


第2趟收集后:


505 008 109 930 063 269 278 083 184 589


第3趟收集后:


008 063 083 109 184 269 278 505 589 930


排序后(静态链表):


keynum=3 recnum=10


keys=278 otheritems=1 next=7


keys=109 otheritems=2 next=6


keys=063 otheritems=3 next=10


keys=930 otheritems=4 next=0


keys=589 otheritems=5 next=4


keys=184 otheritems=6 next=8


keys=505 otheritems=7 next=5


keys=269 otheritems=8 next=1


keys=008 otheritems=9 next=3


keys=083 otheritems=10 next=2


排序后(重排记录):


keynum=3 recnum=10


keys=008 otheritems=9 next=3


keys=063 otheritems=3 next=10


keys=083 otheritems=10 next=2


keys=109 otheritems=2 next=6


keys=184 otheritems=6 next=8


keys=269 otheritems=8 next=1


keys=278 otheritems=1 next=7


keys=505 otheritems=7 next=5


keys=589 otheritems=5 next=4


keys=930 otheritems=4 next=0


Press any key to continue

算法的复杂度:O(n)。

程序参考:《《数据结构》算法实现及解析》。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: