分配类排序:核心是分配和收集,利用关键字的优先级进行排序的思想
高位优先排序:比如桥牌,先比较花色在比较面值;比如学号,比较级,院,班,号;
低位优先排序: 链式基数排序
思想:基于"分配"和"收集"的操作, 将单关键字转化为多关键字排序
将链表作为存储结构, 待排序记录以指针相连,构成链表;
分配:按照关键字取值分配记录到链队列相应队列中,每个队列关键字取值相同
收集:按照关键字大小,从小到大,将队列首尾相接连接成一个链表;
重复上述步骤..
定义:
//待排序记录结点
typedef struct node{int data;//比如说一个三位数 struct node *next;
}TNode;//队列首尾指针
typedef struct{node *front;node *rear;
}TPointer;
//根据数组R[](已经存在元素),构建带头结点待排序记录链表
TNode *create_list(int R[], int n){TNode *p, *ph;//p为每一个存了记录的结点, ph为头结点ph = (TNode *)malloc(sizeof(TNode));if(!ph) return NULL; ph->next = NULL;int i;for(i = 0; i < n; i++){p = (TNode *)malloc(sizeof(TNode));if(!p) return NULL;p->data = R[i];//头插法插入 p->next = ph->next;ph->next = p;}return ph;//返回头结点
} #define N 10
//分配算法,对三位数的记录序列按照关键字低位排序分配
void dispatch(TNode *ph, TPointer *Q, int d){ //ph存记录, Q队列:存指针,d根据关键字到那一趟取值不同 TNode *p = NULL;//作为辅助空间拆分ph int i, idx;//初始化Qfor(i = 0; i < N; i++){Q[i].front = NULL;Q[i].rear = NULL; } p = ph->next;if(p){ph->next = p->next;p->next = NULL;}//第一个记录被单独拆到p里面while(p){idx = p->data;for(i = 0; i < d; i++)idx = idx / N;//第一趟排序,d = 0idx = idx % N;//根据关键字分配到Q中if(Q[idx].front = NULL){Q[idx].front = p;Q[idx].rear = p;} else{//尾插法 Q[idx].rear->next = p;Q[idx].rear = p;}p = ph->next;if(p){//拆,直到拆完 ph->next = p->next;p->next = NULL;}}
}void collect(TNode *ph, TPointer *Q){TNode *p;int i;//ph为头结点,最终可以传出去for(i = 0; !Q[i].front; i++);//找出第一个队列中非空结点ph->next = Q[i].front;p = Q[i].rear;i++;for(; i < N; i++){if(Q[i].front){p->next = Q[i].front;p = Q[i].rear;//注意的是Q[i]内部的结点是连接好的 }}p->next = NULL;
} void list_sort(int *R, int n){int i;TNode *ph, *p;TPointer Q[N];int m = max(R, n);ph = create_list(R, n);for(i = 0; m; i++, m /= N){dispatch(ph, Q, i);collect(ph, Q);}for(i = 0, p = ph->next; p; p = p->next){R[i] = p->data;}free(ph);
}