基数排序

Posted on 2020-04-20 22:32  金色的省略号  阅读(194)  评论(0编辑  收藏  举报

  一、次位优先

 1 /* 基数排序 - 次位优先 */
 2  
 3 /* 假设元素最多有MaxDigit个关键字,基数全是同样的Radix */
 4 #define MaxDigit 4
 5 #define Radix 10
 6  
 7 /* 桶元素结点 */
 8 typedef struct Node *PtrToNode;
 9 struct Node {
10     int key;
11     PtrToNode next;
12 };
13  
14 /* 桶头结点 */
15 struct HeadNode {
16     PtrToNode head, tail;
17 };
18 typedef struct HeadNode Bucket[Radix];
19   
20 int GetDigit ( int X, int D )
21 { /* 默认次位D=1, 主位D<=MaxDigit */
22     int d, i;
23      
24     for (i=1; i<=D; i++) {
25         d = X % Radix;
26         X /= Radix;
27     }
28     return d;
29 }
30  
31 void LSDRadixSort( ElementType A[], int N )
32 { /* 基数排序 - 次位优先 */
33      int D, Di, i;
34      Bucket B;
35      PtrToNode tmp, p, List = NULL; 
36       
37      for (i=0; i<Radix; i++) /* 初始化每个桶为空链表 */
38          B[i].head = B[i].tail = NULL;
39      for (i=0; i<N; i++) { /* 将原始序列逆序存入初始链表List */
40          tmp = (PtrToNode)malloc(sizeof(struct Node));
41          tmp->key = A[i];
42          tmp->next = List;
43          List = tmp;
44      }
45      /* 下面开始排序 */ 
46      for (D=1; D<=MaxDigit; D++) { /* 对数据的每一位循环处理 */
47          /* 下面是分配的过程 */
48          p = List;
49          while (p) {
50              Di = GetDigit(p->key, D); /* 获得当前元素的当前位数字 */
51              /* 从List中摘除 */
52              tmp = p; p = p->next;
53              /* 插入B[Di]号桶尾 */
54              tmp->next = NULL;
55              if (B[Di].head == NULL)
56                  B[Di].head = B[Di].tail = tmp;
57              else {
58                  B[Di].tail->next = tmp;
59                  B[Di].tail = tmp;
60              }
61          }
62          /* 下面是收集的过程 */
63          List = NULL; 
64          for (Di=Radix-1; Di>=0; Di--) { /* 将每个桶的元素顺序收集入List */
65              if (B[Di].head) { /* 如果桶不为空 */
66                  /* 整桶插入List表头 */
67                  B[Di].tail->next = List;
68                  List = B[Di].head;
69                  B[Di].head = B[Di].tail = NULL; /* 清空桶 */
70              }
71          }
72      }
73      /* 将List倒入A[]并释放空间 */
74      for (i=0; i<N; i++) {
75         tmp = List;
76         List = List->next;
77         A[i] = tmp->key;
78         free(tmp);
79      } 
80 }

  二、主位优先

/* 基数排序 - 主位优先 */
 
/* 假设元素最多有MaxDigit个关键字,基数全是同样的Radix */
 
#define MaxDigit 4
#define Radix 10
 
/* 桶元素结点 */
typedef struct Node *PtrToNode;
struct Node{
    int key;
    PtrToNode next;
};
 
/* 桶头结点 */
struct HeadNode {
    PtrToNode head, tail;
};
typedef struct HeadNode Bucket[Radix];
  
int GetDigit ( int X, int D )
{ /* 默认次位D=1, 主位D<=MaxDigit */
    int d, i;
     
    for (i=1; i<=D; i++) {
        d = X%Radix;
        X /= Radix;
    }
    return d;
}
 
void MSD( ElementType A[], int L, int R, int D )
{ /* 核心递归函数: 对A[L]...A[R]的第D位数进行排序 */
     int Di, i, j;
     Bucket B;
     PtrToNode tmp, p, List = NULL; 
     if (D==0) return; /* 递归终止条件 */
      
     for (i=0; i<Radix; i++) /* 初始化每个桶为空链表 */
         B[i].head = B[i].tail = NULL;
     for (i=L; i<=R; i++) { /* 将原始序列逆序存入初始链表List */
         tmp = (PtrToNode)malloc(sizeof(struct Node));
         tmp->key = A[i];
         tmp->next = List;
         List = tmp;
     }
     /* 下面是分配的过程 */
     p = List;
     while (p) {
         Di = GetDigit(p->key, D); /* 获得当前元素的当前位数字 */
         /* 从List中摘除 */
         tmp = p; p = p->next;
         /* 插入B[Di]号桶 */
         if (B[Di].head == NULL) B[Di].tail = tmp;
         tmp->next = B[Di].head;
         B[Di].head = tmp;
     }
     /* 下面是收集的过程 */
     i = j = L; /* i, j记录当前要处理的A[]的左右端下标 */
     for (Di=0; Di<Radix; Di++) { /* 对于每个桶 */
         if (B[Di].head) { /* 将非空的桶整桶倒入A[], 递归排序 */
             p = B[Di].head;
             while (p) {
                 tmp = p;
                 p = p->next;
                 A[j++] = tmp->key;
                 free(tmp);
             }
             /* 递归对该桶数据排序, 位数减1 */
             MSD(A, i, j-1, D-1);
             i = j; /* 为下一个桶对应的A[]左端 */
         } 
     } 
}
 
void MSDRadixSort( ElementType A[], int N )
{ /* 统一接口 */
    MSD(A, 0, N-1, MaxDigit); 
}