基数ソート
まず、使用する必要のある補助関数とキューの実装を記述します(キューが必要です)
#include<stdlib.h>
#include<string.h>
#define INITSIZE 10
#include<stdio.h>
typedef int ElemType;
typedef struct queue
{
ElemType *data;//存储元素的空间的首地址
int front;//队列头
int rear;//队列尾
int size;//标识当前空间的结束位置 扩容
}Queue;
void InitQueue(Queue *que)//初始化
{
if(que==NULL) exit(0);
que->data=(ElemType *)malloc(sizeof(ElemType)*INITSIZE);
if(que->data==NULL) exit(0);
que->front=que->rear=0;
que->size=INITSIZE;
}
static bool AppendSpace(Queue *que)//扩容
{
ElemType *new_space=(ElemType *)malloc(sizeof(ElemType)*que->size*2);
if(new_space==NULL) return false;
int index=0;
while(que->front!=que->rear)
{
new_space[index++]=que->data[que->front];
que->front=(que->front+1)%que->size;
}
que->front=0;
que->rear=que->size-1;
que->size *=2;
free(que->data);
que->data=new_space;
return true;
}
bool IsFull(Queue *que)//判满
{
if(que==NULL) exit(0);
return (que->rear+1)%que->size==que->front;//类似于处理环形
}
bool IsEmpty(Queue *que)//判空
{
if(que==NULL) exit(0);
return que->front==que->rear;
}
bool Push(Queue *que,ElemType val)//入队(从尾入)
{
if(que==NULL) exit(0);
if(IsFull(que))
{
if(!AppendSpace(que))
{
return false;
}
}
que->data[que->rear]=val;
que->rear=(que->rear+1)%que->size;
return true;
}
bool Top(Queue *que,ElemType *reval)//获取队列头的值
{
if(que==NULL) exit(0);
if(IsEmpty(que)) return false;
*reval=que->data[que->front];
return true;
}
bool Pop(Queue *que)//出队(从头出)
{
if(que==NULL) exit(0);
if(IsEmpty(que)) return false;
que->front=(que->front+1)%que->size;
return true;
}
void DestroyQueue(Queue *que)//销毁
{
if(que==NULL) exit(0);
free(que->data);
que->data=NULL;
que->front=que->rear=que->size=0;
}
/*辅助函数:
1.打印数据
2.判断整个数据序列是否已经有序
3.交互两个数据swap方法
*/
void Show(int *arr,int len)//打印数据
{
for(int i=0;i<len;++i)
{
printf("%d ",arr[i]);
}
printf("\n");
}
bool IsSort(int *arr,int len)//判断整个数据序列是否已经有序
{
for(int i=0;i<len-1;++i)
{
if(arr[i]>arr[i+1])
{
return false;
}
}
return true;
}
void SwapValue(int *a,int *b)//交互两个数据swap方法
{
int tmp=*a;
*a=*b;
*b=tmp;
}
基数ソートとは
カーディナリティソートは、複数のキーワードのソートアルゴリズムです。
デジタルシミュレーションには、複数のキーワードがあります。1つの場所、10の場所、100の場所、1000の場所...
特定の場所の値で並べ替え:この場所の数に応じて値の範囲(0 -9)対応する数のキューを申請する
ソートするシーケンス全体をトラバースし、このビットの値に従って各データを対応する添え字キューに格納し
、キュー内の値を順番にポップします
次の図は例です。
最初に1の場所から、次に10の場所からキューをたどり、
次にカーディナルソートアルゴリズムを実装します。
int GetMaxDigits(int *arr,int len)//获取序列中最大值的位数
{
int max_value=arr[0];
for(int i=0;i<len;++i)
{
if(max_value<arr[i])
{
max_value=arr[i];
}
}
int digits=0;
while(max_value)
{
digits++;
max_value/=10;
}
return digits;
}
int GetDigitsValue(int value,int digits)
{
while(digits)
{
value/=10;
digits--;
}
return value%10;
}
void RadixSort(int *arr,int len)
{
//最长的位数
int max_digits=GetMaxDigits(arr,len);
Queue que[10];
for(int i=0;i<10;++i)
{
InitQueue(&que[i]);
}
for(int i=0;i<max_digits;++i)
{
for(int j=0;j<len;++j)
{
int digits_value=GetDigitsValue(arr[j],i);
Push(&que[digits_value],arr[j]);
}
int index=0;
for(int k=0;k<10;++k)
{
while(!IsEmpty(&que[k]))
{
Top(&que[k],&arr[index]);
index++;
Pop(&que[k]);
}
}
}
for(int i=0;i<10;++i)
{
DestroyQueue(&que[i]);
}
}
最後にメイン機能を完了します
int main()
{
int arr[]={
7,87,29,75,41,50,62,92,69,22,76,77,35};
Show(arr,sizeof(arr)/sizeof(arr[0]));
RadixSort(arr,sizeof(arr)/sizeof(arr[0]));
Show(arr,sizeof(arr)/sizeof(arr[0]));
return 0;
}
実行結果は次のとおりです。
基数ソートアルゴリズムの分析:
時間計算量O(d n)d:キーワードの数
空間計算量O(w n)w:数値範囲の数
安定性:安定