C語言基數排序——順序佇列實現
阿新 • • 發佈:2019-01-06
基數排序
基本要求:
從鍵盤上輸入n個程度為m的整數,要求輸出這些整數的升序排列。
具體要求:
- 使用的資料結構是佇列,利用順序佇列來實現
- 有良好的人機互動
- 能夠輸出每一趟分配和收集的情況
基本概念:
基數排序屬於分配式排序、又稱桶子法。通過鍵值的查詢,將要排序的元素分配至某些“桶”中,以達到排序的作用。
具體思想:
以整形為例,將整形10進位制按每位拆分,然後從低位到高位依次比較
主要分為兩個過程:
分配,先從個位開始,根據位值(0-9)分別放到0~9號桶中
收集,再將放置在0~9號桶中的資料按順序放到陣列中
重複分配收集過程,從個位到最高位為重複次數
程式碼實現:
#include<stdio.h> #include<stdlib.h> #include<string.h> #define Radix 10 //代表Radix(10)個佇列 typedef int QElemType; typedef struct { QElemType *base; //初始化的動態分配空間,儲存資料 int front; //頭指標,指向佇列頭元素,用來移動 int rear; //尾指標,指向佇列尾元素的下一位置,確定長度 } SqQueue; //distribute進行第n趟分配 //原始資料儲存在Q.base陣列中 //ArrType是SqQueue型別的陣列, void distribute(SqQueue &Q,int n,SqQueue ArrType[]) { //quot-商 //rem-儲存每個資料的第n位(即第1位、第2位...第n位)的值 int i,c,temp,quot,rem; //for置空Radix(10)個佇列 for(i=0; i<Radix; i++) ArrType[i].front=0; //for處理每個資料的第n位 for(i=0; i<Q.rear; i++) { //將第i個數據暫存到quot quot=Q.base[i]; c=0; //while計算第i個數據的第n位的值並儲存到rem while(c<n) { c++; rem=quot%Radix; quot/=Radix; } //將第n位為rem的資料複製到第rem個佇列 //即根據資料的第n位的數字rem,將資料分配到第rem個佇列的尾部 ArrType[rem].base[ArrType[rem].front++]=Q.base[i]; } printf("第%d趟分配之後的情況是:\n",n); for(i=0; i<Radix; i++) { temp=ArrType[i].front; //if如果第i個佇列不為空 if(temp>0) { printf("佇列[%d]隊頭指標front->",i); for(c=0; c<temp-1; c++) printf("%d-",ArrType[i].base[c]); printf("%d<-佇列[%d]隊尾指標rear\n",ArrType[i].base[temp-1],i); } } } //collect進行第n趟收集 //ArrType儲存了第n-1趟分配的結果 void collect(SqQueue &Q,int n,SqQueue ArrType[]) { //collected記錄已收集資料的數量 int i,collected=0; //for將陣列ArrType中的資料收集到int型陣列Q.base中 for(i=0; i<Radix; i++) { //if如果第i個佇列不空,就收集它的資料 if(ArrType[i].front!=0) { //進行收集(簡單地複製到Q.base陣列就行了) memcpy(Q.base+collected,ArrType[i].base,ArrType[i].front*sizeof(int)); collected+=ArrType[i].front; } } printf("第%d趟收集之後的情況是:\n",n); for(i=0; i<=Q.front-1; i++) { printf("%d ",Q.base[i]); } printf("\n\n"); } //計算每個佇列的初始長度(為資料量的1/Radix) void Ord(SqQueue &Q,SqQueue ArrType[],int M) { int i; int temp=M; for(i=0; i<Radix; i++) { //為第i個佇列分配空間 ArrType[i].base=(int*)calloc(temp,sizeof(int)); ArrType[i].rear=temp; } } //for進行M(M為輸入的每個資料的長度)趟分配和收集 void RadixSort(SqQueue Q,int M,SqQueue ArrType[]) { for(int i=1; i<=M; i++) { distribute(Q,i,ArrType); collect(Q,i,ArrType); } } int main() { int i,M; SqQueue Q,ArrType[Radix]; printf("請輸入每個資料的長度:"); scanf("%d",&M); printf("請輸入共有多少個數據:"); scanf("%d",&Q.rear); Q.base=(int*)calloc(Q.rear,sizeof(int)); Q.front=0; printf("請輸入%d個長度為%d的資料:\n",Q.rear,M); for(i=0; i<Q.rear; i++) scanf("%d",&Q.base[Q.front++]); printf("\n"); Ord(Q,ArrType,M); RadixSort(Q,M,ArrType); //以下的free釋放動態分配的記憶體 free(Q.base); for(i=0; i<Radix; i++) free(ArrType[i].base); system("PAUSE"); return 0; }
資料處理:
尾言:
基數排序法是屬於穩定性的排序,其時間複雜度為O (nlog(r)m),其中r為所採取的基數,而m為堆數
在某些時候,基數排序法的效率高於其它的穩定性排序法。