排序 8 - 基数排序

10 篇文章 0 订阅
10 篇文章 0 订阅

参考:

排序 0 - 前言

百度百科:基数排序


基数排序(radix sort)

工作原理

针对 基数 进行排序,找出待排序列表的最大值,判断它的位数,比如 123 的位数为 3,先对个位数进行排序,遍历待排序列表,将个位数相同的值放在一起,即放在编号 0-9 中,排序完成后,按顺序连接 0-9 桶中的值;再对十位数的值进行排序,同样放入 0-9 中;依此类推,遍历所有位数

基数排序又称为 桶子法(bucket sort)

算法思想

有两种不同的排序方式

  • 最低位优先(LSD,least significant digit first)。先从低位数开始,遍历到最高位,每次遍历后都将所有桶中数据连接在一起,最后一次合并所有桶中的数字就是排序结果

    • 问题:用 Python 实现时考虑如何创建 0-910 个桶,如何将数据放入这些桶中
    • 思路:创建一个下标列表,长度为 10,初始化为 0,表示每个桶的数据个数,同时创建一个辅助列表,保存排序结果
  • 最高位优先(MSD,most significant digit first)。先从最高位数开始,遍历到最低位。和 LSD 不同的是,每次遍历后不再连接所有桶中的数据,而是针对单独桶中的数据进行低位排序,最后再合并所有桶中的数据

    • 问题:如何针对桶中数据进行排序
    • 思路:采用递归方法,输入待排序数据和位数

Python 算法实现

# -*- coding: utf-8 -*-

"""
基数排序实现
"""

import random

__author__ = 'zj'


def create_data(leng, min, max):
    """
    创建待排序序列
    :param leng: 序列长度
    :param min: 最小值
    :param max: 最大值
    :return: 列表
    """
    li = range(min, max)
    return random.sample(li, leng)


def radix_sort(li):
    """
    基数排序实现 lsd(least significant digit first) 从小到大排序
    :param li: 待排序列表
    :return: 已排序列表
    """
    m = max(li)  # 获取最大值
    digits = len(str(m))  # 获取位数

    target = 0
    while target < digits:
        idxs = [x * 0 for x in xrange(10)]
        te = []
        for item in li:
            radix = item / 10 ** target % 10
            idxs[radix] += 1
            te.insert(sum(idxs[:radix + 1]) - 1, item)
        target += 1
        li = te

    return li


def radix_sort_v2(li, d=None):
    """
    基数排序实现 msd(most significant digit first)
    :param li: 待排序列表
    :param d:基数,默认为 None
    :return: 已排序列表
    """
    if len(li) == 1:
        return li
    if d is None:
        m = max(li)  # 获取最大值
        d = len(str(m))  # 获取位数
    if d <= 0:
        return li

    idxs = [x * 0 for x in xrange(10)]
    te = []
    for item in li:
        radix = item / 10 ** (d - 1) % 10
        idxs[radix] += 1
        te.insert(sum(idxs[:radix + 1]) - 1, item)

    res = []
    for i in xrange(len(idxs)):
        if idxs[i] != 0:
            sub = te[sum(idxs[:i]): sum(idxs[:i + 1])]
            # print sub
            res.extend(radix_sort_v2(sub, d - 1))
    return res


if __name__ == '__main__':
    da = create_data(20, 0, 160)
    print da
    res = radix_sort(da)
    print res

性能分析

稳定性

基数排序是稳定排序算法

不论是 LSD 还是 MSD,每次遍历不涉及数据交换,所以相同大小的数据的相对位置不会发生改变

时间复杂度

其时间复杂度为 O(d(r+n)),其中 r 为所采取的基数,而 n 为堆数(关键字的个数),d 代表长度

空间复杂度

空间复杂度为 O(rd+n)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值