数据结构(基数排序)

基数排序

基数排序(radix sort)属于"分配式排序"(distribution sort),又称"桶子法"(bucket sort)或bin sort,顾名思义,它是透过键值的部份资讯,将要排序的元素分配至某些"桶"中,藉以达到排序的作用,其中r为所采取的基数,而m为堆数,在某些时候,基数排序法的效率高于其它的稳定性排序法。

时间复杂度: O(m(n+r))

空间复杂度 : O(n+r)

m:最大数字的位数
n:待排序的数组的数字个数
r:队列申请空间的大小

稳定性: 稳定

基数排序相较于其他排序算法来说,基数排序的最大特点就是数字之间不用比较,在其他排序方法中,大部分都会有数字比较的过程
基数排序如图所示

在这里插入图片描述
从图中我们可以看出,基数排序是通过位来排序的,比如:个位、十位、百位。。。
每一个位上都有0–9的可能性,且在每一位存储的时候都需要一个先进先出的容器,所以,我们在排序的时候需要0–9个队列,队列的长度来自于待排序的数字个数,再通过位数从个位到最大位的比较来实现的排序
在这里举个例子:

例如:1、622、82、599、743、127进行排序

我们在排序之前先要知道待排数字的最大数字的位数是多少
以及创建10个队列(分别存储某位置上是0–9之间数字)

第一趟排序

先排个位上的数字,第一个数字的个位是1,则就将该数字存到存储1的队列中,在看下一个数字个位是2,则就将该数字存到存储2的队列中,在继续看下一个数字个位是2,则就将该数字存到存储2的队列中,在继续看下一个数字个位是9,则就将该数字存到存储9的队列中,在继续看下一个数字个位是3,则就将该数字存到存储3的队列中,在继续看下一个数字个位是7,则就将该数字存到存储7的队列中,至此,队列内容为
队列
【0】NULL
【1】 1
【2】 622 、82
【3】743
【4】NULL
【5】NULL
【6】NULL
【7】127
【8】NULL
【9】599
在将队列里的数字按顺序,按0–9队列输出,至此第一趟结束
输出结果:1、622、82、743、127、599
这组数字乍一看并没有非常有序,但我们可以发现,个位已经有了顺序

第二趟排序

排十位上的数字,第一个数字的十位是0,则就将该数字存到存储0的队列中,在看下一个数字十位是2,则就将该数字存到存储2的队列中,在继续看下一个数字十位是8,则就将该数字存到存储8的队列中,在继续看下一个数字十位是4,则就将该数字存到存储4的队列中,在继续看下一个数字十位是2,则就将该数字存到存储2的队列中,在继续看下一个数字十位是9,则就将该数字存到存储9的队列中,至此,队列内容为
【0】 1
【1】 NULL
【2】 622、127
【3】NULL
【4】743
【5】NULL
【6】NULL
【7】NULL
【8】82
【9】599
在将队列里的数字按顺序,按0–9队列输出,至此第二趟结束
输出结果:1、622、127、743、82、599
我们这次可以发现,十位已经有了顺序

第三趟排序

排百位上的数字,第一个数字的百位是0,则就将该数字存到存储0的队列中,在看下一个数字百位是6,则就将该数字存到存储6的队列中,在继续看下一个数字百位是1,则就将该数字存到存储1的队列中,在继续看下一个数字百位是7,则就将该数字存到存储7的队列中,在继续看下一个数字百位是0,则就将该数字存到存储0的队列中,在继续看下一个数字百位是5,则就将该数字存到存储5的队列中,至此,队列内容为
【0】 1、82
【1】 127
【2】 NULL
【3】 NULL
【4】 NULL
【5】 599
【6】 622
【7】 743
【8】 NULL
【9】 NULL
在将队列里的数字按顺序,按0–9队列输出,至此第三趟结束
输出结果:1、82、127、599、622、743
我们这次可以发现,百位即最大为已经有了顺序
至此,基数排序完成

参考代码

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define LENGTH 15        //待排序的数字个数

typedef struct Que          //定义队列
{
	int *data;
	int head;
	int tail;
}Que;

int Getmax(int arr[],int len)        //获得最大数字的位数
{
	int max = arr[0];
	for(int i=0;i<len;i++)
	{
		if(max<arr[i])
		{
			max = arr[i];
		}
	}

	int tmp = 0;
	while(max)
	{
		max/=10;
		tmp++;
	}

	return tmp;
}

int GetNum(int data,int i)        //获得数字的某一位的数字
{
	int num;
	while(i+1)
	{
		num = data%10;
		data/=10;
		i--;
	}

	return num;
}

void RadixSort(int arr[],int len)       // 基数排序
{
	int max = Getmax(arr,len);

	int i,j;
	Que que[10];                 //定义十个队列
	for(int i=0;i<10;i++)        //给每个队列开辟空间
	{
		que[i].data = (int *)malloc(sizeof(int)*len);
		que[i].head = 0;
		que[i].tail = 0;
	}

	for(i=0;i<max;i++)         //进行排序
	{
		for(j=0;j<len;j++)
		{
			int num = GetNum(arr[j],i);
			que[num].data[que[num].tail] = arr[j];
			que[num].tail++;
		}

		int count = 0;
		for(j=0;j<10;j++)
		{
			while(que[j].head!=que[j].tail)
			{
				arr[count] = que[j].data[que[j].head];
				que[j].head++;
				count++;
			}
			que[j].head = 0;
			que[j].tail = 0;
		}
	}

	for(int i=0;i<10;i++)    //释放开辟的空间
	{
		free(que[i].data);
	}
}

void ShowSort(int arr[],int len)     //打印
{
	for(int i=0;i<len;i++)
	{
		printf("%2d  ",arr[i]);
	}
	printf("\n");
}

int main()
{
	srand((unsigned int)time(NULL));

	int arr[LENGTH];

	for(int i=0;i<LENGTH;i++)
	{
		arr[i] = rand()%1000;   //获得随机数
	}
	ShowSort(arr,LENGTH);
	
	RadixSort(arr,LENGTH);

	ShowSort(arr,LENGTH);
	return 0;
}
  • 5
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
基数排序是一种非比较排序算法,它根据数据元素的每个位上的值进行排序。下面是基于顺序队列的基数排序的C语言实现: ```c #include <stdio.h> #include <stdlib.h> // 定义数据元素的数据结构 typedef struct { int key; } DataType; // 定义队列的数据结构 typedef struct { DataType *data; int front; int rear; } Queue; // 初始化队列 void initQueue(Queue *queue, int size) { queue->data = (DataType *)malloc(size * sizeof(DataType)); queue->front = queue->rear = 0; } // 入队操作 void enqueue(Queue *queue, DataType element) { queue->data[queue->rear++] = element; } // 出队操作 DataType dequeue(Queue *queue) { return queue->data[queue->front++]; } // 判断队列是否为空 int isEmpty(Queue *queue) { return queue->front == queue->rear; } // 获取关键字的某一位上的值 int getDigit(int number, int digit) { int i; for (i = 0; i < digit - 1; i++) { number /= 10; } return number % 10; } // 基数排序 void radixSort(DataType *data, int size, int digit) { int i, j, k; Queue *queues = (Queue *)malloc(10 * sizeof(Queue)); // 创建10个队列,用于存放每个位上的数据元素 // 初始化队列 for (i = 0; i < 10; i++) { initQueue(&queues[i], size); } // 根据每个位上的值将数据元素入队 for (i = 1; i <= digit; i++) { for (j = 0; j < size; j++) { int digitValue = getDigit(data[j].key, i); enqueue(&queues[digitValue], data[j]); } // 将队列中的数据元素按顺序出队,更新原数组 k = 0; for (j = 0; j < 10; j++) { while (!isEmpty(&queues[j])) { data[k++] = dequeue(&queues[j]); } } } // 释放队列的内存空间 for (i = 0; i < 10; i++) { free(queues[i].data); } free(queues); } int main() { int size = 10; int digit = 3; DataType data[] = {{710}, {342}, {45}, {686}, {6}, {841}, {429}, {134}, {68}, {264}}; radixSort(data, size, digit); // 输出排序结果 for (int i = 0; i < size; i++) { printf("%d ", data[i].key); } printf("\n"); return 0; } ``` 运行以上代码,输出结果为:6 45 68 134 264 342 429 686 710 841
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值