基数排序

概念介绍:

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

排序原理:

        基数排序是非比较排序的一种,它分为两种:高位优先(MSD),低位优先(LSD)。其原理都是按位来进行哈希操作。本文描述的是低位优先操作,大致思想是:1.在一堆数组中首先找到最大值;2.确定最大值的位数;3.在进行入桶操作。入桶操作是将元素按照个位,十位,百位...从小到大的顺序依次入桶,个位入桶操作结束后进行排序,排序过程结束后,清空桶,再按元素十位由小到大的顺序入桶,在排序... ...以此类推,直到将最大元素的所有位数全部排好,基数排序过程结束。

排序过程:      

      例如:int arr[] = {10,3,26,9,8,30,15,18,211,256,341};存在这么一堆数组,首先知道数组中最大值是341,是三位数,申请10个桶大小的空间(0-9 一共10个数字),再按照个位,十位,百位一次入桶,排序。

按上图我们可以看出首先进行按个位进行排序,申请一块10大小的空间

 
Radix **pRadix = NULL;
pRadix=(Radix**)malloc(sizeof(Radix*)*10);

数组内元素按顺序入桶,将数组内元素按照个位大小排序,排序结束后再返回原数组,数组由:

                   int arr[] = {10,3,26,9,8,30,15,18,211,256,341};

变成:

                     int arr[] = {10,30,211,341,3,15,26,256,8,18,9};  

数组内元素按顺序入桶,再将数组中元素按十位大小进行排序,排序结束后再返回原数组:

数组由:

                    int arr[] = {10,30,211,341,3,15,26,256,8,18,9};

变成:

                    int arr[]={3,8,9,10,211,15,18,23,30,341,256};

数组内元素按顺序入桶,将数组中元素按百位大小进行排序,排序结束后再返回原数组:

数组由:

                     int arr[]={3,8,9,10,211,15,18,23,30,341,256};

变成:

                     int arr[]={3,8,9,10,15,18,23,30,211,256,341};

基数排序算法的实现:

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


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


void SORT(int arr[],int nlen,int nNum,Radix**pRadix)
{
	//算出最大值是几位数 个位是1 十位是2 百位是3  ...
	int nBase = 1;
	while(nNum>1)
	{
		nNum--;
		nBase *= 10;
	}
	//根据基数入桶 使用尾添加的方法
	int i ;
	int Indix;
	Radix *Temp = NULL;
	Radix *pNode = NULL;
	for(i = 0;i<nlen;i++)
	{
		Indix = arr[i]/nBase%10;	
		Temp = (Radix*)malloc(sizeof(Radix));
		Temp->nValue = arr[i];
		Temp->pNext = NULL;
		//添加
		if(pRadix[Indix] == NULL)//如果桶是空 直接插入
		{
			pRadix[Indix] = Temp;	
		}
		else//若不是空
		{
			pNode = pRadix[Indix];//遍历链表
			while(pNode ->pNext != NULL)
			{
				pNode = pNode->pNext;	
			}//在链表最后一个元素的后面插入新元素
			pNode->pNext = Temp;
		}
	}
	//数据放回原来的数组内
	int j = 0;
	for(i = 0;i<10;i++)
	{
		pNode = pRadix[i];
		while(pNode)
		{
			//小链表遍历 按顺序放入数组
			arr[j] = pNode->nValue;
			j++;
			pNode = pNode->pNext;
		}
	}
	//清除 小链表
	for( i = 0;i<10;i++)
	{
		pNode = pRadix[i];
		while(pNode)
		{
			Temp = pNode;
			pNode = pNode->pNext;
			free(Temp);
			Temp = NULL;	
		}
	}
	//切记要添加完以后要清空桶
	memset(pRadix,0,sizeof(Radix*)*10);
}
void RADIXSORT(int arr[],int len)
{
	int i;
	if(arr == NULL || len <=0 ) return ;
	//找到最大值
	int nMax = arr[0];//最大值
	for(i = 1;i< len; i++)
	{
		if(arr[i] > nMax)
		{nMax = arr[i];}
	}
	int base = 1;//位数
	while(nMax)
	{
		base++;
		nMax /= 10;
	}
	//如桶前,申请桶,并且当参数将桶传进排序函数
	//申请的空间内放的是结构体,并且最多就(0-9)10个元素
	Radix** pRadix = NULL;
	pRadix = (Radix**)malloc(sizeof(Radix*)*10);
	// 注意要清空桶,不然会对结果有影响
	memset(pRadix,0,sizeof(Radix*)*10);
	//处理各个位数 个位 十位 百位... ...
	for(int i = 1;i<base;i++)
	{
	//排序函数
		SORT(arr,len,i,pRadix);
	}
	//释放空间
	free(pRadix);
	pRadix = NULL;
}
void Print(int arr[],int nLength)
{
	int i;
	for(i = 0;i<nLength;i++)
	{
		printf("%d ",arr[i]);
	}
	printf("\n");
}


int main()
{
	int arr[] = {10,3,26,9,8,30,15,18,211,256,341};
	printf("原来的:");	
	Print(arr,sizeof(arr)/sizeof(arr[0]));
	RADIXSORT(arr,sizeof(arr)/sizeof(arr[0]));
	printf("排序后的:");
	Print(arr,sizeof(arr)/sizeof(arr[0]));


复杂度分析

        在基数排序中,因为没有比较操作,所以在复杂上,最好的情况与最坏的情况在时间上是一致的。因此无论是最好,最坏还是平均复杂度都是O(d * (n + r))。其中,d 为位数,r 为基数,n 为原数组个数。 空间复杂度O(n+r)。是稳定的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值