python之基数排序的实现


Posted in Python onJuly 26, 2021

算法思想

        插入\交换\选择\归并类的排序算法都需要通过比较关键字的大小来完成排序.因为存在两两比较所以这一类的排序方法在最好情况下能达到的复杂度是O(n*logn),如快速排序\堆排序\归并排序.在一般情况下和最坏情况下复杂度更是达到O(n**2).

        为了降低复杂度,就有牛人想出了分配收集排序方法,稍后分析它的时间复杂度能到达O(n),

而基数排序就是一种典型的搜集分配收集排序方法.基数排序时一种借助于多关键字排序的思想对单关键字排序的方法.其基本思想是通过对排序记录进行若干趟(有几个关键字就几趟)"分配"与"收集"来实现排序.

        如:

       1. 对整数排序,建立编号0-9(10进制的基数)10个桶,用于装对应位为编号的记录.先将待排序序列分配按'个位'数字分配到10各桶中,然后将桶按从小到大的顺序串接起来.

        2.将上一步的结果再按'十位''数字分配到10各桶中,然后将桶按从小到大的顺序串接起来.

        3. 将上一步的结果再按'百位''数字分配到10各桶中,然后将桶按从小到大的顺序串接起来.

        4.如果还有千位\万位.重复以上步骤,直到完成最高位的分配与收集,排序结束.

动图示例:(转自菜鸟教程:1.10 基数排序 | 菜鸟教程 (runoob.com))

python之基数排序的实现 

算法实现

1.本实现借助队列的数据结构,所以先来定义一个队列

# Bradley N. Miller, David L. Ranum
# Introduction to Data Structures and Algorithms in Python
# Copyright 2005
# 
#queue.py
 
class Queue:
    def __init__(self):
        self.items = []
 
    def isEmpty(self):
        return self.items == []
 
    def enqueue(self, item):
        self.items.insert(0,item)
 
    def dequeue(self):
        return self.items.pop()
 
    def size(self):
        return len(self.items)

2.处理输入数据

将一个列表作为输入,将每一个记录处理为具有相同位数的字符串(用字符串类型时为了方便处理)

def inDataProcess(lis):
    max_lengh = max([len(lis[i]) for i in range(len(lis))])  # 查询记录中最长的字符串
    return [x.zfill(max_lengh) for x in lis]  # 将每一个记录都通过添加前导0的方式转化为一样的长度

3.基数排序主函数

def radixSort(seq:list):
    source_data = inDataProcess(seq)  # 输入处理
    res = []  # 用于保存结果列表
    big_queue = Queue()  # 用于转化的队列
    for ele in source_data:
        big_queue.enqueue(ele)
 
    for i in range(len(source_data[0])-1,-1,-1):
        buckets = []  # 用于保存每一趟的10各基数桶
        for num  in range(10):  # 建立10个基数桶
            bucket = Queue()
            buckets.append(bucket)
        # 在基数桶中插入数据
        while not big_queue.isEmpty():
            currentEle = big_queue.dequeue()  # 大队列中出队一个元素
            index = int(currentEle[i])  # 根据元素对应位上的值添加进对应的基数桶中
            buckets[index].enqueue(currentEle)
 
        # 把基数桶串联起来
        new_big_queue = Queue()
        for bucket in buckets:
            while not bucket.isEmpty():
                out = bucket.dequeue()
                new_big_queue.enqueue(out)
                # print(new_big_queue.size())
        # 修改big_queue
        big_queue = new_big_queue
    # 将大队列中的元素保存到结果列表中
    while not big_queue.isEmpty():
        res.append(big_queue.dequeue().lstrip('0'))  # 利用lstrip('0')去掉前导0
    return res

4.测试及结果

if __name__ == '__main__':
 
    lis = [20,101,39,431,58,600,8,4,999,634,157,199,208,138,389,691,400,932,856,843,401,923]
    lis = [str(i) for i in lis]
    print(radixSort(lis))
    ''' 结果>>>['4', '8', '20', '39', '58', '101', '138', '157', '199', '208', '389', '400', '401', '431', '600', '634', '691',
    '843', '856', '923', '932', '999']'''

算法分析

1)时间复杂度
对于n个记录(假设每个记录含d个关键字,每个关键字的取值范围为rd个值)进行链式基数排序时,每一趟分配的时间复杂度为O(n),每一趟收集的时间复杂度为O(rd),整个排序需进行d趟分配和收集,所以时间复杂度为O(d(n+rd))。
(2)空间复杂度
所需辅助空间为2rd个队列指针,另外由于需用链表做存储结构,则相对于其他以顺序结构存储记录的排序方法而言,还增加了n个指针域的空间,所以空间复杂度为O(n+rd)。

算法的特征

(1)是稳定排序。
(2)可用于链式结构,也可用于顺序结构。
(3)时间复杂度可以突破基于关键字比较一类方法的下界O(nlog2n),达到O(n)。
(4)基数排序使用条件有严格的要求:需要知道各级关键字的主次关系和各级关键字的取值范围。


ref: 

1.严蔚敏等<<数据结构C语言版(第二版)>>

2.Bradley N. Miller, David L. Ranum <<Introduction to Data Structures and Algorithms in Python>>

到此这篇关于python之基数排序的实现的文章就介绍到这了,更多相关python之基数排序内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
python中for语句简单遍历数据的方法
May 07 Python
在Python中操作列表之List.append()方法的使用
May 20 Python
Python 实现简单的电话本功能
Aug 09 Python
2018年Python值得关注的开源库、工具和开发者(总结篇)
Jan 04 Python
python自动截取需要区域,进行图像识别的方法
May 17 Python
python机器人运动范围问题的解答
Apr 29 Python
python2.7 安装pip的方法步骤(管用)
May 05 Python
Python简易版图书管理系统
Aug 12 Python
Django REST框架创建一个简单的Api实例讲解
Nov 05 Python
python爬虫实例之获取动漫截图
May 31 Python
Scrapy模拟登录赶集网的实现代码
Jul 07 Python
Python通过fnmatch模块实现文件名匹配
Sep 30 Python
python之PySide2安装使用及QT Designer UI设计案例教程
python代码实现备忘录案例讲解
Jul 26 #Python
python之django路由和视图案例教程
Jul 26 #Python
OpenCV图像变换之傅里叶变换的一些应用
Python类方法总结讲解
pandas数值排序的实现实例
Jul 25 #Python
python非标准时间的转换
Jul 25 #Python
You might like
php删除与复制文件夹及其文件夹下所有文件的实现代码
2013/01/23 PHP
解析php二分法查找数组是否包含某一元素
2013/05/23 PHP
PHP生成不同颜色、不同大小的tag标签函数
2013/09/23 PHP
javascript 子窗体父窗体相互传值方法
2010/05/31 Javascript
jQuery渐变发光导航菜单的实例代码
2013/03/27 Javascript
鼠标焦点离开文本框时验证的js代码
2013/07/19 Javascript
javascript跨域的4种方法和原理详解
2014/04/08 Javascript
JavaScript中匿名、命名函数的性能测试
2014/09/04 Javascript
javascript中Array()数组函数详解
2015/08/23 Javascript
返回函数的JavaScript函数
2016/06/14 Javascript
M2实现Nodejs项目自动部署的方法步骤
2019/05/05 NodeJs
在layui中layer弹出层点击事件无效的解决方法
2019/09/05 Javascript
原生javascript实现类似vue的数据绑定功能示例【观察者模式】
2020/02/24 Javascript
基于javascript处理nginx请求过程详解
2020/07/07 Javascript
JS获取当前时间戳方法解析
2020/08/29 Javascript
适用于 Vue 的播放器组件Vue-Video-Player操作
2020/11/16 Javascript
Python获取当前时间的方法
2014/01/14 Python
Python 文件处理注意事项总结
2017/04/10 Python
Python+tkinter使用80行代码实现一个计算器实例
2018/01/16 Python
教你使用python实现微信每天给女朋友说晚安
2018/03/23 Python
python pandas中DataFrame类型数据操作函数的方法
2018/04/08 Python
Python2.7环境Flask框架安装简明教程【已测试】
2018/07/13 Python
Python分析彩票记录并预测中奖号码过程详解
2019/07/09 Python
Python数据库小程序源代码
2019/09/15 Python
python 装饰器重要在哪
2021/02/14 Python
深入剖析webstorage[html5的本地数据处理]
2016/07/11 HTML / CSS
使用canvas对多图片拼合并导出图片的方法
2018/08/28 HTML / CSS
澳大利亚领先的皮肤诊所:Skin Matrix(抗衰老、痤疮专家、药妆护肤)
2018/05/20 全球购物
理工大学毕业生自荐信
2013/11/01 职场文书
外贸学院会计专业应届生求职信
2013/11/14 职场文书
财务总监管理岗位职责
2014/03/08 职场文书
法人代表证明书格式
2014/10/01 职场文书
2015年八一建军节慰问信
2015/03/23 职场文书
停电通知范文
2015/04/16 职场文书
Ajax 的初步实现(使用vscode+node.js+express框架)
2021/06/18 Javascript
HTML5页面打开微信小程序功能实现
2022/09/23 HTML / CSS