排序算法——基数排序

来源:互联网 发布:java snmp流量监控 编辑:程序博客网 时间:2024/05/29 11:09
       基数排序不需要进行关键字的比较,而是通过“分配”和“收集”过程来实现排序的,是一种借助多关键字排序的思想对单关键字排序的方法。它通过比较关键字不同位上的字符的大小进行排序,每一趟排序过程并不产生有序区,也就是说在最后一趟排序结束前,所有元素并不一定都归位了。基数排序分为最低位优先(LSD)和最高位优先(MSD)。本博文只介绍最低位优先(LSD),不过,只要理解了最低位优先(LSD),那么最高位优先(MSD)也就很容易理解。

       基数排序并不是使用数组保存待排序元素,而是使用一个单链表保存,并且每个元素的关键字并不是一个数字,而是用一个字符数组表示数字。如,使用长度为10的字符数组,对于数字24,则字符数组的第0位到第7位取值为0,第8位取值为2,第9位取值为4。

/** * 基数排序 * * 算法:基数排序(Radix Sort) * 输入:待排序元素的单链表指针,基数,关键字位数 * 输出: * 原理:元素R[i]的关键字R[i].key由d位数字组成,即R[i].key=k[d-1]k[d-2]…k[0],每一个数字表示关键字的一位,其中k[d-1]是最高位,k[0]是最低位,每一位的值都在[0,r)之间。例,对于一个十进制数,如249,它是一个3位数,所以d=3,最高位k[2]=2,最低位k[0]=9,基数r=10,因为每一位数都在[0,9]之间。 最低位优先:先按最低位的值对元素进行排序,对得到得到的序列,再按次低位进行排序,……,由低位向高位,每一次排序都是根据关键字的一位对元素进行排序,直至最高位。 * 过程: *  1)按照最低位对元素进行排序,在排序过程中将它们暂时保存在多个链表中(该过程称为分配) *  2)将暂时保存在链表中的元素,重新保存到一个单链表中,此时所有元素按照最低位是从小到大排序的(该过程称为收集) *  3) 按照次低位对元素进行排序,重复上述操作 *  4)... *  5) 按照最高位对元素进行排序,重复上述操作 *  6)最终得到的单链表p中的元素递增排序 * * 时间复杂度为O(d*(n+r)),空间复杂度为O(r),稳定的排序方法。其中,n为元素个数,r为基数 */#define NULL 0#define MAXD 10typedef struct node{char data[MAXD]; //MAXD为最大的关键字位数,把关键字表示为字符数组struct node *next;}RecPoiType;#define MAXR 10void radixSort(RecPoiType *&p, int r, int d){//定义各链表的首尾指针RecPoiType *head[MAXR], *tail[MAXR], *t;int i, j, k;//从低位到高位循环for (i = 0; i <= d - 1; i++){//初始化各链队首、尾指针for (j = 0; j < r; j++)head[j] = tail[j] = NULL;//分配:对于原链表中每个节点循环while (p != NULL){//找第k个链队k = p->data[i] - '0';if (head[k] == NULL) //第k个链队空时,队头队尾均指向*p{head[k] = p;tail[k] = p;}else //第k个链队非空时,*p入队{tail[k]->next = p;tail[k] = p;}//取下一个待排序的元素p = p->next;}//重新用p来收集所有节点p = NULL;//若第j个链队是第一个非空链队for (j = 0; j < r; j++){if (head[j] != NULL){if (p == NULL){p = head[j];t = tail[j];}else //若第j个链队是其它非空链队{t->next = head[j];t = tail[j];}}}//最后一个节点的next域置NULLt->next = NULL;}}

       为了让大家更好的理解基数排序,接下来会给出一个例子,通过例子可以很容易理解基数排序的原理。本例子摘自于教科书中。


0 0
原创粉丝点击