# 6. 分配类排序

1. 多关键字排序
两个关键字的优先级,先分高级的叫 “高位优先” 排序法,先分低级的叫 “低位优先” 排序法

2. 链式基数排序
排序时先按最低位的值对记录进行初步排序,在此基础上再按次低位的值进行进一步排序。依此类推,由低位到高位,每一趟都是在前一趟的基础上,根据关键字的某一位对所有记录进行排序,直至最高位,这样就完成了基数排序的全过程。

// 理解就好不用硬看
#define RADIX 10
#define KEY_SIZE 6
#define LIST_SIZE 20
typedef int KeyType;
typedef struct {
    KeyType keys[KEY_SIZE]; /* 子关键字数组 */
	OtherType other_data; /* 其它数据项 */
	int next; /* 静态链域 */
}RecordType1;
typedef struct {
	RecordType1 r[LIST_SIZE+1]; /* r [0] 为头结点 */
	int length;
	int keynum;
} SLinkList; /* 静态链表 */
typedef int PVector[RADIX]; 
/* 记录数组 r 中记录已按低位关键字 key [i+1],…,key [d] 进行过 “低位优先” 排序。
本算法按第 i 位关键字 key [i] 建立 RADIX 个队列,同一个队列中记录的 key [i] 相同。head [j]
和 tail [j] 分别指向各队列中第一个和最后一个记录(j=0,1,2,…,RADIX-1)。head [j]=0
表示相应队列为空队列 */
void Distribute(RecordType1 r[], int i, PVector head, PVector tail){
	for ( j=0 ; j<=RADIX-1 ; ++j)head[j]=0; /* 将 RADIX 个队列初始化为空队列 */
	p= r[0].next ; /* p 指向链表中的第一个记录 */
	while( p!=0 ){
		j=Order(r[p].key[i]); /* 用记录中第 i 位关键字求相应队列号 */
		if ( head[j]==0 ) head[j]=p ; /* 将 p 所指向的结点加入第 j 个队列中 */
		else r[tail[j]].next=p;
	 	tail[j]=p;
		p= r[p].next ;
	}
} /* Distribute */
/* 本算法从 0 到 RADIX-1 扫描各队列,将所有非空队列首尾相接,重新链接成一个链表 */
void Collect (RecordType r[], PVector head, PVector tail){
	j=0;
	while (head[j]==0 )  ++j ;/* 找第一个非空队列 */
	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 ){ /* 链接非空队列 */
	    	r[t].next =head[j] ;
            t=tail[j] ;
		}
	}
	r[t].next =0; /* t 指向最后一个非空队列中的最后一个结点 */
} /* Collect */
/* length 个记录存放在数组 r 中,执行本算法进行基数排序后,链表中的记录将按关键字从小到大的顺序相链接。 */
void RadixSort (RecordType r[],int length ){
	n= length;
	for ( i=0 ; i<= n-1 ; ++i) r[i].next=i+1 ; /* 构造静态链表 */
	r[n].next =0 ;
	d= keynum;
	for ( i =d-1 ; i>= 0; --i ){ /* 从最低位子关键字开始,进行 d 趟分配 和 收集 */
		Distribute(r,i,head,tail); /* 第 i 趟分配 */
		Collect(r,head,tail) /* 第 i 趟收集 */
	}
} /* RadixSort */
-->