算法系列之--Javascript和Kotlin的基数排序算法(原)

Posted 工程师阿杜

tags:

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

上一节我们学习了堆算法,这一节来学习基数算法,算法系列文章目录在这里


介绍


        之前的所有算法都是基于比较的算法, 而基数排序算法不同,他不是基于比较的,而是将整形的数据拆分为 不同的位数分别进行排序,适用于 数列中的数字相差不大的情况,其具体操作步骤如下:
        1. 将所有数字按照最后一位数的内容放入map中,比如对于[25,1,3,21,23,5,9]这个序列,放入map后内容应该是:key=1:[1,21],key=3:[3,23],key=5:[25,5],key=9:9
        2. 然后将map中的数字按照map的key从小到大依次放入列表中,此时列表内容就变为[1,21,3,23,25,5,9]
        3. 重复上述1的步骤,只不过这一次比较十位上的数字,没有十位的要用0补位,比如此时就会生成key=0:[1,3,5,9],key=2:[21,23,25]
        4. 重复2步骤,此时序列变为[1,3,5,9,21,23,25],即完成排序


效率


        平均时间复杂度O(n*k)
        最坏时间复杂度O(n*k)
        最优时间复杂度O(n*k)

        这里的 k就是数列中最大数的位数,比如1234这个数字其位数为4


源码


Js源码


let list = [123456, 4, 8, 23, 5, 13, 323, 1, 9, 2, 3]
let max = 0
for (let i = 0; i < list.length; i++) 
    if (list[i] > max) 
        //找到当前序列最大数
        max = list[i]
    

//通过最大数找到最大数的位数
let maxDigit = max.toString().length
//dev是当前要计算的位数,mod是当前要计算的位数的高一位
for (let i = 0, mod = 10, dev = 1, counter = []; i < maxDigit; i++, dev *= 10, mod *= 10) 
    for (let j = 0; j < list.length; j++) 
        // 取出某个数的第mod位的值
        // 比如数字123,123%100=23,23继续计算23/10=2,最终拿到123的中间位数字
        let bucket = parseInt((list[j] % mod) / dev)
        if (counter[bucket] == null) 
            counter[bucket] = []
        
        //按照当前位数作为key以此存入counter的map中
        counter[bucket].push(list[j])
    
    let pos = 0
    for (let j = 0; j < counter.length; j++) 
        let value = null
        if (counter[j] != null) 
            while ((value = counter[j].shift()) != null) 
                //依次将counter中的值放入列表中
                //第一次经过进--出的操作就对个位数字进行了排序
                //第二次经过进--出的操作就对十位进行了排序
                //经过上面两次排序,就达到了个位+十位的综合排序,也就完成了两位数字的整体排序
                list[pos++] = value
            
        
    



Kotlin源码


private var ARRAY_COUNT = 100000
/*
 * 获取随机数列
 */
private fun getSortList(): IntArray 
    var sortList = IntArray(ARRAY_COUNT)
    var ra = Random()
    for (i in sortList.indices) 
        sortList[i] = ra.nextInt(ARRAY_COUNT * 10)
    
    return sortList

/*
 * 交换数列元素
 */
private fun swapByIndex(list: IntArray, x: Int, y: Int) 
    var temp = list[x]
    list[x] = list[y]
    list[y] = temp

/*
* 基数排序
*/ 
private fun jishu() 
    var sortList = getSortList()
    //寻找当前序列中的最大值,目的是计算最大的位数
    var max = 0
    for (i in 0..sortList.size - 1) 
        if (sortList[i] > max) 
            //找到当前序列最大数
            max = sortList[i]
        
    
    //通过最大数找到最大数的位数
    var maxDigit = max.toString().length
    var mod = 10
    var dev = 1
    for (i in 0 until maxDigit) 
        var counter = mutableMapOf<Int, ArrayList<Int>>()
        for (j in 0 until sortList.size) 
            // 取出某个数的第mod位的值
            // 比如数字123,123%100=23,23继续计算23/10=2,最终拿到123的中间位数字
            var bucket = (sortList[j] % mod) / dev
            //按照当前位数作为key以此存入counter的map中
            if (counter[bucket] == null) 
                counter[bucket] = ArrayList<Int>()
            
            counter[bucket]?.add(sortList[j])
        
        var pos = 0
        for (i in 0..9) 
            //这里一定使用0--9的索引,因为对counter来说,里面的map的key只能是这个组合,并且一定要按照从0到9的顺序弹出
            counter[i]?.forEach 
                //依次将counter中的值放入列表中
                //第一次经过进--出的操作就对个位数字进行了排序
                //第二次经过进--出的操作就对十位进行了排序
                //经过上面两次排序,就达到了个位+十位的综合排序,也就完成了两位数字的整体排序
                sortList[pos++] = it
            
        
        dev *= 10
        mod *= 10
    


        下一节我们来学习一种该算法系列中最为高效的排序算法----快速算法

         各个算法的Kotlini版本性能测试结果请看算法系列之--Kotlin的算法实战比较》 


以上是关于算法系列之--Javascript和Kotlin的基数排序算法(原)的主要内容,如果未能解决你的问题,请参考以下文章

算法系列之--Javascript和Kotlin的冒泡算法(原)

算法系列之--Javascript和Kotlin的基数排序算法(原)

算法系列之--Javascript和Kotlin的堆排序算法(原)

算法系列之--Javascript和Kotlin的希尔排序算法(原)

算法系列之--Javascript和Kotlin的快速排序算法(原)

算法系列之--Kotlin的算法实战比较(原)