基数排序其实是利用队列先进先出的特点,然后进行排序的。基本方法是这样:
int arr[] = {278,109,63,930,589,184,505,269,8,83};
- 初始化十个(数组元素的个数)队列bucket,并存放在一个数组中;
- 求base,即数组中最大元素是几位数。在这个数组中,base = 3;
- 接下来就要入队列了,这是很关键的一步。首先你要决定以什么样的方式入队列,怎么入,其次你要考虑入到哪里。基于base,我们先求出来元素的最后一位数,然后将求出来的数作为bucket的下标,也就是将该元素放到所对应的队列中。举个例子来说,对于数字278,base走第一次循环求出来的数是8,所以它就应该存放在bucket[8]中。然后按照这种方法,我们把十个数都放到各自对应的队列中。
4. 现在十个数都被放倒对应的队列中了,下来就该出队列了。出队列好说。arr下标从0开始走,同时判断队列是否为空,不为空的话出队列,并将其数据存放在arr中,直到所有元素全部出完。这个时候你会看到数组中元素的最后一位是按照顺序排列的。
5. 接下来求出元素的倒数第二位数,然后像第二步一样,给它入队列。还是拿278来说,它应该被放到bucket[7]中。
6. 十个元素都被放到队列中了,接下来又该出队列了,让那些元素回到它们母亲的怀抱了,像第四步那样做就可以了。
8. 就剩最后一步了,将所有的元素都放回去就大功告成了。当然,这是基于base等于3的情况,如果base更大,那肯定循环的次数就更多了。
下面来看看代码的实现吧:
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <assert.h>
//初始化一个队列
LINK_SORT *init_queue()
{
LINK_SORT *p = (LINK_SORT *)malloc(sizeof(LINK_SORT));
assert(p != NULL);
p->data = 0;
p->next = NULL;
return p;
}
//销毁队列
bool destory_queue(LINK_SORT *phead)
{
if (phead == NULL)
{
return false;
}
LINK_SORT *p = phead->next;
//释放队列中的元素
while (p != NULL)
{
phead->next = p->next;
free(p);
p = phead->next;
}
free(phead); //释放头结点
return true;
}
//申请一个结点
static LINK_SORT *alloc_node(elem_type e)
{
LINK_SORT *tmp = (LINK_SORT *)malloc(sizeof(LINK_SORT));
assert(tmp != NULL);
tmp->data = e;
tmp->next = NULL;
return tmp;
}
//判断队列是否为空
bool is_empty(LINK_SORT *phead)
{
if (phead == NULL)
{
return false;
}
return phead->next == NULL;
}
//查看队列中的第一个元素,只是查看,并不出队列
bool get_head(LINK_SORT *phead, elem_type *e)
{
if (phead == NULL)
{
return false;
}
*e = phead->next->data;
return true;
}
//入队列
bool push(LINK_SORT *phead, elem_type e)
{
if (phead == NULL)
{
return false;
}
LINK_SORT *p = phead;
LINK_SORT *tmp = alloc_node(e);
while(p->next != NULL)
{
p = p->next;
}
p->next = tmp;
return true;
}
//出队列
bool pop(LINK_SORT *phead, elem_type *e)
{
if (phead == NULL || is_empty(phead))
{
return false;
}
LINK_SORT *p = phead->next;
phead->next = p->next;
*e = p->data;
free(p);
return true;
}
//计算数组中最大元素的位数
int get_base(int *arr,int len)
{
int max = arr[0];
//求数组中的最大元素
for (int i=1;i<len;i++)
{
if (max < arr[i])
{
max = arr[i];
}
}
int count = 0;
// 计算最大元素的位数
while(max != 0)
{
max /= 10;
count++;
}
return count;
}
//排序
void base_sort(int *arr, int len, int base,int radix)
{
LINK_SORT **bucket = (LINK_SORT **)malloc(sizeof(LINK_SORT *) * radix);//二级指针用来保存队列的地址
assert(bucket != NULL);
for (int i = 0;i<len;i++)
{
bucket[i] = init_queue();//以待排序数组的长度为标准初始化队列
}
for (int i = 0;i<base;i++)//遍历每个元素的每一位
{
for (int j = 0;j<len;j++)
{
//将数组中的元素逐一放进它第base位所对应的队列中
push(bucket[(arr[j]/(int)pow((double)radix,i))%radix],arr[j]);
}
int k = 0;
for (int j = 0;j<len;j++)
{
while(!is_empty(bucket[j]))//当队列不为空时,出队列,并继续放到数组中
{
pop(bucket[j],&arr[k]);
k++;
}
}
}
for (int i = 0;i<len;i++)
{
destory_queue(bucket[i]);
}
free(bucket);
}
int main()
{
int arr[] = {278,109,63,930,589,184,505,269,8,83};
int len = sizeof(arr)/sizeof(arr[0]);
int base = get_base(arr,len);
int radix = 10;
base_sort(arr, len, base,radix);
for (int i=0;i<len;i++)
{
printf("%d ",arr[i]);
}
printf("\n");
return 0;
}
原文:https://blog.csdn.net/qq_35820702/article/details/52975231