排序算法----基數排序(RadixSort(L))單鏈表智能版本


轉載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 }

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM