• PCB 挺有意思的基数排序----C#代码实现


    今天在头条看一个很有意思的排序算法【基数排序】,以前所学习的排序算法都是基于数值对比的方式排序的,而这个算法挺有意思的非常独特。但从网上看到的例子通常是对个位,十位处理,并转为对应的桶索引的方式实现,这里将此算法用C#实现,并以位运算的新方式实现。

     一.代码实现

            static void Main(string[] args)
            {
                //待排序数组
                List<int> arrlist = new List<int>() { 72, 11, 82, 32, 44, 13, 17, 95, 54, 28, 79, 56 };
                int Number = 3;               //基数   网上教材都是基于个位,十位,百位进行运算,这里通过位数计算
                int NumCount = 1 << Number;   //桶数   位数是3那么桶数是8,  位数是4那么桶数是16
                List<List<int>> intList = new List<List<int>>(); //建立好桶 
                for (int i = 0; i < NumCount; i++)
                {
                    intList.Add(new List<int>());
                }
                int LayerCount = 3; //位数划分组数(计算方法:数组最大值为95,对应二进制为:1011111,基数为3的话,可以分为1,011,111; 组数为3)
                //算法实现-----算法复杂度(nxm)
                for (int k = 1; k <= LayerCount; k++) //最大整数最高位数划分组数
                {
                    intList.ForEach(tt => tt.Clear());
                    foreach (var item in arrlist)
                    {
                        int index = item & ((1 << k * Number) - 1); //左移加与位运算 求桶索引   
                        index = index >> (k - 1) * Number;//右移加与运算  求桶索引   
                        intList[index].Add(item);
                    }
                    arrlist.Clear();
                    for (int i = 0; i < NumCount; i++)
                    {
                        for (int j = 0; j <intList[i].Count; j++)
                        {
                            arrlist.Add(intList[i][j]);
                        }
                    }
                }
                //输出
                arrlist.ForEach(tt=>Console.WriteLine(tt));
                Console.ReadKey();
            }

    二.输出排序结果:

    三 .基数排序算法介绍:

    基数排序的两个关键要点:

    (1)基:被排序的元素的“个位”“十位”“百位”,暂且叫“基”,栗子中“基”的个数是2(个位和十位);

    画外音:来自野史,大神可帮忙修正。

    (2)桶:“基”的每一位,都有一个取值范围,栗子中“基”的取值范围是0-9共10种,所以需要10个桶(bucket),来存放被排序的元素;

     

    基数排序的算法步骤为:

    FOR (每一个基) {

    //循环内,以某一个“基”为依据

    第一步:遍历数据集arr,将元素放入对应的桶bucket

    第二步:遍历桶bucket,将元素放回数据集arr

    }

     

    更具体的,对应到上面的栗子,“基”有个位和十位,所以,FOR循环会执行两次。

     

    【第一次:以“个位”为依据】

     

    画外音:上图中标红的部分,个位为“基”。

    第一步:遍历数据集arr,将元素放入对应的桶bucket;

     

     

    操作完成之后,各个桶会变成上面这个样子,即:个位数相同的元素,会在同一个桶里。

     

    第二步:遍历桶bucket,将元素放回数据集arr;

    画外音:需要注意,先入桶的元素要先出桶。

     

    操作完成之后,数据集会变成上面这个样子,即:整体按照个位数排序了。

    画外音:个位数小的在前面,个位数大的在后面。

     

    【第二次:以“十位”为依据】

     

    画外音:上图中标红的部分,十位为“基”。

    第一步:依然遍历数据集arr,将元素放入对应的桶bucket;

     

    操作完成之后,各个桶会变成上面这个样子,即:十位数相同的元素,会在同一个桶里。

     

    第二步:依然遍历桶bucket,将元素放回数据集arr;

     

    操作完成之后,数据集会变成上面这个样子,即:整体按照十位数也排序了。

    画外音:十位数小的在前面,十位数大的在后面。

     

    首次按照个位从小到大,第二次按照十位从小到大,即:排序结束。

     

    神奇不神奇!!!

     

    几个小点:

    (1)基的选取,可以先从个位开始,也可以先从十位开始,结果是一样的;

    (2)基数排序,是一种稳定的排序;

    (3)时间复杂度,可以认为是线性的O(n);

     

  • 相关阅读:
    正则中的顺序环视和逆序环视
    LeetCode 第 27 场双周赛
    LeetCode 每日一题 198. 打家劫舍
    LeetCode 每日一题 974. 和可被 K 整除的子数组
    LeetCode 每日一题 287. 寻找重复数
    LeetCode 每日一题 4. 寻找两个正序数组的中位数
    LeetCode 每日一题 146. LRU缓存机制
    LeetCode 每日一题 105. 从前序与中序遍历序列构造二叉树
    [转]多线程的那点儿事
    LeetCode 每日一题 5. 最长回文子串
  • 原文地址:https://www.cnblogs.com/pcbren/p/9788836.html
Copyright © 2020-2023  润新知