經典算法:位圖排序

最近發現一個有趣的排序算法,通過位圖來完成排序。位圖排序其實就是基數排序,只不過位圖排序的下標是比特位。

問題描述

輸入:一個最多包含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.pswp.cn/news/276595.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/276595.shtml
英文地址,請注明出處:http://en.pswp.cn/news/276595.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

PHP中刪除目錄的三種方法

原文鏈接&#xff1a;http://www.chinaz.com/program/2008/1022/41645.shtml PHP中刪除目錄的三種方法 1、遞規法&#xff1a;利用遞歸一層一層的刪。 deleteDir(&#xff04;dir) { if (rmdir(&#xff04;dir)false && is_dir(&#xff04;dir)) {if (&#xff04;d…

b樣條曲面繪制 opengl_CAD制圖軟件中如何利用EXCEL輸入坐標繪制曲線?

當在使用浩辰CAD制圖軟件繪制圖紙的過程中&#xff0c;經常要繪制由多個坐標點連接成的曲線時&#xff0c;有什么方便快捷的方法嗎&#xff1f;那當然是有的。利用EXCEL表格保存數據并與CAD制圖軟件巧妙地結合起來&#xff0c;就能很容易地畫出曲線。下面給大家詳細介紹一下吧&…

根據進程名殺掉進程

foreach (System.Diagnostics.Process pro in System.Diagnostics.Process.GetProcesses()){if (pro.ProcessName "Bss"){pro.Kill();break;}} 轉載于:https://www.cnblogs.com/wolfcool/archive/2009/04/17/1438284.html

JavaScript 操作 Cookie

從事web開發也有些日子了&#xff0c;cookie 是個啥差不多能說明白&#xff0c;可是實際自己一上手操作就是得去搜索(你們懂的)&#xff0c;結果被鄙視了...所以就寫一篇博文做為自己的學習筆記&#xff0c;嘿嘿&#xff0c;博客的好處在此體現出來了。 什么是 Cookie “cookie…

阿里云服務器購買該如何選擇?阿里云服務器購買步驟流程介紹...

很多第一次購買阿里云服務器&#xff0c;不知該如何選擇適合自已的服務器。其實購買阿里云服務器&#xff0c;主要是根據自已網站的流量來決定的。如果網站流量不大&#xff0c;一天只有幾百ip&#xff0c;一般選擇1核cpu&#xff0c;1G內存&#xff0c;1MB帶寬就可以用了&…

python 切片_全面解讀Python高級特性切片

大家好&#xff0c;歡迎來到Crossin的編程教室&#xff01;眾所周知&#xff0c;我們可以通過索引值(或稱下標)來查找序列類型(如字符串、列表、元組…)中的單個元素&#xff0c;那么&#xff0c;如果要獲取一個索引區間的元素該怎么辦呢&#xff1f;切片(slice)就是一種截取索…

十大Web網站漏洞掃描工具

原文鏈接&#xff1a;http://zhumeng8337797.blog.163.com/blog/static/1007689142012819111054920/ 1. Nikto 這是一個開源的Web服務器掃描程序&#xff0c;它可以對Web服務器的多種項目(包括3500個潛在的危險文件/CGI&#xff0c;以及超過900個服務器版本&#xff0c;還有250…

讀書筆記(06) - 語法基礎 - JavaScript高級程序設計

寫在開頭 本篇是小紅書筆記的第六篇&#xff0c;也許你會奇怪第六篇筆記才寫語法基礎&#xff0c;筆者是不是穿越了。 答案當然是沒有&#xff0c;筆者在此分享自己的閱讀心得&#xff0c;不少人翻書都是從頭開始&#xff0c;結果永遠就只在前幾章。對此&#xff0c;筆者換了隨…

最近做了一個安裝包的安裝流程圖

最近到做安裝包的詳細設計。下圖是安裝包的流程圖&#xff0c;如果有什么意見和建議&#xff0c;希望大家給我留言&#xff0c;大家以前討論 轉載于:https://www.cnblogs.com/zengshengping815/archive/2009/04/22/1441319.html

如何使用Nikto漏洞掃描工具檢測網站安全

轉載鏈接&#xff1a;http://www.linuxidc.com/Linux/2011-02/32000.htm 【51CTO.com 獨家特稿】隨著信息技術的發展&#xff0c;網絡應用越來越廣泛&#xff0c;很多企業單位都依靠網站來運營&#xff0c;正因為業務的不斷提升和應用&#xff0c;致使網站的安全性顯得越來越重…

什么是區塊鏈預言機(BlockChain Oracle)

預言機 Oracle 是區塊鏈中非常重要的一個功能&#xff0c;但我發現很少有人討論&#xff0c;也可能很多人對此并不了解。而網上關于預言機的文章很少&#xff0c;很多也沒有講明白&#xff0c;甚至有些還是錯誤的。所以我整理了一篇詳細的文章&#xff0c;分享給大家&#xff0…

idea tomcat啟動成功但是訪問方面都是404_IDEA相關配置【集成Tomcatamp;項目部署】...

“知其然知其所以然”始終是Brick我學習新興技術的出發點&#xff0c;那么咱們來聊聊以下幾個問題問題1&#xff1a;在編寫完web項目之后&#xff0c;我們怎么才能運行項目呢&#xff1f;--需要部署項目到Tomcat上。問題2&#xff1a;部署項目到Tomcat服務器有多少種方式&#…

程序員素質面試題

技術題做完后&#xff0c;先檢查技術是否合格&#xff0c;技術合格的并非就一定是合適人選&#xff0c;還要做素質面試。 如下是小y出的面試題&#xff1a; &#xff08;上進心&#xff09;1.你的職業規劃是怎樣的&#xff0c;未來兩年想朝哪個方向發展&#xff1f; &#xff0…

用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 …

Linux源碼安裝mysql 5.6.12(cmake編譯)

轉載鏈接&#xff1a;http://www.2cto.com/database/201307/229260.html Linux源碼安裝mysql 5.6.12&#xff08;cmake編譯&#xff09;1.安裝make編譯器(默認系統自帶)下載地址&#xff1a;http://www.gnu.org/software/make/[c-sharp] tar zxvf make-3.82.tar.gz cd make-3.…

云棲專輯 | 阿里開發者們的第6個感悟:享受折磨

2015年12月20日&#xff0c;云棲社區上線。2018年12月20日&#xff0c;云棲社區3歲。阿里巴巴常說“晴天修屋頂”。在我們看來&#xff0c;寒冬中&#xff0c;最值得投資的是學習&#xff0c;是增厚的知識儲備。所以社區特別制作了這個專輯——分享給開發者們20個彌足珍貴的成長…

python刪除數據庫的數據完整代碼_利用python操作小程序云數據庫實現簡單的增刪改查...

不止python&#xff0c;你可以利用任何語言那實現通過http請求來操作你自己的小程序云數據庫了背景也是在最近吧&#xff0c;小程序更新了云開發 HTTP API 文檔&#xff0c;提供了小程序外訪問云開發資源的能力&#xff0c;使用 HTTP API 開發者可在已有服務器上訪問云資源&…