【基数排序】
基数排序的算法思想:基数排序不同于前面的各种排序算法,前面的排序算法都是基于元素之间的比较好实现的,而基数排序则是利用分类进行排序的方法。

【算法思想】

基数排序是一种多关键字排序算法。基数排序通过对所有元素根据关键字进行分类,然后按照关键字的顺序将这些元素收集起来,通过这样的方法完成对元素序列的排序。因此基数排序算法分成两个分部:分配和收集。

具体算法描述:假设第i个元素a_i的关键字为key_i,key_i是由d位个十进制组成,即key_i=ki^d ki^d-1 ... ki^1,其中ki^1为最低位,ki^d为最高位。关键字的每一位数字都可以作为一个子关键字。首先将每一个元素依次按照每个关键字进行排序并收集,直到按照所有的关键字都排序、收集完毕,这样就完成了排序过程。

【示例】
例如,一组元素序列为325,138,29,214,927,631,732,205。这组元素的位数最多是3,在排序之前首先将所有元素都转换为3位数字组成的数,不够3位的在前面添加0,即325,138,029,214,927,631,732,205。对这组元素进行基数排序需要进行3趟分配和收集。其次需要对该元素序列的关键字的最低位即个位上的数字进行分配和收集,再对十位数字进行分配和收集,最后是对最高位的数字进行分配和收集。一般情况下,采用链表实现基数排序。

对最低位进行分配和收集的过程如下图所示。


其中,数组f[i]保存第i个链表的头指针,数组r[i]保存第i个链表的尾指针。

对十位数字的分配和收集的过程如下图所示。


对百位数字的分配和收集的过程如下图所示。


由上很容易看出,经过第1趟排序即对个位数字作为关键字进行分配后,关键字被分为10类,个位数组相同的数字被划分为一类,然后对分配后的元素进行收集之后,得到以个位数字非递减排列的元素。同理,经过第2趟分配和收集后,得到以十位数字非递减排列的元素序列。经过第3趟分配和收集后,得到最终排序结果。

code:

#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#define MaxSize 200 /*待排序元素的最大个数*/
#define N 8             /*待排序元素的实际个数*/
#define MaxNumKey 6 /*关键字项数的最大值*/
#define Radix 10        /*关键字基数,10表示十进制数字可以分为十组*/
/*静态链表的结点,存放待排序元素*/
typedef struct
{int key[MaxNumKey];    /*关键字*/int next;
}SListCell;
/*静态链表,存放元素序列*/
typedef struct
{SListCell data[MaxSize];       /*存储元素,data[0]为头结点*/int keynum;              /*每个元素的当前关键字个数*/int length;                 /*静态链表的当前长度*/
}SList;
typedef int addr[Radix]; /*指针数组类型,用来指向每个链表的第1个结点和最后一个结点*/
void DispList(SList L);             /*输出链表中的元素*/
void DispStaticList(SList L);       /*以静态链表的形式输出元素*/
void InitList(SList *L, int d[], int n);
int trans(char c);              /*将字符转换为数字*/
void Distribute(SListCell data[], int i, addr f, addr r);   /*分配*/
void Collect(SListCell data[], addr f, addr r);         /*收集*/
void RadixSort(SList *L);                   /*基数排序*/
void Distribute(SListCell data[], int i, addr f, addr r)
/*为data数组中的第i个关键字key[i]建立Radix个子表,使同一子表中元素的key[i]相同*/
/*f[0..Radix-1]和r[0..Radix-1]分别指向各个子表中第一个和最后一个元素*/
{int j, p;for (j = 0; j<Radix; j++)           /*初始化各个子表*/f[j] = 0;for (p = data[0].next; p; p = data[p].next){j = trans(data[p].key[i]);      /*将关键字转换为数字*/if (!f[j])             /*f[j]是空表,则f[j]指示第一个元素*/f[j] = p;elsedata[r[j]].next = p;r[j] = p;        /*将p所指的结点插入第j个子表中*/}
}
void Collect(SListCell data[], addr f, addr r)
/*收集,按key[i]将f[0..Radix-1]所指各子表依次链接成一个静态链表*/
{int j, t;for (j = 0; !f[j]; j++);   /*找第一个非空子表,succ为求后继函数*/data[0].next = f[j];t = r[j];           /*r[0].next指向第一个非空子表中第一个结点*/while (j<Radix - 1){for (j = j + 1; j<Radix - 1 && !f[j]; j++);       /*找下一个非空子表*/if (f[j])       /*将非空链表连接在一起*/{data[t].next = f[j];t = r[j];}}data[t].next = 0;      /*t指向最后一个非空子表中的最后一个结点*/
}
void RadixSort(SList *L)
/*基数排序,使得L成为按关键字非递减的静态链表,L.r[0]为头结点*/
{int i;addr f, r;for (i = 0; i<(*L).keynum; i++)  /*由低位到高位依次对各关键字进行分配和收集*/{Distribute((*L).data, i, f, r);        /*第i趟分配*/Collect((*L).data, f, r);          /*第i趟收集*/printf("第%d趟收集后:", i + 1);DispStaticList(*L);}
}
void InitList(SList *L, int a[], int n)
/*初始化静态链表L*/
{char ch[MaxNumKey], ch2[MaxNumKey];int i, j, max = a[0];for (i = 1; i<n; i++)           /*将最大的元素存入max*/if (max<a[i])max = a[i];(*L).keynum = (int)(log10(max)) + 1;   /*求子关键字的个数*/(*L).length = n;                   /*待排序个数*/for (i = 1; i <= n; i++){itoa(a[i - 1], ch, 10);    /*将整型转化为字符,并存入ch*/for (j = strlen(ch); j<(*L).keynum; j++)/*若ch的长度<max的位数,则在ch前补'0'*/{strcpy(ch2, "0");strcat(ch2, ch);strcpy(ch, ch2);}for (j = 0; j<(*L).keynum; j++)    /*将每个元素的各位数存入key,作为关键字*/(*L).data[i].key[j] = ch[(*L).keynum - 1 - j];}for (i = 0; i<(*L).length; ++i)            /*初始化静态链表*/(*L).data[i].next = i + 1;(*L).data[(*L).length].next = 0;
}
void main()
{int d[N] = { 325,138,29,214,927,631,732,205 };SList L;InitList(&L, d, N);printf("待排序元素个数是%d个,关键字个数为%d个\n", L.length,L.keynum);printf("排序前的元素序列:");DispStaticList(L);printf("排序前的元素的存放情况:\n");DispList(L);RadixSort(&L);printf("排序后元素的存放情况:\n");DispList(L);getchar();
}
void DispList(SList L)
/*按数组序号形式输出静态链表*/
{int i, j;printf("序号 关键字 地址\n");for (i = 1; i <= L.length; i++){printf("%2d    ", i);for (j = L.keynum - 1; j >= 0; j--)printf("%c", L.data[i].key[j]);printf("    %d\n", L.data[i].next);}
}
void DispStaticList(SList L)
/*按链表形式输出静态链表*/
{int i = L.data[0].next, j;while (i){for (j = L.keynum - 1; j >= 0; j--)printf("%c", L.data[i].key[j]);printf(" ");i = L.data[i].next;}printf("\n");
}
int trans(char c)
/*将字符c转化为对应的整数*/
{return c - '0';
}

结果:

【主要用途】

基数排序算法实现复杂,它是一种多关键字排序算法,属于分类排序。因为基数排序算法不需要过多比较,所以在数据较多的情况下,采用基数排序算法的效率要优于前面谈到的排序算法。

【稳定性与复杂度】

基数排序是一种稳定的排序算法。
基数排序算法的时间复杂度为O(d(n+r)),其中,n表示待排序的元素个数,d表示关键字个数,r表示基数。其中一趟分配时间复杂度为O(n),一趟收集时间复杂度为O(r)。

基数排序需要2*r个指向链式队列的辅助空间。

排序算法8——基数排序相关推荐

  1. 经典排序算法之基数排序(C语言版)

    排序算法之基数排序的C语言实现. #include "math.h" #include "stdio.h"/* * 基数排序 2016-04-18 23:43: ...

  2. 数据结构之排序算法:基数排序

    排序算法:基数排序 思维导图: 基数排序的定义: 分配和收集: 基数排序的性能: 基数排序应用: 思维导图: 基数排序的定义: ps: n表示线性表长度 d表示每个元素的位数,例324有三位数字 r表 ...

  3. php排序算法算法,PHP排序算法之基数排序(Radix Sort)实例详解

    本文实例讲述了PHP排序算法之基数排序(Radix Sort).分享给大家供大家参考,具体如下: 基数排序在<大话数据结构>中并未讲到,但是为了凑齐八大排序算法,我自己通过网络学习了这个排 ...

  4. 【基数排序】十大排序算法之基数排序

    [基数排序]十大排序算法之基数排序,是属于[稳定]的排序. 目录 一.基数排序基本思想 二.基数排序代码实现 2.1.二维数组实现 2.2.链表实现

  5. 经典排序算法之基数排序

    经典排序算法之基数排序 1. 基数排序 基数排序是一种非比较型整数排序算法,其原理是将整数按位数切割成不同的数字,然后按每个位数分别比较.由于整数也可以表达字符串(比如名字或日期)和特定格式的浮点数, ...

  6. 排序算法-08基数排序(python实现)

    基数排序 前言 这就是整个排序算法的最后一篇了,再深入的后来提出的排序算法基本上是基于这8中基本的排序算法,不做过多赘述. 概述 这是完全不同于之前的排序理念的一种排序方式,它是非基于比较的整形数据排 ...

  7. C语言必学的12个排序算法:基数排序

    # 基本思想 基数排序(radix sort),同样时一种非比较的内部排序算法,主要基于多关键字排序的思想进行排序,它将单个关键字按照基数分成"多个关键字"进行排序.例如整数789 ...

  8. 排序算法:基数排序与计数排序

    基数排序是基于计数排序的算法,每次都需要使用计数排序从而实现基数排序. 那么什么叫基于计数排序?我们首先要明白基数排序的原理: 每次对数字的一个数位(个位.十位.百位......)进行比较,每次比较后 ...

  9. 基数排序 java_JAVA排序算法之基数排序

    源代码运行单个java,且不能带包名: /* * This is a orion editor sample. */ public class PomitTest { public static vo ...

最新文章

  1. 关于MySQL内核,一定要知道的!
  2. Oracle常用知识
  3. ieee文章作者对不齐怎么办呢?
  4. 第1章 数据分析概述
  5. 话说Svn与Git的区别
  6. Linux 等待进程结束 wait() 和 waitpid()
  7. 1.4)深度学习笔记------深层神经网络
  8. realme GT2 Pro获3C认证:65W超级快充加持
  9. 零拷贝技术在 Java 中为何这么牛?
  10. smart原则_用SMART原则,定位好副业目标
  11. Steam如何打开控制台
  12. python英雄对战代码_Python爬虫获取op.gg英雄联盟英雄对位胜率代码
  13. 修改 UITabBar的背景颜色
  14. java websocket ie8_解决WebSocket兼容ie浏览器版本问题
  15. oracle重做日志论文,Oracle重做日志文件相关概念
  16. 事务的并发读问题(简图)
  17. 三次改变世界、却被无情出局的程序员
  18. 实现文件拷贝并获取拷贝进度
  19. 下载神器annie的安装及使用
  20. Win10中使用CMD命令遍历文件夹删除重复文件

热门文章

  1. 阿里云域名+老薛主机 搭建个人博客网站 小结
  2. 美团面试——后端开发岗
  3. Python学习记录——이십 lambda表达式
  4. TortoiseGit配置GitHub
  5. spark入门介绍(菜鸟必看)
  6. Android 获取本地闹钟铃声
  7. 顾问分享|建筑施工企业员工任职资格体系的构建与实践应用
  8. 厨房有约 | 华人生活馆HuarenStore官方博客
  9. linux 清屏命令(3种方式),Linux 清屏命令
  10. Chapter 4、JDK 动态代理