基數排序 順序實現與鏈式實現


最近數據結構剛剛講完了基數排序,以下我的一些見解:

大多數的排序都是通過比較數據大小的方法對待排數據序列進行排序整理過程。

而基數排序卻很另類,那么,基數排序是采用怎樣的策略進行排序的呢?

簡要概括一下:基數排序是通過“分配”和“收集”兩個過程來實現排序的。

而這個思想該如何理解呢?請看以下例子:

(1)有以下待排序列

309 385 867 183 341 605 385

(2)第一次分配和收集:

首先按照各個數據的個位數字(即按照9,5,7,3,1,5,5)分配到0-9的10個區間內

結果如下:

分配結束后。接下來將所有空間中的數據按照序號由小到大依次重新收集起來,得到如下仍然無序的數據序列:

(3)第二次分配和收集:

 這次按照十位數字進行分配,步驟同上

結果如下:

分配結束后。接下來將所有空間中的數據按照序號由小到大依次再次收集起來,得到如下仍然無序的數據序列:

 

(4)第三次分配和收集:

 這次按照百位數字進行分配,步驟同上

結果如下:

分配結束后。接下來將所有空間中的數據按照序號由小到大依次再次收集起來;

哎?!停一下!奇怪,數據竟然有序了!

當然,數據分別按照個,十,百位依次排序后自然是有序的,至於為什么,我相信細心的讀者已經想明白了。

 

下面介紹一下對上面所說的基數排序算法做一些補充:

(1)如果數據大小更大,則需按照上面的思路繼續排序(比如排序到千位,萬位.....),排序的次數就是待排數據中最大數字的位數;

(2)上面的分析是說的數字的排序,如果要對等長的字符串集合排序,則各個空間的關鍵字由0-9變為‘a’-‘z’;

(3)基數排序是穩定的,而且看起來似乎在時間代價上很好,但實際並非如此,它在記錄數較關鍵字大得多的情況下比較有效,還有一個缺點是:它對一些數據類型來說是難於實現的,如對實型或不等長的字串。

下面再思考一個問題:既然我們可以從最低位到最高位進行如此的分配收集,那么是否可以由最高位到最低位依次操作呢? 答案是完全可以的。

基於兩種不同的排序順序,我們將基數排序分為LSD(Least significant digital)或MSD(Most significant digital),

LSD的排序方式由數值的最右邊(低位)開始,而MSD則相反,由數值的最左邊(高位)開始。

注意一點:LSD的基數排序適用於位數少的數列,如果位數多的話,使用MSD的效率會比較好。

下面給出算法實現代碼:

鏈式實現:

 1 #include <iostream>
 2 
 3 using namespace std;
 4 const int maxn=100000+10;
 5 const int Radix=20;
 6 typedef struct
 7 {
 8     int next;
 9     int key;
10 }SLNode;
11 typedef struct
12 {
13     SLNode r[maxn];
14     int length;
15 }SLList;
16 typedef int ArrType[Radix];
17 ArrType f,e;
18 int Ord(int k,int j)
19 {
20     for(int i=1;i<j;i++)
21         k/=10;
22     k%=10;
23     return k+10;
24 }
25 void Print_L(SLList L)
26 {
27     int mrk=0;
28     for(int p=L.r[0].next;p;p=L.r[p].next)
29     {
30         if(mrk)
31             printf(" ");
32         printf("%d",L.r[p].key);
33         mrk=1;
34     }
35     printf("\n");
36 }
37 void Distribute(SLList &L,int i,ArrType &f,ArrType &e)
38 {
39     //printf("i=%d\n",i);
40     for(int i=0;i<Radix;i++)
41         f[i]=0;
42     //for(int p=L.r[0].next;p!=0;p=L.r[p].next)
43     for(int p=L.r[0].next;p;p=L.r[p].next)
44     {
45         int k=Ord(L.r[p].key,i);
46         //printf("%d\n",k);
47         if(f[k]==0)
48         {
49             f[k]=e[k]=p;
50         }
51         else
52         {
53             L.r[e[k]].next=p;
54             e[k]=p;
55         }
56     }
57 }
58 void Collect(SLList &L,int i,ArrType &f,ArrType &e)
59 {
60     int j=0;
61     while(f[j]==0)
62         j++;
63     L.r[0].next=f[j];
64     int tail=e[j];
65     while(j<Radix)
66     {
67         j++;
68         while(j<Radix&&f[j]==0)
69             j++;
70         L.r[tail].next=f[j];
71         tail=e[j];
72     }
73 }
74 void RadixSort(SLList &L)
75 {
76     for(int i=1;i<=6;i++)//待排數據中最大值的位數,可根據實際需要變化
77     {
78         Distribute(L,i,f,e);
79         Collect(L,i,f,e);
80     }
81 }
82 
83 int main()
84 {
85     int n;
86     scanf("%d",&n);
87     SLList L;
88     L.length=n;
89     L.r[0].next=1;
90     for(int i=1;i<=n;i++)
91     {
92         scanf("%d",&L.r[i].key);
93         L.r[i].next=i+1;
94     }
95     L.r[n].next=0;
96     RadixSort(L);
97     Print_L(L);
98     return 0;
99 }
View Code

鏈式時間復雜度: 

順序實現:

  1 //庫函數頭文件包含
  2 #include<stdio.h>
  3 #include<malloc.h>
  4 #include<stdlib.h>
  5 
  6 
  7 //函數狀態碼定義
  8 #define TRUE        1
  9 #define FALSE       0
 10 #define OK          1
 11 #define ERROR       0
 12 #define INFEASIBLE -1
 13 #define OVERFLOW   -2
 14 #define Radix      10
 15 #define maxn       100010
 16 typedef int  Status;
 17 typedef int QElemType;
 18 
 19 typedef struct QNode
 20 {
 21     QElemType data;
 22     struct QNode *next;
 23 }QNode, *QueuePtr;
 24 
 25 typedef struct
 26 {
 27     QueuePtr front;
 28     QueuePtr rear;
 29 }LinkQueue;
 30 
 31 Status InitQueue(LinkQueue &Q)
 32 {
 33     Q.front=Q.rear=(QueuePtr)malloc(sizeof(QNode));
 34     if(!Q.front)
 35         exit(OVERFLOW);
 36     Q.front->next=NULL;
 37     return OK;
 38 }
 39 Status DestroyQueue(LinkQueue &Q)
 40 {
 41     while(Q.front)
 42     {
 43         Q.rear=Q.front->next;
 44         free(Q.front);
 45         Q.front=Q.rear;
 46     }
 47     return OK;
 48 }
 49 Status EnQueue(LinkQueue &Q,QElemType e)
 50 {
 51     QueuePtr p=(QueuePtr)malloc(sizeof(QNode));
 52     if(!p)
 53         exit(OVERFLOW);
 54     p->data=e;
 55     p->next=NULL;
 56     Q.rear->next=p;
 57     Q.rear=p;
 58     return OK;
 59 }
 60 Status DeQueue(LinkQueue &Q,QElemType &e)
 61 {
 62     if(Q.front==Q.rear)
 63         return ERROR;
 64     QueuePtr p=Q.front->next;
 65     e=p->data;
 66     Q.front->next=p->next;
 67     if(Q.rear==p)
 68         Q.rear=Q.front;
 69     free(p);
 70     return OK;
 71 }
 72 Status QueueEmpty(LinkQueue Q)
 73 {
 74     if(Q.front==Q.rear)
 75         return TRUE;
 76     else
 77         return FALSE;
 78 }
 79 typedef struct
 80 {
 81     int key;
 82 }SLNode;
 83 typedef struct
 84 {
 85     SLNode r[maxn];
 86     int length;
 87 }SLList;
 88 LinkQueue B[Radix];
 89 int Ord(int k,int j)
 90 {
 91     for(int i=1;i<j;i++)
 92         k/=10;
 93     k%=10;
 94     return k;
 95 }
 96 void Print_L(SLList L)
 97 {
 98     int mrk=0;
 99     for(int p=1;p<=L.length;p++)
100     {
101         if(mrk)
102             printf(" ");
103         printf("%d",L.r[p].key);
104         mrk=1;
105     }
106     printf("\n");
107 }
108 void Distribute(SLList &L,int i)
109 {
110     for(int j=1;j<=L.length;j++)
111     {
112         int k=Ord(L.r[j].key,i);
113         EnQueue(B[k],L.r[j].key);
114     }
115 }
116 void Collect(SLList &L)
117 {
118     int i=1;
119     for(int j=1;j<Radix;j++)
120     {
121         while(!QueueEmpty(B[j]))
122             DeQueue(B[j],L.r[i++].key);
123     }
124 }
125 void RadixSort(SLList &L)
126 {
127     for(int i=0;i<Radix;i++)
128     {
129         InitQueue(B[i]);
130     }
131     for(int i=1;i<=6;i++)   //最高位數為6,可根據實際變化
132     {
133         Distribute(L,i);
134         Collect(L);
135     }
136 }
137 int main()
138 {
139     int n;
140     scanf("%d",&n);
141     SLList L;
142     L.length=n;
143     for(int i=1;i<=n;i++)
144     {
145         scanf("%d",&L.r[i].key);
146     }
147     RadixSort(L);
148     Print_L(L);
149     return 0;
150 }
View Code

順序時間復雜度:

 

(由於我們所用教材為嚴蔚敏老師編寫的,所以代碼風格接近,也易於讀懂。

 

堅持不懈地努力才能成為大神!


免責聲明!

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



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