二维数组实现基数排序(c语言)

1.原理,基数排序是基于输入序列元素的键值来进行排序的,也是利用桶排序的思想,在确定的有限个桶内,按照基数的键值划分到不同的桶中,在该种排序中,输入序列的键值是有多个的,根据条件的不同,键值也不同。而且每次比较的键值的优先级也不一样。假设输入序列都是正整形元素的话,我们可以以个位数,十位数,百位数等分别进行三次划分元素进桶操作。而且当完成一轮的进桶操作之后,要将桶中元素依次放出并覆盖原输入序列。
2.算法分析,要有确定的有限个桶来存储对应元素。这里我们采取二维数组keys_table[10][100]来充当桶,因为数字为0到9,所以二维数组的0到9行存储对应位数上的元素,即是二维数组的0~9行也是键值为0到9的9个桶。那么怎么解决桶中元素的位置存储问题呢。
可以有两种方式,第一种可以在每个桶的第一个位置,即是keys_table[i][0]来存储该桶中的元素,每添加一个元素就自加1,第二种则是在额外定义一个辅助的一维数组a[10],该数组的0到9个位分别存储对应的键值的桶中的元素。这样九个桶的就已经布置完成了。
那接下来便是将输入序列中的元素按各个位上的键值丢到桶里面了。因为每次的比较是按个,十,百,千,……这样来比较的。所以决定比较的轮数是具有最多位数的数,能够代表这个数的可以是输入序列中的最大值。所以我们接下来要先找出输入序列中的最大数,然后在算出它是几位数。算几位数很简单,只需要将其于1,10,100,1000……等分别比较,大于等于都往后比较,并且自身位数+1,不满足则跳出即可。这样我们就得到了需要比较的轮数,因为每轮比较的元素都是一个输入序列,所以每轮循环里面还有一个循环来根据输入序列中的键值分到对应的桶中。接下来便是提取元素的个位数,百位数,千位数等。这里有一个提取各位数上的代码。
提取一个数上的各位数
个位:int =sum%10
十位:int =sum/10%10
百位:int =sum/100%10
千位:int =sum/1000%10
万位:int =sum/10000%10
这样很明显是10的次方变化。我们根据比较的轮数来改变10的次方值既可以了,或者完成依次比较就乘以10,这样更加简便。
这样我们根据提取出来的元素放入了对应的桶中。
接下来便是将按照键值大小,来将桶中的元素依次取出覆盖到原输入序列,这样才能保持该次排序的影响,将桶中的元素取出时也要辅助数组中的值来减少每个桶中不必要的访问。
完成该步骤之后,要将辅助数组中的元素全部清空,以便下一次排序。此步骤一定要放在划分元素进桶之前。
循环完毕之后输入序列中就是已经排好的键值元素了。
3.问题,为什么是从个往上比,而不是从最大位往下比?很简单,举个例子就行。比如312,146。如果从髙到低比的话,那最后是146比312大,为什么呢。因为地位的优先值本就低于高位,我高位排好序的话,你再进行低位的排序也是再高位的涵盖范围之内,所以是高位到低位的排序。
4.整体代码如下下面展示一些 。

#include<stdio.h>
#include<stdlib.h> 
#define MaxSize 100//这种做法有一些缺陷,当失去辅助数组的下标的计数支持时,其下标之后的值可能会冒出
//计数排序的关键是每次的基数的键值是必须知道的,每位元素的长度也是必须知道的。
//是桶排序的分支,利用了桶的思想,单排序是基于基数的键值来排序的。 
void SolidSort(int keys[],int keys_number,int keys_table[10][MaxSize])
{
	int max = 0;
	//获取最大数 
	for(int max_i=0;max_i<keys_number;max_i++)
	{
		if(keys[max_i]>max)max=keys[max_i];
	}
	int position = 0;
	int ten_turn = 1;
	int cnt_k = 0;
	while(1){
		if(max>=ten_turn){
			ten_turn*=10;
			position++;
			cnt_k++;
		}else{
			break;
		}
	}printf("最大数为%d,它的位数为%d,循环了%d次",max,position,cnt_k);
	int count_keys[10] = {0};
	int table_subscript = 0;
	int sort_ten = 1;
	int keys_subscript=0;
	for(int sort_i=0;sort_i<position;sort_i++)
	{
			for(int go_i=0;go_i<10;go_i++)count_keys[go_i]=0;//每次使用前化0,既可以方便下面代码转移有序序列,又可以在下次排序之前清空计数的值 
		
		int jishu=0;
		for(int sort_in_i=0;sort_in_i<keys_number;sort_in_i++)
		{
			
			table_subscript = (keys[sort_in_i]/sort_ten)%10;
			jishu = count_keys[table_subscript];
			keys_table[table_subscript][jishu] = keys[sort_in_i];
			count_keys[table_subscript]++;
			printf(" %d ",keys_table[table_subscript][jishu]);//这里不推荐套用多重地址 
		}
		printf("\n");
		sort_ten*=10;
	
		
		//将初步排好的序列放入输入序列 
		printf("%\n");
		for(int i=0;i<10;i++)
		{
		
			for(int j=0;j<count_keys[i];j++,keys_subscript++){
		keys[keys_subscript] = keys_table[i][j];
	}
		
		}
		keys_subscript=0;

	}
	//输出一遍数组是否正确 
		for(int i=0;i<10;i++)
		{
		
			for(int j=0;j<count_keys[i];j++,keys_subscript++){
		printf(" %d ",keys[keys_subscript]);
	}
		
		}

	
	
}

main()
{
	int keys_long=0;
	int kk=0;
	printf(" 请输入待排序列的长度 ");
	scanf("%d",&keys_long);
	int keys[keys_long];
	printf("请输入%d个整型数据",keys_long);
	for(int i=0;i<keys_long;i++){
		fflush(stdin);
		scanf("%d",&kk);
		keys[i]=kk;
	//	printf(" %d ",keys[i]);
	} 
	int keys_table[10][MaxSize]; 
	SolidSort(keys,keys_long,keys_table);//这里的数组传递,传首地址就行了。 
} 

5.总结:基数排序基于输入序列的基数的键值,本身是桶排序的分支。所以基数的键值是一定要可以确定的, 二维数组充当桶的话空间浪费严重,并不推荐用来实际排序。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值