排序专题之分配排序

Posted 纯纯的心儿

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了排序专题之分配排序相关的知识,希望对你有一定的参考价值。

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

下面来看下这两种排序:



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


#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; //收集完毕 
	 
	
	
	
 





以上是关于排序专题之分配排序的主要内容,如果未能解决你的问题,请参考以下文章

快速排序

排序专题之分配排序

排序算法

排序的稳定性

十大排序算法之基数排序

字节排序函数