排序算法之计数&基数排序

计数排序>

   给定一组待排序的数据,找到这组数据中的最大值,然后开辟一个最大值加1的数组,用memset初始化为全0,然后再次遍历原数组,使得这个新开辟的数组中存储的是该数字出现的次数,此时只需要将新数组的内容写入原数组即可.

     

      我们发现计数排序其实利用的是哈希的思想来统计次数,是一种非比较的排序,它的时间复杂度为O(N+范围),因为计数排序是一种以空间换取时间的排序算法.

 计数排序的优化>

      如果给定这样一组数据"1001,1002,1003",那仫按照之前的思路我们就需要开辟1004块空间,很明显存在极大的空间浪费.要优化它只能从减小开辟空间的个数入手了.

      其实我们可以找出一组数据中的最大值和最小值,此时开辟的辅助数组只需要开辟max-min+1块即可,在统计次数要重新映射进辅助数组.

     

void CountSort(int *a,int size)
{
	assert(a);
	int max=a[0];
	int min=a[0];
	//找到最大最小值
	for (int i=0;i<size;++i)
	{
		if(a[i] > max)
			max=a[i];
		if(a[i] < min)
			min=a[i];
	}
	int range=max-min+1;
	int *tmp=new int[range];
	memset(tmp,0,sizeof(int)*range);
	//统计数字出现的次数
	for (int i=0;i<size;++i)
	{
		tmp[a[i]-min]++;
	}
	//还原初始数组
	int index=0;
	for (int i=0;i<range;++i)
	{
		while (tmp[i]--)
		{
			a[index++]=i+min;
		}
	}
	delete[] tmp;
}


 

 

基数排序>

     基数排序是另一种非比较的排序,类似哈希桶.它的主要思想是:从低位开始将一组序列按照这一位值的大小放至相应的编号0~9中。等到低位排完之后再按照类似的想法继续排次低位,直至排到最高位为止,此时这个序列就是有序的序列.

    

int GetMaxDigit(int *a,int size)
{
	//标识数量级
	int base=10;
	//统计最大数据的位数
	int digit=1;
	for (int i=0;i<size;++i)
	{
		while (a[i] >= base)
		{
			++digit;
			base *= 10;
		}
	}
	return digit;
}
void LSDSort(int *a,int size)
{
	assert(a);
	int base=1;
	int digit=GetMaxDigit(a,size);
	int *count=new int[10];
	int *start=new int[10];
	int *tmp=new int[size];
	while(digit--)
	{
		//统计数字出现的次数
		memset(count,0,sizeof(int)*size);
		for (int i=0;i<size;++i)
		{
			count[(a[i]/base)%10]++;
		}
		//求每组数据的起始位置
		start[0]=0;
		for (int i=1;i<10;++i)
		{
			start[i]=start[i-1]+count[i-1];
		}
		//将数据写入tmp中
		for (int i=0;i<size;++i)
		{
			int num=(a[i]/base)%10;
			tmp[start[num]]=a[i];
			start[num]++;
		}
		//将tmp中的内容写入a中
		for (int i=0;i<size;++i)
		{
			a[i]=tmp[i];
		}
		base *= 10;
	}
	delete[] tmp;
}


 

  

    在上述找最大位的方法先设置数量级base=10,digit统计位数=1,遍历数组,如果存在大于等于数量级的数就更新数量级统计位数加1.当然这个方法不太好理解,另一种求位数的方法是:先遍历一遍数组找到数组中的最大值,求出最大值的位数.

   基数排序的时间复杂度为O(N*digit),digit是这组待排序数据中的最大位,它的空间复杂度为O(N),基数排序是一种稳定的排序算法.

   在这里就分享结束啦~~~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值