位圖算法的應用

位圖的應用

編程珠璣 Chapter1

位圖位向量圖作爲一個集合,表示的這樣的一個數據結構:

          用字符串 0 1 1 1 0 1 0 0 1 0 0 0 0 1 0 0 0 0 0 0 表示集合 {1,2,3,5,8,13}.

    位圖的應用需要數據有如下的特性:

         1.輸入數據限制在相對較小的範圍內;

         2.數據沒有重複;

         3.除了單一整數外,沒有任何其他關聯數據.

    但很可惜的是,大多數待排序數據沒有這些特性(就是說這些特性在大多數情況下是很難滿足的).

習題1 如果不缺內存,如何使用一個具有庫的語言來實現一種排序算法以表示和排序集合

解題報告:

擁有庫的語言,C/C++/JAVA都是很好的選擇,由於目前只會C++,因此對於我來說別無選擇. 而對於C++,實現排序的庫有太多的選擇,典型的有STL中的stdlib.h中的qsort和algorithm中的sort.對於這兩者的區別,在這裏不想多談(其實我並不清楚,大概瞭解的是stdlib是C的產物,而algorithm的後代,不過,sort在使用上比較簡單).

習題二 如何使用位邏輯運算(例如與、或、移位)來實現位向量

解題報告:

一開始當然沒有想到要用位邏輯運算來實現位向量,而是用十進制來實現(這是理所當然的事)。

用一個一維數組a[10000000]來存儲至多1E7個號碼,考慮整數m,一旦發現這個號碼,根據我們的算法,應當置a[m]=1.

好的,一切看起來都如此完美,簡單的算法,出色的時間效率,差強人意的空間效率.但上機起來就不是這回事了:

但是美好的想法在現實面前是如此的脆弱,這段代碼在運行的時候出錯了,原因是數組越界.好吧,現在我可以承認,數組開到1E7是不現實的,這該如何是好?

現在是時候回到位邏輯運算了,這是一種模仿計算機底層二進制運算的運算方法,十分高效,但是第一次看上去會顯得晦澀難懂,等到將它與十進制運算聯繫起來後,會發現它相當有用.

整個的思想是,a[10000000]顯得太過巨大的原因是每一個元素a[i]只保留了一個bool值或者是一個整型值0或1,如果我們把每一個元素包含的內容擴充,使之保留儘可能多的號碼是否存在的信息,那麼數組範圍會得到明顯的下降.

事實上,我們是用每一個元素表示一個32位的二進制字符串,這樣這個元素可以保留相鄰32個號碼是否存在的信息,數組範圍就下降到10000000/32了.例如對於號碼89256,由於89256 mod 32=2789…8,這樣我們應該置a[2789]中32位字符串的第8位(從低位數起)爲1.

現在問題的關鍵是,如何用位邏輯運算來表示這種操作. 關於位邏輯運算的知識,你應當去參考手頭的C++教材,因爲在這裏我無法講的比教材更好:

重要的是要從十進制運算的思維轉化爲二進制運算,位邏輯運算不過是工具而已.

下面是一個位運算的類:

 

習題三 在你自己的系統上實現位圖排序並度量其運行時間

解題報告:

爲什麼說這個算法時空效率達到極致呢?我們對100萬個不重複的正整數(1000,0000以內)的文件進行測試:

 

系統排序

C++/STL.set

C++/sort

C++/位圖

總時間(s)

89

38

12.6

10.7

計算時間(s)

79

28

2.4

0.5

內存使用(MB)

0.8

70

4

1.25

(本測試數據是在較舊的電腦上測試的,但還是體現性能的差距)
第一行是總時間,第二行的計算時間是總時間減去數據讀取耗時10.2秒。雖然通用C++程序使用內存和CPU時間是專用C++程序(C++位圖)的50倍,但是它的使用僅需要一半的代碼,並能很容易擴展到其他問題上,這也是專用C++程序最大的缺點吧。

 

原文鏈接:http://knightsgang.spaces.live.com/Blog/cns!5536415C9770F9BF!144.entry

發佈了30 篇原創文章 · 獲贊 66 · 訪問量 65萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章