分配类排序——基数排序

原创 2013年12月03日 21:04:29

         基数排序属于“分配式排序”(distribution sort),基数排序法又称“桶子法”(bucket sort)或bin sort,顾名思义,它是透过键值的部份资讯,将要排序的元素分配至某些“桶”中,藉以达到排序的作用,基数排序法是属于稳定性的排序

时间效率:设待排序列为n个记录,d个关键码,关键码的取值范围为radix,则进行链式基数排序的时间复杂度为O(d(n+radix)),其中,一趟分配时间复杂度为O(n),一趟收集时间复杂度为O(radix),共进行d趟分配和收集。 
空间效率:需要2*radix个指向队列的辅助空间,以及用于静态链表的n个指针。

最高位优先(Most Significant Digit first)法,简称MSD法:先按k1排序分组,同一组中记录,关键码k1相等,再对各组按k2排序分成子组,之后,对后面的关键码继续这样的排序分组,直到按最次位关键码kd对各子组排序后。再将各组连接起来,便得到一个有序序列。
最低位优先(Least Significant Digit first)法,简称LSD法:先从kd开始排序,再对kd-1进行排序,依次重复,直到对k1排序后便得到一个有序序列。

下面是C语言实现的一个例子(使用最低优先法)

#include <unistd.h>
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>

#define RADIX 10                      //基数
#define KEY_SIZE 6                    //键的最大个数
#define LIST_SIZE 20                  //需要排序数的个数
typedef struct
{
    int key;
    int next;                          //静态链域
} RecordType1;

typedef struct 
{
	RecordType1 r[LIST_SIZE + 1];
	int length;
	int keynum;
} SLinkList;                            //静态链表

typedef int PVector[RADIX];
int num[LIST_SIZE][KEY_SIZE];            //将整数进行分离

/*将输入的十进制数的每一位拆分开来*/
void Order(SLinkList *s_num)
{
	int i, m, j, tmp;
	int r_num;

        m = s_num->keynum;
	for (i = 1; i <= s_num->length; i++)
	{       
		r_num = s_num->r[i].key;
		for (j = m-1; j >= 0; j--)                  
		{
			tmp = r_num % 10;
			num[i][j] = tmp;
			r_num = r_num / 10;
			while (r_num == 0 && j != 0)
			{
				j--;
				num[i][j] = 0;
				break;
			}
		}
	}
}

/*分配*/
void Distribute(SLinkList *s_num, int i, PVector head, PVector tail)
{
	int j, p;
	for (j = 0; j <= RADIX-1; ++j)
	{
		head[j] = 0;
	}
	p = s_num->r[0].next;
	while(p != 0)
	{
		j = num[p][i];
		if (head[j] == 0)
		      head[j] = p;
	        else
		      s_num->r[tail[j]].next = p;
		tail[j] = p;
		p = s_num->r[p].next;
	}
}

/*回收*/
void Collect(SLinkList *s_num, PVector head, PVector tail)
{
	int j, t;
	j = 0;
	while (head[j] == 0)
	      ++j;
	s_num->r[0].next = head[j];
	t = tail[j];
	while (j < RADIX - 1)
	{
		++j;
		while ((j < RADIX - 1) && (head[j] == 0))
		{
			++j;
		}
		if (head[j] != 0)
		{
			s_num->r[t].next = head[j];
			t = tail[j];
		}
	}
	s_num->r[t].next = 0;
}

//找最大数
int maxNum(SLinkList *s_num)
{
	int i, max = 0;
	for (i = 1; i <= s_num->length; i++)
	{
		if (s_num->r[i].key > max)
		      max = s_num->r[i].key;
	}
	return max;
}

/*确定关键字的个数(找最大数关键子的位数)*/
void Keynum(SLinkList *s_num)
{
	int max_num, temp = 0, count = 1;

	max_num = maxNum(s_num);                  //找最大数

	temp = max_num / 10;
	while (temp != 0)
	{
		count++;
		temp = temp / 10;
	}
	s_num->keynum = count;
}

/*基数排序*/
void RadixSort(SLinkList *s_num)
{
	PVector head, tail;
	int i, d, n;

	n = s_num->length;
	for (i = 0; i <= n-1; ++i)
	      s_num->r[i].next = i+1;
	s_num->r[n].next = 0;

	d = s_num->keynum;                          //关键字的个数
	for (i = d-1; i >= 0; i--)
	{
		Distribute(s_num, i, head, tail);         //第i趟分配
		Collect(s_num, head, tail);               //第i趟回收
	}
}

/*输出排序后的结果*/
void Print(SLinkList *s_num)
{
	int j;
	j = s_num->r[0].next;

	printf("\nsort finish:");
	while (j != 0)
	{
		printf("%d  ", s_num->r[j].key);
		j = s_num->r[j].next;
	}
	printf("\n");
}

int main(int argc, char *argv[])
{
	SLinkList *s_num;
        int i;

	s_num = (SLinkList *)malloc(sizeof(SLinkList));

	printf("input sort count is : ");
	scanf("%d", &s_num->length);


	printf("\nPlease input sort number is :");
	for (i = 1; i <= s_num->length; i++)
	{
		scanf("%d", &s_num->r[i].key);
	}

        Keynum(s_num);             //计算关键字的个数
	Order(s_num);              //将输入的十进制数进行拆分
	RadixSort(s_num);
	Print(s_num);

	return EXIT_SUCCESS;
}


相关文章推荐

基数排序——radix-sort

  • 2016年04月15日 19:40
  • 205KB
  • 下载

算法导论第八章——基数排序

基数排序的原理是:假设所有要排序的数字位数为d位,不足的数字高位补0,从第一位开始,以该位为基准对数组进行排序(意思是将所有的数中的第1位提取出来,并按照大小进行排序,每一位所对应的数组元素也相应的改...

积跬步至千里——算法强化训练(6)利用基数排序解决O(n)问题

基数排序: 基数排序(radix sort)属于“分配式排序”(distribution sort),又称“桶子法”(bucket sort)或bin sort,顾名思义,它是透过键值的部份资讯,将要...

算法导论例程——基数排序

基数排序(radix_sort)可以被称为是计数排序的升级版,他的原理是基于以前的卡片式排序方法,这里把要排序的每个整数看作是一张卡片,把整数的各位数字看作是卡片上的关键字,在进行计数排序时,我们逐位...
  • CFhM_R
  • CFhM_R
  • 2016年02月08日 03:17
  • 325

微软笔试题——基数排序

这是一题微软的笔试题,原题如下:  排序N个比N^7小的数,要求的算法是O(n)(给了提示..说往N进制那方面想) 此题的分析见 http://blog.csdn.net/sinshine/a...

数据结构——基数排序

简介基数排序和其他一般的排序算法不同,一般的排序算法主要是通过关键字之间的比较和移动记录这两种操作,而实现基数排序则不需要进行记录关键字间的比较。 基数排序是一种借助多关键字排序的思想,对单逻辑关键...

基数排序(Radix Sort)——java实现

关于基数排序的相关概念这里就不多说了,参考基数排序 。 觉得麻烦的看下面的内容: 基数排序(Radix sort)是一种非比较型整数排序算法,其原理是将整数按位数切割成不同的数字,然后按每个...

数据结构实践—— 英文单词的基数排序

本文是针对[数据结构基础系列(9):排序]的实践。【项目 - 英文单词的基数排序】   设计一个基数排序的算法,将一组英文单词,按字典顺序排列。假设单词均由小写字母或空格构成,最长的单词有MaxLe...

算法题——Maximum Gap(JAVA)基数排序

求出数组排序后相连两个数之间最大的差值。

算法导论学习笔记——基数排序

/** * 基数排序:n个d位数进行排序,先从最低有效位进行,由于每位数字都界于0到9(只考虑整数), * 可以用计数排序对每一位进行排序,重复这一过程直到对所有的d位数字都进行了排序。 * 由...
  • FG2006
  • FG2006
  • 2011年08月10日 23:43
  • 1399
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:分配类排序——基数排序
举报原因:
原因补充:

(最多只允许输入30个字)