数据结构与算法分析 C 语言描述第二版第三章——链表实现基数排序
基数排序(radix sort)算法
算法思想见:
基数排序
排序算法----基数排序(RadixSort(L,max))单链表版本
基数排序从低位而不是从高位排序的原因:
why radix sort preferred to Least Significant Digit first
程序
程序从小到大排序
#include<stdio.h>
#include<math.h>
#include<stdlib.h>
#define RADIX 10 //基数
#define POS_LEN 3 //输入数字的最大位数
struct node;
typedef struct node *ptrtonode;
typedef ptrtonode list;
typedef ptrtonode position;
struct node {
int data;
ptrtonode next;
};
list InitList(void);
void CreatList(list L);
void ShowList(list L);
void RadixSort(list L);
void DeleteList(list L);
int main(void)
{
list L;
L = InitList();
CreatList(L);
puts("\nOriginal numbers:");
ShowList(L);
puts("\nSorted numbers:");
RadixSort(L);
ShowList(L);
DeleteList(L);
return 0;
}
list InitList(void)
{
list L = (list)malloc(sizeof(struct node));
if (L == NULL) {
fprintf(stderr,"out of space\n");
exit(EXIT_FAILURE);
}
L->next = NULL;
return L;
}
void InsertTail(int n, position p) {
list tem = (list)malloc(sizeof(struct node));
tem->data = n;
tem->next = p->next;
p->next = tem;
}
void eatline(void) {
while (getchar() != '\n')
continue;
}
void CreatList(list L)
{
printf("Please enter numbers (no more than %d digits):\n",POS_LEN);
position p = L;
int n;
while (scanf("%d",&n) == 1) {
if ((int)(n / (int)pow(10, POS_LEN)) == 0) {
InsertTail(n,p);
p = p->next;
}
else
break;
}
eatline();
}
void ShowList(list L) {
position p = L->next;
while (p) {
printf("%d ",p->data);
p = p->next;
}
putchar('\n');
}
int IsEmpty(list L)
{
return L->next == NULL;
}
int IsLast(position p, list L)
{
return p->next == NULL;
}
//将L2的首节点,即头节点后一个节点移到L1的尾节点后面
void MoveNode(list L1, list L2) {
position tem1 = L1, tem2;
if (IsEmpty(L2)) {
fprintf(stderr,"Empty linked list\n");
exit(EXIT_FAILURE);
}
while (!IsLast(tem1,L1))
tem1 = tem1->next;
//tem2指向L2所在链表的首节点
//再将该节点从链表中移除
tem2 = L2->next;
L2->next = tem2->next;
//tem2指向的节点放到L1所在链表尾节点后面
tem1->next = tem2;
tem2->next = NULL;
}
void RadixSort(list L) {
if (IsEmpty(L)) {
fprintf(stderr,"Empty linked list\n");
exit(EXIT_FAILURE);
}
list bucket[RADIX];
int num, nsub;
for (int i = 0; i < RADIX; i++)//建立桶并初始化
bucket[i] = InitList();
/*从低位开始将链表中的节点移到对应的桶中
第一次循环:i=0,按照最低位分配链表中数值,下标nsub = num%10
一次分配按照最低位将链表中元素全部取出后,
再按照桶下标顺序将元素按顺序再全部放回链表中
接着开始第二次循环,此时 i=1,按照十位分配链表值,nsub=num/10%10
按此规律循环,直到按照最高位排序好,再按顺序取出即排序完成
*/
for (int i = 0; i < POS_LEN; i++) {
while (!IsEmpty(L)) {
num = L->next->data;
nsub = (int)(num / pow(10,i)) % 10;
MoveNode(bucket[nsub], L);
}
for (int j = 0; j < RADIX; j++)
while (!IsEmpty(bucket[j]))
MoveNode(L, bucket[j]);
}
//排序完成将桶释放
for (int i = 0; i < RADIX; i++)
free(bucket[i]);
}
void DeleteList(list L)
{
position p = L->next, tem;
L->next = NULL;
while (p) {
tem = p->next;
free(p);
p = tem;
}
}
测试结果:
Please enter numbers (no more than 3 digits):
64 8 216 512 27 729 0 1 343 125 1234 2 1
Original numbers:
64 8 216 512 27 729 0 1 343 125
Sorted numbers:
0 1 8 27 64 125 216 343 512 729