排序专栏:基数排序

Posted 电脑小白路漫漫

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了排序专栏:基数排序相关的知识,希望对你有一定的参考价值。


到目前位置,我们学到的所有排序方法,都是通过比较大小的方式来进行排序的。


那么有没有不用比较大小就能排序的方法呢?


有!


这就是今天介绍的:基数排序


首先我们先看一下效果:

维基百科

为了达到效果,今天我们的数据有些特别:


441    220    283    101    92


接下来,我们用这5个数进行基数排序。

在我们使用基数排序时,首先,我们需要十个“桶”


我们给这十个桶做一个编号,从0-9。随后我们把相应的元素放在桶里。

当然,不能随便乱放,这个元素的数值是几,我们就放到哪个桶里面。


如果我们的数在0-9区间还好说,我们把元素放到相应的同中,接着按照桶的顺序进行排列。


但数值很大怎么办呢?在上面的数列中我们最大的数是584,难道我们需要584个桶吗?


不需要,我们仍然只需要10个桶,只不过过程比个位数时候复杂一点罢了。


我们首先先按照每个元素的个位来进行排序


441——>1号桶

220——>0号桶

283——>3号桶

101——>1号桶

92  ——>2号桶


然后我们按照桶的顺序逐一拿出来得到的数列是这样的。


220    441    101    92    283


这个时候,个位已经具有了一定的顺序。现在我们按照十位来放到桶里

220——>2号桶

441——>4号桶

101——>0号桶

92  ——>9号桶

283——>8号桶


然后我们继续按照桶的顺序逐一拿出来


101    220    441    283    92


虽然这一步看上去打乱了上一步的工作,但实际上这个时候十位以及个位都已经有了顺序,接着到了百位


101——>1号桶

220——>2号桶

441——>4号桶

283——>2号桶

92  ——>0号桶


我们再次按照桶的顺序进行排序


92    101    220    283    441


此时无需再进行比较,数列已经排序完毕了。


这就是基数排序的步骤。

现在我们一起来看看代码:

#include <stdio.h>#include <stdlib.h>
void sort(int a[], int n);void count(int a[], int n, int exp);
int main(void){ int a[10] = {251, 330, 621, 124, 6, 25, 975, 553, 459, 843}; int i;
sort(a, 10); for (i=0; i<10; i++) printf("%d ", a[i]);
return 0;}
void sort(int a[], int n){ int max, i, exp; max = a[0]; for (i=1; i<10; i++) { if (a[i] > max) max = a[i]; }
for (exp=1; max/exp > 0; exp *= 10) { count(a, n, exp); }}
void count(int a[], int n, int exp){ int *output; output = (int *)malloc(n * sizeof(int)); int i, count[10] = {0};
for (i=0; i<n; i++) { count[(a[i]/exp)%10]++; }
for (i=1; i<10; i++) { count[i] += count[i-1]; }
for (i=n-1; i>=0; i--) { output[count[(a[i]/exp)%10]-1] = a[i]; count[(a[i]/exp)%10]--; } for (i=0; i<n; i++){ a[i] = output[i]; } free(output);}

我们用了两个函数来实现基数排序。

再第一个sort函数里,我们先遍历找到最大值,目的是为了确保最大值的位数是。


接着我们通过循环来调用count函数。在这个循环中变量exp的作用就是指定目前排列的是哪一个分位。


再count函数中,我们先为一个output指针分配了与原来数组同样多的内存空间来存储数据。

同时我们用一个数组count来代表“桶”


首先第一个循环我们通过遍历,来确定当前排序的分位数据有多少个。

第二个循环我们通过累加,让他们每一个数据都代表一个数。

第三个循环值得注意:我们需要从后往前,目的是确保在高分位一样的时候,低分位从小到大排列。因为由于是按照count来选取的数值。所以这个过程必须倒过来执行。(不信的话你可以试试)

三次循环以后,我们再把元素一个个还给a[i],让a数组具有一定的规律。

最后我们释放内存。


这就是基数排序,基数排序通过占用内存来减少花费的时间。你学会了吗?

以上是关于排序专栏:基数排序的主要内容,如果未能解决你的问题,请参考以下文章

数据结构-排序之基数排序(使用java代码实现)

数据结构-排序之基数排序(使用java代码实现)

数据结构-排序之基数排序(使用java代码实现)

基数排序:基数排序中的“组”是啥意思?

算法-java代码实现基数排序

改变基数排序基础?