基数排序_FAFU_1270

基数排序的介绍:

http://baike.baidu.com/view/1170573.htm


基数排序的方式可以采用LSD(Least significant digital)或MSD(Most significant digital),LSD的排序方式由键值的最右边开始,而MSD则相反,由键值的最左边开始。

  以LSD为例,假设原来有一串数值如下所示:
  73, 22, 93, 43, 55, 14, 28, 65, 39, 81
  首先根据个位数的数值,在走访数值时将它们分配至编号0到9的桶子中:
  0
  1 81
  2 22
  3 73 93 43
  4 14
  5 55 65
  6
  7
  8 28
  9 39
  接下来将这些桶子中的数值重新串接起来,成为以下的数列:
  81, 22, 73, 93, 43, 14, 55, 65, 28, 39
  接着再进行一次分配,这次是根据十位数来分配:
  0
  1 14
  2 22 28
  3 39
  4 43
  5 55
  6 65
  7 73
  8 81
  9 93
  接下来将这些桶子中的数值重新串接起来,成为以下的数列:
  14, 22, 28, 39, 43, 55, 65, 73, 81, 93
  这时候整个数列已经排序完毕;如果排序的对象有三位数以上,则持续进行以上的动作直至最高位数为止。
  LSD的基数排序适用于位数小的数列,如果位数多的话,使用MSD的效率会比较好。MSD的方式与LSD相反,是由高位数为基底开始进行分配,但在分配之后并不马上合并回一个数组中,而是在每个“桶子”中建立建立“子桶”,将每个桶子中的数值按照下一数位的值分配到“子桶”中。在进行完最低位数的分配后再合并回单一的数组中。


fafu1270:http://acm.fafu.edu.cn/problem.php?id=1270

这题 如果仅仅是过那很简单了,用queue直接排两次就能过,根本不用什么循环~~~  (不过不是老师的本意 - -#,管他呢,先过了再说 ……^_^)

// http://acm.fafu.edu.cn/problem.php?id=1270

#include <stdio.h>
#include <queue>
using namespace std;
int num[30005];



int main(void)
{
	queue<int> que[10];
	int n;
	scanf("%d", &n);
	int val;
	int temp = n;
	int i;
	//刚读进来时就把数据按个位大小存到0~9队列中
	while(temp--)
	{
		scanf("%d", &val);
		que[val%10].push(val);
	}
	
	//然后把队列中的数据首尾相连存到num数组中去
	int index=0;
	for(i=0; i<10; i++)
	{
		while(!que[i].empty())
		{
			num[index++] = que[i].front();
			que[i].pop();
		}
	}
	
	//最后按输入数据的十位再次存放到0~9队列中
	for(i=0; i<n; i++)
	{
		que[num[i]/10%10].push(num[i]);
	}
	int foo=0;

	//然后把队列中的经过两次收集之后的数据打印出来
	for(i=0; i<10; i++)
	{
		while(!que[i].empty())
		{
			foo++;
			printf("%d%s", que[i].front(), foo%10==0 ? "\n": " ");
			que[i].pop();
		}
	}
	return 0;
}

然后,把上面代码改动一下,让其可以处理更多的情况,也可以实现真正的排序,只要给radix适当的值就行了,当然,还是比较低级的,不能算是实用的基数排序算法


// http://acm.fafu.edu.cn/problem.php?id=1270

#include <stdio.h>
#include <queue>
using namespace std;
int num[30005];
queue<int> que[10];

void radix_sort(int * array, int radix, int n)
{
	// radix是要排的位数, 比如说把一堆数按个位和十位排两次,那radix=2
	// n是num数组中元素的个数
	int j;
	int k=1; // k is an important variable, can't used by others
 	
	for(int i=1; i<=radix; i++)  //对radix扫描:个位,十位,百位…… 
	{
		//把所有的数按某一位放入队列数组中 
		for(j=0; j<n; j++)
			que[array[j]/k%10].push(array[j]);
		k *= 10;
		
		//把所有数据首尾相连后再次放入数组中去
		j = 0;
		for(int i=0; i<10; i++)	//扫描队列数组 
		{
			while(!que[i].empty())
			{
				array[j++] = que[i].front();
				que[i].pop();
			}
				
		} 
	} 
}

int main(void)
{

	int n,i;
	scanf("%d", &n);		
	
	//把数据读到数组中去 
	for(i=0; i<n; i++)
		scanf("%d", &num[i]);
		
	radix_sort(num, 2, i);

	//打印出排序后的数据	
	for(i=0; i<n; i++)
		printf("%d%s", num[i], (i+1)%10==0 ? "\n" : " ");
	return 0;
}

版本三:

可以不用指定位数来进行排序了


#include <stdio.h>
#include <queue>
using namespace std;
int num[30005];
queue<int> que[10];



void radix_sort(int * array, int length)
{
	int j;
	int k=1; 
 	
	bool scan_over = false;
	while(true) //对radix扫描:个位,十位,百位…… 
	{
		if(scan_over)
			break;
		scan_over = true;
		//把所有的数按某一位放入队列数组中 
		for(j=0; j<length; j++)
		{
			if(array[j]/k != 0)
				scan_over = false;
			que[array[j]/k%10].push(array[j]);
		}
			
		k *= 10;
		
		//把所有数据首尾相连后再次放入数组中去
		j = 0;
		for(int i=0; i<10; i++)	//扫描队列数组 
		{
			while(!que[i].empty())
			{
				array[j++] = que[i].front();
				que[i].pop();
			}
				
		}
		if(!scan_over)
		printf("k is %d\n", k); 
	} 
}

int main(void)
{

	int n,i;
	scanf("%d", &n);		
	
	//把数据读到数组中去 
	for(i=0; i<n; i++)
		scanf("%d", &num[i]);
		
	radix_sort(num, i);

	//打印出排序后的数据
	for(i=0; i<n; i++)
		printf("%4d%s", num[i], (i+1)%10==0 ? "\n" : " ");
	return 0;
}


你可能感兴趣的:(算法)