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);

 

 

posted @ 2018-10-14 23:46  pcbren  阅读(995)  评论(0编辑  收藏  举报