链式基数排序法

一、性能分析:

若有n条记录,记录最多含有a个关键字,每个关键字的基数取值范围为b个值,则:

1.平均时间复杂度 = O(a(n + b))

2.空间复杂度:O(ab)

二、实现:

 1 #define INDEX 10 //关键字基数,此时是十进制整数的基数
 2 #define KEYNUM 2 //最大关键字个数
 3 
 4 typedef struct Node {
 5     int data;
 6     struct Node* next;
 7 }Node;
 8 
 9 struct {
10     Node* head;
11 }L[INDEX];//指针数组L
12 
13 void RadixSort(int a[], int n) {
14     int i, j;
15     for (i = 0; i < KEYNUM; ++i) {
16         for (j = 0; j < INDEX; ++j) {                  //重置链表L
17             L[j].head = NULL;
18         }
19         Distribute(a, i, n);                           //分配数组a中元素的第i项到链表L中
20         Collect(a);                                    //收集链表L中元素到数组a中
21     }
22 }
23 
24 void Distribute(int a[], int m, int n) {               //记录的第m项,元素总数n
25     int i, k;
26     Node *P, *F;
27     for (i = 1; i < n; ++i) {
28         k = Digit(a[i], m);                            //k为a[i]的第m项
29         P = (Node*)calloc(1, sizeof(Node));            //把记录a[i]备份到结点P中
30         P->data = a[i];
31         if (L[k].head) {                               //若链表该域的头指针存在,则链接到该域的尾部
32             for (F = L[k].head; F->next; F = F->next);
33             F->next = P;
34         }
35         else {                                         //否则直接插入结点P
36             L[k].head = P;
37         }
38     }
39 }
40 
41 void Collect(int a[]) {
42     int i = 0, j = 1;
43     Node* P;
44     while (i < INDEX) {
45         for (P = L[i++].head; P; P = P->next) {         //从小到大把链表元素存入数组a中
46             a[j++] = P->data;
47         }
48     }
49 }
50 
51 int Digit(int num, int m) {                             //返回数num中的倒数第m项
52     while (m--) {
53         num /= INDEX;
54     }
55     return num % INDEX;
56 }

三、源代码

 1 //在 Microsoft Visual Studio Community 2022 环境测试通过
 2 #define _CRT_SECURE_NO_WARNINGS
 3 #include <stdio.h>
 4 #include <stdlib.h>
 5 #define INDEX 10 //关键字基数,此时是十进制整数的基数
 6 #define KEYNUM 2 //最大关键字个数
 7 
 8 typedef struct Node {
 9     int data;
10     struct Node* next;
11 }Node;
12 
13 struct {
14     Node* head;
15 }L[INDEX];//指针数组L
16 
17 int Digit(int num, int m) {                            //返回数num中的倒数第m项
18     while (m--) {
19         num /= INDEX;
20     }
21     return num % INDEX;
22 }
23 
24 void Distribute(int a[], int m, int n) {               //记录的第m项,元素总数n
25     int i, k;
26     Node *P, *F;
27     for (i = 1; i < n; ++i) {
28         k = Digit(a[i], m);                            //k为a[i]的第m项
29         P = (Node*)calloc(1, sizeof(Node));            //把记录a[i]备份到结点P中
30         P->data = a[i];
31         if (L[k].head) {                               //若链表该域的头指针存在,则链接到该域的尾部
32             for (F = L[k].head; F->next; F = F->next);
33             F->next = P;
34         }
35         else {                                         //否则直接插入结点P
36             L[k].head = P;
37         }
38     }
39 }
40 
41 void Collect(int a[]) {
42     int i = 0, j = 1;
43     Node* P;
44     while (i < INDEX) {
45         for (P = L[i++].head; P; P = P->next) {        //从小到大把链表元素存入数组a中
46             a[j++] = P->data;
47         }
48     }
49 }
50 
51 void RadixSort(int a[], int n) {
52     int i, j;
53     for (i = 0; i < KEYNUM; ++i) {
54         for (j = 0; j < INDEX; ++j) {                  //重置链表L
55             L[j].head = NULL;
56         }
57         Distribute(a, i, n);                           //分配数组a中元素的第i项到链表L中
58         Collect(a);                                    //收集链表L中元素到数组a中
59     }
60 }
61 
62 int main(void) {
63     int i = 1, a[11] = { 0, 82, 31, 95, 63, 44, 32, 54, 12, 11, 0 };//a[0]哨兵位
64     RadixSort(a, 11);
65     while (i < 11) {
66         printf("%d ", a[i++]);
67     }
68 }
源代码

 

posted @ 2022-02-13 03:22  吕辉  阅读(268)  评论(0)    收藏  举报