经典算法:位图排序

最近发现一个有趣的排序算法,通过位图来完成排序。位图排序其实就是基数排序,只不过位图排序的下标是比特位。

问题描述

输入:一个最多包含n个正整数的文件,每个数都小于n,其中n=10^7。如果在输入文件中有任何正数重复出现就是致命错误。没有其他数据与该正数相关联。

输出:按升序排列的输入正数的列表。

约束:最多有1MB的内存空间可用,有充足的磁盘存储空间可用。运行时间最多几分钟,运行时间为10秒就不需要进一步优化。

一种解决方法是把整个文件分成 40 份,每份 250000 个整数,一个整形占 4 字节,刚好可以在 1MB 的空间里操作。在第一趟遍历中,将大小为 0 至 249999 之间的任何整数都读入内存中,并对这 250000 个整数进行排序,写到输出文件中。第二趟遍历排序 250000 至 499999 之间的整数,依此类推,到第 40 趟结束,我们已经完成了排序。这种排序的代价是要读取输入文件 40 次。

而另一种解决方法就是使用位图排序。

位图排序

一般编程语言的 int 类型所占空间大于等于 4 字节,共 32 位。我们可以用这 32 位来表示 0 到 31 的的数字。假设有一个集合为 {0, 3, 5},在位图里表示就是 0000101001 ,这里省去了前面 22 个 0 。

一个 32 位的 int 数可以表示 32 个数字。假设总共有 100 个数,我们只需 (100/32)+1=4 个 int 整数就可以表示这 100 个数,0~31 储存在第 1 个 int 数,32~63 储存在第 2 个 int 数。

这样,存储所有数值需要的 int 个数为 10^7 / 32 = 312500, 需要总内存为312500 * 4 / 1024 / 1024 = 1.25M, 1M内存限制跑两趟就可以完成排序。

位图排序实现

我们可以用 3 个函数来实现位图。

函数1:将所有的位都置为0,从而将集合初始化为空。

函数2:通过读入文件中的每个整数来建立集合,将每个对应的位置都置为 1。

函数3:检验每一位,如果该为为1,就输出对应的整数。

位图操作类

class BitMap:# maxval        最大值# bitsperword   一个int数的位数# shift         能表示 bitsperword 需要的位数, 5 位可以表示 32 这个数# mask          能表示 bitsperword 需要的位数,用二进制表示def __init__(self, maxval, bitsperword=32, shift=5, mask=0b11111):self.bitsperword = bitsperwordself.shift = shiftself.mask = mask# 初始化位图,相当于函数1self.x = [0 for i in range(1 + int(maxval / bitsperword))]def set(self, i):# i>>self.shift 操作等同于 i 除于 2^self.shift# i & self.mask 操作等同于 i 对 2^self.shift 求余# 1 << n 等同于 1 * 2^nself.x[i >> self.shift] |= (1 << (i & self.mask))# 如果某位上有数,就返回 truedef test(self, i):return self.x[i >> self.shift] & (1 << (i & self.mask))

设置

>>> bit = BitMap(500)
>>> bit.x
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]>>> bit.x
[2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
# self.x[0] 的二进制为 10>>> bit.set(4)
>>> bit.x
[18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
# self.x[0] 的二进制为 10010

输出位对应的值

>>> print (bit.test(1))
2

排序实现

def bitSort(lists, maxval):sortLists = []bit = BitMap(maxval)for val in lists:bit.set(val)for i in range(maxval):if bit.test(i):sortLists.append(i)return sortLists

排序测试

>>> lists = [5, 2, 6, 8, 10, 22, 25, 44, 29, 36, 40, 3, 4, 1, 20, 27, 37]
>>> print (bitSort(lists, max(lists)))
[1, 2, 3, 4, 5, 6, 8, 10, 20, 22, 25, 27, 29, 36, 37, 40]

位图操作的优点非常明显,内存占用非常低,非常适合在内存有限时使用。

完整代码

#!/bin/python
# -*- coding:utf-8 -*-class BitMap:# maxval        最大值# bitsperword   一个int数的位数# shift         能表示 bitsperword 需要的位数, 5 位可以表示 32 这个数# mask          能表示 bitsperword 需要的位数,用二进制表示def __init__(self, maxval, bitsperword=32, shift=5, mask=0b11111):self.bitsperword = bitsperwordself.shift = shiftself.mask = mask# 初始化位图,相当于函数1self.x = [0 for i in range(1 + int(maxval / bitsperword))]def set(self, i):# i>>self.shift 操作等同于 i 除于 2^self.shift# i & self.mask 操作等同于 i 对 2^self.shift 求余# 1 << n 等同于 1 * 2^nself.x[i >> self.shift] |= (1 << (i & self.mask))# 如果某位上有数,就返回 truedef test(self, i):return self.x[i >> self.shift] & (1 << (i & self.mask))def bitSort(lists, maxval):sortLists = []bit = BitMap(maxval)for val in lists:bit.set(val)for i in range(maxval):if bit.test(i):sortLists.append(i)return sortListsif __name__ == '__main__':lists = [5, 2, 6, 8, 10, 22, 25, 44, 29, 36, 40, 3, 4, 1, 20, 27, 37]print (bitSort(lists, max(lists)))
参考: 编程珠玑

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/276595.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

b样条曲面绘制 opengl_CAD制图软件中如何利用EXCEL输入坐标绘制曲线?

当在使用浩辰CAD制图软件绘制图纸的过程中&#xff0c;经常要绘制由多个坐标点连接成的曲线时&#xff0c;有什么方便快捷的方法吗&#xff1f;那当然是有的。利用EXCEL表格保存数据并与CAD制图软件巧妙地结合起来&#xff0c;就能很容易地画出曲线。下面给大家详细介绍一下吧&…

阿里云服务器购买该如何选择?阿里云服务器购买步骤流程介绍...

很多第一次购买阿里云服务器&#xff0c;不知该如何选择适合自已的服务器。其实购买阿里云服务器&#xff0c;主要是根据自已网站的流量来决定的。如果网站流量不大&#xff0c;一天只有几百ip&#xff0c;一般选择1核cpu&#xff0c;1G内存&#xff0c;1MB带宽就可以用了&…

python 切片_全面解读Python高级特性切片

大家好&#xff0c;欢迎来到Crossin的编程教室&#xff01;众所周知&#xff0c;我们可以通过索引值(或称下标)来查找序列类型(如字符串、列表、元组…)中的单个元素&#xff0c;那么&#xff0c;如果要获取一个索引区间的元素该怎么办呢&#xff1f;切片(slice)就是一种截取索…

读书笔记(06) - 语法基础 - JavaScript高级程序设计

写在开头 本篇是小红书笔记的第六篇&#xff0c;也许你会奇怪第六篇笔记才写语法基础&#xff0c;笔者是不是穿越了。 答案当然是没有&#xff0c;笔者在此分享自己的阅读心得&#xff0c;不少人翻书都是从头开始&#xff0c;结果永远就只在前几章。对此&#xff0c;笔者换了随…

最近做了一个安装包的安装流程图

最近到做安装包的详细设计。下图是安装包的流程图&#xff0c;如果有什么意见和建议&#xff0c;希望大家给我留言&#xff0c;大家以前讨论 转载于:https://www.cnblogs.com/zengshengping815/archive/2009/04/22/1441319.html

idea tomcat启动成功但是访问方面都是404_IDEA相关配置【集成Tomcatamp;项目部署】...

“知其然知其所以然”始终是Brick我学习新兴技术的出发点&#xff0c;那么咱们来聊聊以下几个问题问题1&#xff1a;在编写完web项目之后&#xff0c;我们怎么才能运行项目呢&#xff1f;--需要部署项目到Tomcat上。问题2&#xff1a;部署项目到Tomcat服务器有多少种方式&#…

用U盘或移动硬盘安装Windows7 (超简单制作Win7安装U盘方法)

转载链接&#xff1a;http://www.iplaysoft.com/win7-usb-dvd-download-tool.html 最近很多人想要安装 Windows7 &#xff0c;下载回去后的ISO镜像文件很多人都是使用 Nero 或 IMGBurn 等工具刻录成光盘来安装的。但实际上&#xff0c;不需刻盘安装Win7的方法还是有不少的。…

安装pywin32时:ImportError: DLL load failed: %1 不是有效的 Win32 应用程序和 DLL load failed...

问题一&#xff1a;ImportError: DLL load failed: %1 不是有效的 Win32 应用程序 import pywinapi报错:ImportError: DLL load failed: %1 不是有效的 Win32 应用程序 原因&#xff1a;与python版本不对应 pypi官网上下载whl文件,我的python 版本为27 下载第一个后安装 下载文…

pointcut注解_Spring AOP使用指南,详细了解AOP相关注解

Spring AOP 指导教程什么是Spring AOP spring aop可以在spring构建的系统中使用面向切面编程。当然Spring Boot也是基于Spring构建的。使用AOP可以实现诸如事务&#xff0c;日志以及安全校验等通过切面统一完成的任务。他可以通过简单的注解方式实现在方法执行前后来执行你自己…

C# 实现FTP上传与下载

向FTP服务器下载文件的简单实例 Codestring filePath "d:\\"; string fileName "lhking.txt"; //文件下载之后要保存的路径和文件名 FtpWebRequest reqFTP; try { FileStream outputStream …

云栖专辑 | 阿里开发者们的第6个感悟:享受折磨

2015年12月20日&#xff0c;云栖社区上线。2018年12月20日&#xff0c;云栖社区3岁。阿里巴巴常说“晴天修屋顶”。在我们看来&#xff0c;寒冬中&#xff0c;最值得投资的是学习&#xff0c;是增厚的知识储备。所以社区特别制作了这个专辑——分享给开发者们20个弥足珍贵的成长…

加密文件忘记密码怎么解密_MyBatis 配置文件 用户密码加密存储

properties配置文件一般是使用properties保存配置文件内容,然后在mybatis配置文件中进行读取在resource文件下新建db.properties文件内容如下# 数据库配置文件 driver com.mysql.cj.jdbc.Driver url jdbc:mysql:// /mybatis username password 然后,接着把文件放入源码包…

科技前沿智能创新 2019北京智能家居 全屋智能博览会

2019北京智能家居大型展览会 2019北京全屋智能家居博览会报道布展&#xff1a;2019年6月26日-27日 展会开幕&#xff1a;2019年6月28日上午9&#xff1a;00时展会交易&#xff1a;2019年6月28日-30日 展会撤展&#xff1a;2019年6月30日下午14&#xff1a;00时 展览会在北京市政…

java 容器_我也来聊聊,JAVA容器与迭代器

java的容器与迭代器是一个老生常谈的话题了。本文旨在与大家分享一些关于双向链表与迭代器的运用小技巧&#xff0c;并希望本篇文章的内容能够在项目中给你带来帮助。Stack与LinkedListStack是一个LIFO(后进先出)的容器。若要在java中定义一个Stack应该怎么办&#xff1f;也许你…

apache目录的访问控制

转载链接&#xff1a;http://blog.sina.com.cn/s/blog_7be8a2150100trml.html 1.根目录的访问控制 DocumentRoot "/var/www/html" <Directory /> Options FollowSymLinks AllowOverride None </Directory> 解释一下&#xff1a; <Dir…

广东高院驳回快播对深圳市场监管局2.6亿罚款案上诉

雷帝网 乐天 12月29日报道据广东高院官方微信消息&#xff0c;广东省高级人民法院对深圳市快播科技有限公司&#xff08;简称快播&#xff09;诉深圳市市场监督管理局&#xff08;简称市场监管局&#xff09;著作权行政处罚纠纷案作出终审宣判&#xff0c;驳回上诉&#xff0c;…

shell 练习3

1、编写脚本/root/bin/createuser.sh&#xff0c;实现如下功能&#xff1a;使用一个用户名做为参数&#xff0c;如果指定参数的用户存在&#xff0c;就显示其存在&#xff0c;否则添加之&#xff1b;显示添加的用户的id号等信息2、编写脚本/root/bin/yesorno.sh&#xff0c;提示…

两个数组结果相减_学点算法(三)——数组归并排序

今天来学习归并排序算法。分而治之归并算法的核心思想是分而治之&#xff0c;就是将大问题转化为小问题&#xff0c;在解决小问题的基础上&#xff0c;再去解决大问题。将这句话套用到排序中&#xff0c;就是将一个大的待排序区间分为小的待排序区间&#xff0c;对小的排序区间…

ASP记数器

这两天有好几个老的ASP网站要改&#xff0c;其中有要求加记数器&#xff0c;为图简单&#xff0c;就用文本文件的形式存储记数。以前用ifream的形式嵌入&#xff0c;不能很好的控制记数器显示的风格&#xff0c;现在改进了一下&#xff0c;可以很好的与嵌入板块风格结合了。把做…

[转] DevExpress 第三方控件汉化的全部代码和使用方法

DevExpress.XtraEditors.Controls 此控件包中包含的控件最多&#xff0c;包括文本框&#xff0c;下拉列表&#xff0c;按钮&#xff0c;等等 DevExpress.XtraGrid 网格 DevExpress.XtraBars 菜单栏 和 工具栏 DevExpress.XtraNavBar 导航条 DevExpress.XtraPr…