基数排序过程c语言,基数排序

基数排序

①简介

基数排序是一种用在卡片排序机上的算法,一张卡片有80列,在每一列上机器可以选择在12个位置中的任意一处穿孔。通过机器的操作,能够“编程”来检查每个卡片中的给定列,然后根据穿孔的位置将他们分别放在12个容器中。操作员就可以挨个容器来收集卡片,其中第一个位置穿孔的卡片在最上面,以此类推。

②原理

直观上来看,可能会认为应该先按照最高有效位进行排序并分装到不同的容器中,再对每个容器进行递归的排序,但是对一个容器排序的同时,其他容器全部是空闲状态,必须放在一边还要存起来,会花费很大的空间。

基数排序的思想恰好和人们的直观感受相反,是先按最低有效位进行排序来解决问题的。按最低有效位排序并分配好容器,再将容器中的卡片按照容器编号合成一叠,0号容器在1号容器上面,依次类推。合成一堆后再依据次最低有效位循环上面的流程。

a923dfe946c85e2ef7abbc8dbe7cc5de.png

③C语言实现

#define NUM 10

int digit_assist[] = { 1, 10, 100, 1000, 10000 };

//清空辅助数组

void clear_array(int* a, int count)

{

for (int i = 0; i < count; i++)

{

a[i] = 0;

}

}

//得到第d位数上的数字

int get_digit(int num, int d)

{

return (num / digit_assist[d - 1]) % 10;

}

//得到输入数组中最大的位数

int get_max_digit(int *a, int count)

{

int max_digit = 1,max = a[0];

for (int i = 1; i < count; i++)

{

if (a[i] > max)

max = a[i];

}

while (0 != max / 10)

{

max = max / 10;

max_digit++;

}

return max_digit;

}

//基数排序

void radix_sort(int* a, int count)

{

int max_digit, *bucket, *bucket_index;

bucket = (int*)malloc(count * sizeof(int));

bucket_index = (int*)malloc(NUM * sizeof(int));

max_digit = get_max_digit(a, count);

for (int i = 0; i < max_digit; i++)

{

//清空辅助容器

clear_array(bucket, count);

clear_array(bucket_index, NUM);

/* 利用了计数排序的小知识,避免过大的容器开销

* 先统计每个桶里面有多少个数字

*/

for (int j = 0; j < count; j++)

bucket_index[get_digit(a[j], i + 1)]++;

for (int j = 1; j < NUM; j++)

bucket_index[j] += bucket_index[j - 1];

/* 开始进行排序

* 这里倒序开始,此处重点,原因在后面分析

*/

for (int j = count - 1; j >= 0; j--)

{

int k = get_digit(a[j], i + 1);

bucket[bucket_index[k] - 1] = a[j];

bucket_index[k]--;

}

//再从容器中收集排列的数据

for (int j = 0; j < count; j++)

{

a[j] = bucket[j];

}

}

}

void main()

{

int count, *p;

printf("请输入需要排序的数的个数 :");

scanf_s("%d", &count);

p = (int*)malloc(count * sizeof(int));

printf("\n请输入需要排序的%d个数字:",count);

for (int i = 0; i < count; i++)

{

scanf_s("%d", p+i);

}

printf("\n快速排序后的数组:");

radix_sort(p,count);

for (int i = 0; i < count; i++)

{

printf("%d ", p[i]);

}

printf("\n");

system("pause");

}

在这里说明一下,代码里面开始排序的时候为什么从后面提取数据而不是从前面。这里用一个例子来说明情况:假设我们需要排列的数组有三个数,分别是333,22,1。这三个数需要三次大的基数排序循环才能排好序,在循环的前两次,按照流程走下来都没什么大的问题,第二次大循环下来后,原始数组变成了1,22,333。

现在进行第三次的排序,轮到比较百位上的数字了,分别是百位上数字为0,0,3。统计出来的bucket_index数组中结果为2,2,2,3,3,3,3,3,3,3。统计完成后开始排序,如果这时候从前往后开始重新放置数字进入新的数组(类似计数排序那样bucket_index[k]–;),具有相同的百位数字中,十位数字较小的数字可能被放到十位数字较大的数字后面,会造成之前十位数字大循环拍好序列的紊乱。因此需要从后面向前面取数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值