排序专题之分配排序

分配排序分两块,桶式排序和基数排序,基数排序是桶式排序的递进:

下面来看下这两种排序:



简单的说,桶式排序就是,先将序列的数字进行顺序计数,
然后遍历计数每个数字的起点(数字相同的已经合并),然后
从尾部向前扫描,得一个排序好的序列:
具体代码如下:


#include<iostream>
using namespace std;
int main()
{
	int n;
	cin>>n;
	int s[10],a[10];
	int count[50];
	int max; 
	int t;
	int i,j;
	for(i=0;i<n;i++)
	{
		cin>>s[i];
		a[i]=s[i];
	}
	for(i=0;i<50;i++)
	{
		count[i]=0;
	}
	
	for(i=0;i<n;i++)
	{
		count[s[i]]++;
	}
	for(i=0;i<50;i++)
	{
		count[i]=count[i]+count[i-1];
	}
	for(i=n-1;i>=0;i--)
	{
		s[--count[a[i]]]=a[i];
	}
	for(i=0;i<n;i++)
	{
		cout<<" "<<s[i];
	}
	return 0;
}

基数排序:




多关键字排序方法
最高位优先法(MSD):先对最高位关键字k1(如花色)排序,将序列分成若干子序列,
每个子序列有相同的k1值;然后让每个子序列对次关键字k2(如面值)排序,
又分成若干更小的子序列;依次重复,直至就每个子序列对最低位关键字kd排序;
最后将所有子序列依次连接在一起成为一个有序序列





最低位优先法(LSD):从最低位关键字kd起进行排序,然后再对高一位的关键字排序,
……依次重复,直至对最高位关键字k1排序后,便成为一个有序序列
MSD与LSD不同特点
按MSD排序,必须将序列逐层分割成若干子序列,然后对各子序列分别排序
按LSD排序,不必分成子序列,对每个关键字都是整个序列参加排序
;并且可不通过关键字比较,而通过若干次分配与收集实现排序

基数排序的顺序方法(d次桶式排序)


for(i=1;i<=d;i++)
	{
		for(j=0;j<r;j++)//桶置零 
		{
			count[j]=0;
		}
		for(j=0;j<n;j++)//桶计数 
		{
			k=(s[i]/ra)%r;
			count[k]++;
		}
		for(j=1;j<r;j++)
		{
			count[j]=count[j]+count[j-1]; //统计 
		}
		for(j=n-1;j>=0;j--) //桶式排序的倒序放入 
		{
			k=(s[j]/ra)%r;
			count[k]--;
			a[count[k]]=s[j];
		}
		for(j=0;j<n;j++)//重新给予赋值 进入第二次桶式排序 
		{
			s[j]=a[j];
		}
		ra*=r;//改变模,向左移一位 
	}




链式基数排序
      基数排序:借助“分配”和“收集”对单逻辑关键字进行排序的一种方法
      链式基数排序:用链表作存储结构的基数排序




链式基数排序步骤
设置10个队列,f[i]和e[i]分别为第i个队列的头指针和尾指针
第一趟分配对最低位关键字(个位)进行,改变记录的指针值,
将链表中记录分配至10个链队列中,每个队列记录的关键字的个位相同
第一趟收集是改变所有非空队列的队尾记录的指针域,
令其指向下一个非空队列的队头记录,重新将10个队列链成一个链表
重复上述两步,进行第二趟、第三趟分配和收集,分别对十位、百位进行,
最后得到一个有序序列


void distribute(record *a[],int first,int i,int r,staticqueue *queue) //分配过程 
{
	int j,k,a,curr=first;
	for(j=0;j<r;j++)//初始化整个队列 
	{
		queue[j].head=-1;
	}
	
	while(curr!=-1)//对整个静态链进行分配
	{
		k=a[curr].key; //取第i位的排序码数字k
		for(a=0;a<i;a++)
		{
			k/=r;
		} 
		k%=r;
		if(queue[k].head==-1) //桶为空,则a[curr]为第一个记录 
		{
			queue[k].head=curr;
		}
		else a[queue[k].tail].next=curr;
		queue[k].tail=curr;
		curr=a[curr].next;	
	} 
}


void collect(record *a,int &first,int r,staticqueue *queue)//收集过程
{
	int last,k=0;
	while(queue[k].head==-1)//找到第一个非空队列 
	{
		k++;
	}
	first=queue[k].head;
	last=queue[k].tail;
	while(k<r-1)//继续收集下一个队列 
	{
		k++;
		while(k<r-1&&queue[k].head==-1)
		{
			k++;
			if(queue[k].head!=-1)
			{
				a[last].next=queue[k].head;
				last=queue[k].tail;
			}
		}
		a[last].next=-1; //收集完毕 
	} 
	
	
	
} 





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值