每日一算法|基数排序---第十一天

Posted 江小湖资源分享平台

tags:

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

基数排序




每日一算法|基数排序---第十一天

算法

原理


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

基数相对于前面的排序稍微复杂些,原理与桶排序类似,可以分为高位优先和低位优先。我们这里讲低位优先,高位一样的理解就好。

基数排序适合对那些位数差别比较大的数组适用性会好些。以整数排序为例,主要思想是将整数按位数划分,准备 10 个桶,代表 0 - 9,根据整数个位数字的数值将元素放入对应的桶中,之后按照输入赋值到原序列中,依次对十位、百位等进行同样的操作,最终就完成了排序的操作。

我们要找出最大值,判断它是多少位的我们就循环多少次。

接下来举例说明一下,假设有一组数据{3,1,18,11,28,45,23,50,30},最大位数为两位,所以只要循环两次就行了。

第一步:准备0~9的10个空桶(分配空间),把上面的数据按个位分别放到对应的空桶(空间)中,放完后,将空桶中的数据按顺序放回原来的数组中去,这样第一趟就完成了。

第二步:十位把数组放到对应空桶(空间)中,十位没有的按0来算;全部放好后再按顺序放回到原来数组中,此时,数列排序完毕。

如果还有更多位数的数,按上面的方法依次把位数往前推就好。


总结一下:

1.找最大值,判断位数。

2.位数=循环次数

3.分配空间

4.使用二维数组存储元素在桶中的位置:一个是余数位,一个是在在桶中第几个位置。




每日一算法|基数排序---第十一天


C语言


每日一算法|基数排序---第十一天

#include<stdio.h>
 
#define Max_ 10      //数组个数
#define RADIX_10 10    //整形排序
#define KEYNUM_31 10     //关键字个数,这里为整形位数
 
// 打印结果
void Show(int  arr[], int n)
{
    int i;
    for ( i=0; i<n; i++ )
        printf("%d  ", arr[i]);
    printf("\n");
}
 
// 找到num的从低到高的第pos位的数据
int GetNumInPos(int num,int pos)
{
    int temp = 1;
    for (int i = 0; i < pos - 1; i++)
        temp *= 10;
    
    return (num / temp) % 10;
}
 
 
//基数排序  pDataArray 无序数组;iDataNum为无序数据个数
void RadixSort(int* pDataArray, int iDataNum)
{
    int *radixArrays[RADIX_10];    //分别为0~9的序列空间
    for (int i = 0; i < 10; i++)
    {
        radixArrays[i] = (int *)malloc(sizeof(int) * (iDataNum + 1));
        radixArrays[i][0] = 0;    //index为0处记录这组数据的个数
    }
    
    for (int pos = 1; pos <= KEYNUM_31; pos++)    //从个位开始到31位
    {
        for (int i = 0; i < iDataNum; i++)    //分配过程
        {
            int num = GetNumInPos(pDataArray[i], pos);
            int index = ++radixArrays[num][0];
            radixArrays[num][index] = pDataArray[i];
        }
        
        for (int i = 0, j =0; i < RADIX_10; i++)    //收集
        {
            for (int k = 1; k <= radixArrays[i][0]; k++)
                pDataArray[j++] = radixArrays[i][k];
            radixArrays[i][0] = 0;    //复位
        }
    }
}
 
int main()
{   //测试数据
    int arr_test[Max_] = { 3,1,18,11,28,45,23,50,30 };
    //排序前数组序列
    Show( arr_test, Max_ );
    RadixSort( arr_test, Max_);
    //排序后数组序列
    Show( arr_test, Max_ );
    return 0;
}



Java



每日一算法|基数排序---第十一天

// 基数排序
public static void radixSort(int[] arr) {
    if (arr == null || arr.length < 2) {
        return;
    }
    radixSort(arr, 0, arr.length - 1, maxbits(arr));
}
    
// 计算最大位数
public static int maxbits(int[] arr) {
    int max = Integer.MIN_VALUE;
    for (int i = 0; i < arr.length; i++) {
        max = Math.max(max, arr[i]);
    }
    int res = 0;
    while (max != 0) {
        res++;
        max /= 10;
    }
    return res;
}

// 基数排序
public static void radixSort(int[] arr, int begin, int end, int digit) {
    final int radix = 10;
    int i = 0, j = 0;
    int[] count = new int[radix];
    int[] bucket = new int[end - begin + 1];
    // 依次遍历每个位数
    for (int d = 1; d <= digit; d++) {
        for (i = 0; i < radix; i++) {
            count[i] = 0;
        }
            
        // 统计数量
        for (i = begin; i <= end; i++) {
            j = getDigit(arr[i], d);
            count[j]++;
        }
            
        // 计算位置
        for (i = 1; i < radix; i++) {
            count[i] = count[i] + count[i - 1];
        }
            
        // 记录到对应位置
        for (i = end; i >= begin; i--) {
            j = getDigit(arr[i], d);
            bucket[count[j] - 1] = arr[i];
            count[j]--;
        }
        for (i = begin, j = 0; i <= end; i++, j++) {
            arr[i] = bucket[j];
        }
    }
}

// 获取位数数值
public static int getDigit(int x, int d) {
    return ((x / ((int) Math.pow(10, d - 1))) % 10);
}




Python



def RadixSort(a):
    i = 0                                             #初始为个位排序
    n = 1                                           #最小的位数置为1(包含0)
    max_num = max(a)                       #得到带排序数组中最大数
    while max_num > 10**n:              #得到最大数是几位数
        n += 1
    while i < n:
        bucket = {}                             #用字典构建桶
        for x in range(10):
            bucket.setdefault(x, [])    #将每个桶置空
        for x in a:                               #对每一位进行排序
            radix =int((x / (10**i)) % 10)   #得到每位的基数
            bucket[radix].append(x) #将对应的数组元素加入到相应位基数的桶中
        j = 0
        for k in range(10):
            if len(bucket[k]) != 0:       #若桶不为空
                for y in bucket[k]:         #将该桶中每个元素
                    a[j] = y                       #放回到数组中
                    j += 1
        i += 1

if __name__ == '__main__':
    a = [3,1,18,11,28,45,23,50,30]
    print("Before sorting...")
    print("---------------------------------------------------------------")
    print(a)
    print("---------------------------------------------------------------")
    RadixSort(a)
    print("After sorting...")
    print("---------------------------------------------------------------")
    print(a)
    print("---------------------------------------------------------------")



总结:排序算法到这里就讲完了,总共十大排序算法,当然还有一些其他的排序算法,这里就不发了。之后会做一个总结,对比一下10大经典排序算法各个方面的区别、优劣等。

         再之后的算法,也是一些比较经典的算法,还有蓝桥杯的一些试题解析(当然,看得懂就发,看不懂就算了(手动狗头.jpg))。



以上是关于每日一算法|基数排序---第十一天的主要内容,如果未能解决你的问题,请参考以下文章

每日一算法|桶排序---第十天

每日一算法|计数排序---第九天

每日一算法|直接插入排序---第五天

C语言每日一练——第161天:冒泡排序算法

冲刺大厂每日算法&面试题,动态规划21天——第十一天

每日算法&面试题,大厂特训二十八天——第十一天(数组)