114-基数ソートアルゴリズムの実装と分析

基数ソート

まず、使用する必要のある補助関数とキューの実装を記述します(キューが必要です)

#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:数値範囲の数
安定性:安定

おすすめ

転載: blog.csdn.net/LINZEYU666/article/details/111601264
おすすめ