基数排序-------C语言实现

6 篇文章 0 订阅
5 篇文章 0 订阅

其他排序

堆排序
归并排序
插入排序和希尔排序
快速排序
冒泡排序和选择排序

基数排序

前备知识

注:我们知道,对于一个数如果我们想获取它得个位,只需对10取余,想获取十位的数,可以除10然后再对10取余,获取百位除100然后再对10取余,获取千位除1000再对10取余...

核心思想:根据数字的位(个位、十位、百位…)来进行的排序算法,有点类似于哈希表,基数排序首先应该找到数字中最大的数,然后算出这个数有几位,其次依次根据个位、十位、百位、千位、…、最大位来进行排序
实现过程
在这里插入图片描述如上图所示,对上述数据进行由小到大排序:
1.首先,找出所有数中最大的数,计算它的位数
从上图我们可以看出最大值为1356,即此时位数int nBit = 4;

2.然后,我们需要一次按照个位、十位、百位、千位(因为最大位数只有4)进行排序
在进行排序之前,我们需要有一个空间能存储排序的数据,由于我们是按位进行排序,所以我们需要包括所有可能取得的值0-9,然后获取对应位数的值后放入相应位置。
先按照个位排序,排序结果如下:
在这里插入图片描述经过个位排序之后,结果如上图所示,此时我们已经将数组按照个位拍好序,之后我们将拍好序的值重新放回原数组,然后释放原有空间,接着再按照十位排序,返回原数组之后结果如下:
在这里插入图片描述接着,按照十位排序,结果如下:
在这里插入图片描述放回原数组,结果如下(这个过程和上面类似,不再细说):
在这里插入图片描述
按照百位排序,如下:

在这里插入图片描述放回原数组,结果如下:
在这里插入图片描述按照千位排序,如下
在这里插入图片描述如上图所示,将数据放回原数组,结束(因为千位为最大位数,这也是我们为什么刚开始要找打最大的数字)

在这里插入图片描述总结,从上述的实现过程我们可以看出,每次按照位数进行排序时,在对应的每个位置都是一个链表,而且总共是有十个链表组成在一起,因此我们排序时所需要申请的空间为一个指针数组来保存这些数据。
代码实现

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

typedef struct Radix
{
	int nValue;
	struct Radix *pNext;
}Radix;

void RadixSort(int arr[],int nLen)
{
	if(arr == NULL || nLen <= 0)
		return;

	int nBit = 1;
	int nMax = arr[0];

	//找出最大数
	for(int i = 1;i < nLen;i++)
	{
		if(nMax < arr[i])
		{
			nMax = arr[i];
		}
	}
	//计算位数
	while(nMax /= 10)
	{
		nBit++;
	}
	int n = 1;
	//定义一个指针数组来存数据,并开辟10个Radix空间
	Radix **pRadix = (Radix **)malloc(sizeof(Radix *)*10);
	Radix *pTemp = NULL;
	Radix *pMark = NULL;
	int nCount;
	Radix *pDel = NULL;
	//初始化为空
	for(int i = 0;i < 10;i++)
	{
		pRadix[i] = NULL;
	}
	for(int i = 0;i < nBit;i++)
	{
		//按位排序
		for(int j = 0;j < nLen;j++)
		{
			pTemp = (Radix*)malloc(sizeof(Radix));
			pTemp->nValue = arr[j];
			pTemp->pNext = NULL;

			if(pRadix[arr[j]/n%10] == NULL)
			{
				pRadix[arr[j]/n%10] = pTemp;
			}
			else
			{
				pMark = pRadix[arr[j]/n%10];
				while(pMark->pNext != NULL)
				{
					pMark = pMark->pNext;
				}
				pMark->pNext = pTemp;
			}
		}
		nCount = 0;
		//将数据重新放回原数组
		for(int j = 0;j < 10;j++)
		{
			while(pRadix[j] != NULL)
			{
				arr[nCount++] = pRadix[j]->nValue;
				pDel = pRadix[j];
				pRadix[j] = pRadix[j]->pNext;
				free(pDel);
				pDel = NULL;
			}
		}
		n *= 10;
	}
}

void Print(int arr[],int nLen)
{
	if(nLen <= 0) return;

	for(int i = 0;i < nLen;i++)
	{
		printf("%d\t",arr[i]);
	}
	printf("\n");
}
int main()
{


	//int arr[] = {1,78,2,54,56,2,78,12,4555,8};
	int arr[] = {8,13,231,156,29,1356,50,200,6};
	RadixSort(arr,sizeof(arr)/sizeof(arr[0]));
	
	Print(arr,sizeof(arr)/sizeof(arr[0]));
	return 0;
}

平均时间复杂度:O( n*k)k:为最大的位数

空间复杂度:O(m+n)空间复杂度我们也可以看出来,主要就是取决于链表的数量以及序列元素的数量,所以空间复杂度为O(n+k)

稳定性:稳定

适用场合:数组量大且较无序

排序名称最好时间复杂度平均时间复杂度最坏时间复杂度空间复杂度稳定性适用场合
BubbleSortO(n)O(n2)O(n2)O(1)稳定
SelectSortO(n2)O(n2)O(n2)O(1)不稳定
InsertSortO(n)O(n2)O(n2)O(1)稳定
ShellSortO(n)O(n1.3)O(n2)O((log2n)不稳定
QuickSortO(nlogn)O(nlogn)O(n2)O(logn)~O(n)不稳定
MergeSortO(nlogn)O(nlogn)O(nlogn)O(n)稳定
HeapSortO(nlogn)O(nlogn)O(nlogn)O(1)稳定
RadixSort稳定
  • 1
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Bug.Remove()

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值