1.思想
1.1 例子
1.2.思想介绍
1.基数排序是在箱排序的基础之上进行扩展和完善的
2.通过判断待排序的数组中的位数,决定进行创建箱子的个数和遍历的次数.
例如:待排序中最多的位数为3位,那么就需要创建三个箱子(当然也可以创建两个,进行复用,记得复用之前要清除之前的箱子),这里我就不复用了.那么需要进行遍历三次
3.开始排序(就是遍历装箱操作)
3.1:第一次遍历待排序的数组.进行第一次装箱(箱子A),按照个数进行装到对应的箱子.
3.2:第二次顺序遍历前面的箱子(箱子A),进行第二次装箱(箱子B),按照十位数进行装到对应的箱子中.
3.3:第三次顺序遍历前面的箱子(箱子B),进行第三次装箱(箱子C),按照百位数进行装到对应的箱子中.
到了这里已经排序完成,还差最后一步.
4.组装数据,顺序遍历最后一次的箱子(箱子C).存储到一个数组中,此时数组中的数据就是已经排序好的.
例如:上面的箱子,顺序遍历这个箱子A存储到箱子B中.(按照十位存储)
读取0号桶:
第一个数:200, 十位为0, 存储箱子B中0号桶[200]
第二个数:100, 十位为0, 存储箱子B中0号桶[200,100]
读取1号桶:
第一个数:211, 十位为1, 存储箱子B中1号桶[211]
读取2号桶:
没有值跳过
读取3号桶:
第一个数:143, 十位为4, 存储箱子B中4号桶[143]
第二个数:433, 十位为3, 存储箱子B中3号桶[433]
读取4号桶:
第一个数:84, 十位为4, 存储箱子B中8号桶[84]
第二个数:134, 十位为3, 存储箱子B中3号桶[433,134]
第三个数:534, 十位为3, 存储箱子B中3号桶[433,134,534]
第四个数:994, 十位为9, 存储箱子B中9号桶[994]
…后面的就不一一举例了.直到遍历结束.
2.运行结果
3.算法实现
3.1 定义数据结构
#define MAX_COUNT 10
//链表结点 顺序存储箱子中数值,这样就可以不用限制数据量.
typedef struct SNode{
int value;
struct SNode * next;
}Node;
//箱子中的每个链表
typedef struct List{
int key;
Node *header;//头指针
Node *rear;//尾指针
}LinkList;
//箱子列表
typedef struct RadixBox{
LinkList * boxs[MAX_COUNT];
}RB;
3.2 定义方法集合
//入队
void InsertList(LinkList *list,int value);
//打印队列
void logList(LinkList *list);
//打印箱子
void logRadixBox(RB rb);
//打印箱子--数组类型
void logRadixBoxArray(RB rb);
//装箱操作
//type:1->除数为1*10 2:除数为2*20
void EnRadixBox(int type,RB rb,int value);
//基数排序
void RadixSort(void);
下载的源码中少了这个方法:logRadixBoxArray(),可以添加上,也可以不加,这是多打印了每次装箱后的数组.
3.3 方法实现
//打印队列
void logList(LinkList *list){
//先判断列表是否为空
if(list!=NULL){
Node *p=list->header;
printf("[");
int first=1;
while (p!=NULL) {
if(first==1){
first=0;
printf("%d",p->value);
}else{
printf(",%d",p->value);
}
p=p->next;
}
printf("]\n");
}
}
//打印箱子
void logRadixBox(RB rb){
printf("********************************\n");
int i;
for(i=0;i<MAX_COUNT;i++){
printf("[%d]->",rb.boxs[i]->key);
logList(rb.boxs[i]);
}
logRadixBoxArray(rb);
printf("********************************\n");
}
//打印箱子--数组类型
void logRadixBoxArray(RB rb){
Node *p;
int i=0;
int j;
printf("装箱后的数组:[");
for(j=0;j<MAX_COUNT;j++){
p= rb.boxs[j]->header;
while (p!=NULL) {
if(i==0)
{
printf("%d",p->value) ;
i=1;
}
else
printf(",%d",p->value) ;
p=p->next;
}
}
printf("]\n");
}
//入队
void InsertList(LinkList *list,int value){
//1.创建插入的结点
Node *p=(Node *)malloc(sizeof(Node));
p->value=value;
p->next=NULL;
//2.判断链表是否为NULL
if(list==NULL){
list=(LinkList *)malloc(sizeof(LinkList));
list->header=NULL;
list->rear=NULL;
}
//3.将新的结点插入链表
if(list->header==NULL){
list->header=p;
}
if(list->rear==NULL){
list->rear=p;
}else{
list->rear->next=p;
list->rear=p;
}
}
//装箱操作
//type->0:个数,1:十位,2:百位的余数
void EnRadixBox(int type,RB rb,int value){
//1.type必须从1开始
if(type<0){
return;
}
//2.计算位置
//134: 134%10
//134: (134/10)%10
//134: (134/100)%10
//(value/(pow(10,type)))%10
int position= ((int) (value/(int)pow(10, type)))%10;
LinkList *list= rb.boxs[position];
InsertList(list,value);
}
//基数排序
void RadixSort(void){
int i;
int j;
int n=19;
//1.初始化待排序的数组
int array[]={76,84,134,196,177,143,696,534,599,211,433,200,994,459,635,179,100,26,284};
printf("未排序:");
logArray(array, n);
//2.首先要知道数组中最大的是几位数,就需要几个箱子,从个位到最高位顺序装箱
//初始化箱子
RB rbs[3];
//初始化三个箱子
for(i=0;i<3;i++){
for(j=0;j<MAX_COUNT;j++){
rbs[i].boxs[j]=(LinkList *)malloc(sizeof(LinkList));
rbs[i].boxs[j]->key=j;
rbs[i].boxs[j]->header=NULL;
rbs[i].boxs[j]->rear=NULL;
}
}
//3.开始装箱
for(i=0;i<3;i++){
if(i==0){//第一次是遍历排序数组,装箱
for(j=0;j<n;j++){
//个位
EnRadixBox(i,rbs[i],array[j]);
}
logRadixBox(rbs[i]);
}else{//之后就是遍历前一个箱子进行装箱
//遍历前一个箱子,装在当前箱子
RB rbPre=rbs[i-1];
for(j=0;j<MAX_COUNT;j++){
if(rbPre.boxs[j]!=NULL){
Node *p=rbPre.boxs[j]->header;
while (p!=NULL) {
EnRadixBox(i,rbs[i],p->value);
p=p->next;
}
}
}
logRadixBox(rbs[i]);
}
}
//4.遍历最后一个箱子装入数组,就是排好序的
Node *p;
i=0;
for(j=0;j<MAX_COUNT;j++){
p= rbs[2].boxs[j]->header;
while (p!=NULL) {
array[i++]=p->value;
p=p->next;
}
}
printf("已排序:");
logArray(array, n);
}
3.4 另外的实现思路
我这里循环遍历的时候,第一次是遍历待排序的数据,然后进行装箱,剩下的顺序遍历,是遍历上一次的箱子.
优化点:
1.创建箱子的时候,可以创建一个个箱子
2.每次装完箱子操作后,可以先顺序遍历箱子,顺序存储到数组中.然后下一次遍历的时候,是遍历装箱后的数组.这样就是每次都是遍历数组,进行装箱.
3.在决定循环几次的时候,我这里知道待排序中的数组,最大的是3位数,
3.1这里可以写一个快速查找方法,寻找最大位数,或者最大值.
3.2或者是在第一次装箱的时候,同时查找最大位数(N)也可以,这样后面循环的就是再进行(N-1)次.