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

其他排序

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

基数排序

前备知识

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

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

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

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

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

#include 
#include 

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)

稳定性:稳定

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

排序名称 最好时间复杂度 平均时间复杂度 最坏时间复杂度 空间复杂度 稳定性 适用场合
BubbleSort O(n) O(n2) O(n2) O(1) 稳定
SelectSort O(n2) O(n2) O(n2) O(1) 不稳定
InsertSort O(n) O(n2) O(n2) O(1) 稳定
ShellSort O(n) O(n1.3) O(n2) O((log2n) 不稳定
QuickSort O(nlogn) O(nlogn) O(n2) O(logn)~O(n) 不稳定
MergeSort O(nlogn) O(nlogn) O(nlogn) O(n) 稳定
HeapSort O(nlogn) O(nlogn) O(nlogn) O(1) 稳定
RadixSort 稳定

你可能感兴趣的:(C/C++,指针,排序,排序算法)