轉載http://blog.csdn.net/Shayabean_/article/details/44885917博客
先說說基數排序的思想:
基數排序是非比較型的排序算法,其原理是將整數按位數切割成不同的數字,然后按每個位數分別比較。
將所有待比較數值(正整數)統一為同樣的數位長度,數位較短的數前面補零。然后,從最低位開始,依次進行一次排序。在每一次排序中,按照當前位把數組元素放到對應
的桶當中,然后把桶0到桶9中的元素按先進先出的方式放回數組中。這樣從最低位排序一直到最高位排序完成以后, 數列就變成一個有序序列。
這個智能版本的基數排序RadixSort(L)較之前的RadixSort(L,max)不同的是不需要輸入待排序列最大數的位數。因為最大數位在程序中已經計算過了,但是因為需要計算最大數,所以需要對待排鏈表最開始循環一次,RadixSort(L,max)速度比RadixSort(L)稍快。
這篇博客包括4個文件,兩個頭文件RadixSort.h和fatal.h,一個庫函數RadixSort.c,和一個測試文件Test_Radix_Sort.c
頭文件fatal.h:
1 #include<stdio.h> 2 #include<stdlib.h> 3 #define Error(Str) FatalError(Str) 4 #define FatalError(Str) fprintf(stderr, "%s\n", Str), exit(1);
頭文件RadixSort.h:
1 typedef int ElementType; 2 #ifndef RADIX_SORT_H 3 #define RADIX_SORT_H 4 5 #include<stdbool.h> 6 #include<assert.h> 7 #define ListEmpty -2 8 9 struct Node; 10 typedef struct Node *PtrToNode; 11 typedef PtrToNode List; 12 typedef PtrToNode Position; 13 14 List MakeEmpty(List L); 15 bool IsEmpty(List L); 16 bool IsLast(Position P, List L); 17 Position Header(List L); 18 Position Advance(Position P); 19 ElementType Retrieve(Position P); 20 void DeleteList(List L); 21 void PrintList(const List L); 22 ElementType Max_LinkedList(List L);//獲取鏈表的最大值 23 int Get_Num_Length(ElementType Num);//獲取某個數的位數 24 void Insert(ElementType X, List L, Position P); 25 void MoveNode(List L1, List L2);//將表L2中的頭節點移動成為L1的尾節點 26 void RadixSort(List L);//最終基數排序函數,輸入鏈表L,將L排序得到新的排序鏈表L 27 #endif // !RADIX_SORT_H
其中RadixSort是最終排序函數,調用它即可排序。
庫函數RadixSort.c
1 #include "RadixSort.h" 2 #include<stdio.h> 3 #include<stdlib.h> 4 #include<malloc.h> 5 #include<math.h> 6 #include"fatal.h" 7 8 //定義結構體 9 struct Node 10 { 11 ElementType Element; 12 Position Next; 13 }; 14 15 //初始化鏈表 16 List MakeEmpty(List L) 17 { 18 if (L != NULL) 19 DeleteList(L);//如果鏈表非空,則刪除鏈表 20 L = malloc(sizeof(struct Node)); 21 if (L == NULL) 22 FatalError("Out of memory!"); 23 L->Next = NULL; 24 return L; 25 } 26 //判斷鏈表是否為空 27 bool IsEmpty(List L) 28 { 29 return L->Next == NULL; 30 } 31 32 //判斷當前指針P是否指向鏈表最后一個元素 33 bool IsLast(Position P, List L) 34 { 35 return P->Next == NULL; 36 } 37 38 //獲取鏈表頭 39 Position Header(List L) 40 { 41 return L; 42 } 43 44 //獲取位置P的下一個位置 45 Position Advance(Position P) 46 { 47 return P->Next; 48 } 49 50 //提取位置P處結構里面的值 51 ElementType Retrieve(Position P) 52 { 53 return P->Element; 54 } 55 56 //刪除鏈表 57 void DeleteList(List L) 58 { 59 Position P, Temp; 60 P = L->Next; 61 L->Next = NULL; 62 while (P != NULL) 63 { 64 Temp = P->Next; 65 free(P); 66 P = Temp; 67 } 68 } 69 70 //打印鏈表 71 void PrintList(const List L) 72 { 73 Position P = Header(L); 74 if (IsEmpty(L)) 75 printf("Empty list\n"); 76 else 77 { 78 do 79 { 80 P = Advance(P); 81 printf("%d ", Retrieve(P)); 82 } while (!IsLast(P, L)); 83 printf("\n"); 84 } 85 } 86 87 //獲取鏈表的最大值 88 ElementType Max_LinkedList(List L) 89 { 90 if (IsEmpty(L)) 91 Error("Empty List") 92 else 93 { 94 Position P = L->Next; 95 ElementType Max = P->Element; 96 while (P != NULL) 97 { 98 if (P->Element > Max) 99 Max = P->Element; 100 P = P->Next; 101 } 102 return Max; 103 } 104 } 105 106 //計算一個數有多少位 107 int Get_Num_Length(ElementType Num) 108 { 109 int Length=1; 110 while ((Num /= 10) != 0) Length++; 111 return Length; 112 } 113 114 //插入元素X到位置P后面 115 void Insert(ElementType X, List L, Position P) 116 { 117 Position TmpCell; 118 TmpCell = malloc(sizeof(struct Node)); 119 if (TmpCell == NULL) 120 FatalError("Out of Space!!!"); 121 TmpCell->Element = X; 122 TmpCell->Next = P->Next; 123 P->Next = TmpCell; 124 } 125 126 void MoveNode(List L1, List L2) 127 { 128 //將表L2中的頭節點移動成為L1的尾節點 129 Position Tmp1 = L1; 130 Position Tmp2; 131 if (IsEmpty(L2)) exit(ListEmpty); 132 while (!IsLast(Tmp1,L1)) 133 Tmp1 = Tmp1->Next;//使Tmp1指向L1表尾 134 Tmp2 = L2->Next; 135 L2->Next = Tmp2->Next; 136 Tmp1->Next = Tmp2; 137 Tmp2->Next = NULL; 138 } 139 140 //基數排序核心代碼 141 void RadixSort(List L) 142 { 143 int i,j,Max_Length, TmpSub;//Tmpsub存儲數的個位、十位、百位 144 ElementType FirstElement;//存儲鏈表的第一個元素 145 Max_Length = Get_Num_Length(Max_LinkedList(L)); 146 List Bucket[10];//開辟10個桶,依次為0~9 147 for (i = 0; i < 10; i++) Bucket[i] = MakeEmpty(NULL);//對10桶進行初始化,每一個數組都是一個鏈表 148 for (i = 0; i < Max_Length; i++)//開始提取每一位數的個位、十位、百位 149 { 150 while (!IsEmpty(L))//當L中的元素被取光了,則循環結束 151 { 152 FirstElement = L->Next->Element;//取出第一個節點的數據 153 TmpSub = (int)(FirstElement / pow(10, i)) % 10;//依次取出個十百位數字 154 MoveNode(Bucket[TmpSub], L);//將L中的節點依次移到對應的桶中 155 } 156 for (j = 0; j < 10; j++) //將桶中的數再次移動到L中 157 { 158 while (!IsEmpty(Bucket[j])) MoveNode(L, Bucket[j]); 159 } 160 } 161 for (i = 0; i < 10; i++) free(Bucket[i]) ;//釋放掉10個桶 162 }
測試函數Test_Radix_Sort.c
1 #include<stdio.h> 2 #include "RadixSort.h" 3 #include"fatal.h" 4 #include<time.h> 5 6 int main() 7 { 8 int amount;
10 List L; Position P; 11 L = MakeEmpty(NULL);//初始化鏈表 12 P = L; 13 if (L == NULL) Error("Out of Space!!!"); 14 printf("隨機生成多少位數:"); 15 scanf_s("%d", &amount); 16 srand((unsigned)time(NULL)); 17 for (int i = 0; i < amount; i++) 18 { 19 Insert(rand()%10000, L, P); 20 P = Advance(P); 21 } 22 printf("排序前的結果:"); 23 PrintList(L); 24 RadixSort(L);//調用排序函數排序 25 printf("基數排序后的結果:"); 26 PrintList(L); 27 }