莊周夢蝶

          生活、程序、未來
             :: 首頁 ::  ::  :: 聚合  :: 管理

          位圖排序

          Posted on 2008-01-07 15:30 dennis 閱讀(3787) 評論(3)  編輯  收藏 所屬分類: 數據結構與算法計算機科學與基礎
              《編程珠璣》第一章第一題就相當的精彩,做個筆記。題目如下:
          輸入:   一個包含n個正整數的文件,每個正整數小于n,n等于10的7次方(一千萬)。并且文件內的正整數沒有重復和關聯數據。

          輸出:  輸入整數的升序排列
           
          約束: 限制在1M左右內存,充足的磁盤空間

              假設整數占32位,1M內存可以存儲大概250000個整數,第一個方法就是采用基于磁盤的合并排序算法,第二個辦法就是將0-9999999切割成40個區間,分40次掃描(10000000/250000),每次讀入250000個在一個區間的整數,并在內存中使用快速排序。書中提出的第三個解決辦法是采用bitmap(或者稱為bit vector)來表示所有數據集合(注意到條件,數據沒有重復),這樣就可以一次性將數據讀入內存,減少了掃描次數。算法的偽代碼如下:
          階段1:初始化一個空集合
               for i=[0,n)
                     bit[i]=0;
          階段2:讀入數據i,并設置bit[i]=1
              for each i in the input file
                     bit[i]=1;
          階段3:輸出排序的結果
             for i=[0,n)
                    if bit[i]==1
                        write i on the output file

          這個算法的時間復雜度在O(n),用c語言寫的版本可以在10秒內完成任務!c語言的源碼在該書主頁上有,這里給一個java的測試版,加上我的理解注釋:

          /**
           * Created by IntelliJ IDEA.
           * User: zhuangxd
           * Date: 2008-1-7
           * Time: 14:30:44
           
          */
          public class BitSortTest {
              
          private static final int BITSPERWORD = 32;  //整數位數
              private static final int SHIFT = 5;
              
          private static final int MASK = 0x1F;  //5位遮蔽 0B11111
              private static final int N = 10000000;
              
          //用int數組來模擬位數組,總計(1 + N / BITSPERWORD)*BITSPERWORD位,足以容納N
              private static int[] a = new int[(1 + N / BITSPERWORD)];

              
          public static void main(String[] args) {
                  bitsort(
          new int[]{11002100009999456778902});
              }

              
          public static void bitsort(int[] array) {
                  
          for (int i = 0; i < N; i++)
                      clr(i);   
          //位數組所有位清0
                  for (int i = 0; i < array.length; i++)
                      set(array[i]);  
          //階段2
                  for (int i = 0; i < N; i++)
                      
          if (test(i))
                          System.out.println(i);
              }

              
          //置a[i>>SHIFT]的第(i & MASK)位為1,也就是位數組的第i位為1
              public static void set(int i) {
                  a[i 
          >> SHIFT] |= (1 << (i & MASK));
              }

              
          //置a[i>>SHIFT]的第(i & MASK)位為0,也就是位數組的第i位為0
              public static void clr(int i) {
                  a[i 
          >> SHIFT] &= ~(1 << (i & MASK));
              }

              
          //測試位數組的第i位是否為1
              public static boolean test(int i) {
                  
          return (a[i >> SHIFT] & (1 << (i & MASK))) == (1 << (i & MASK));
              }
          }




          評論

          # re: 位圖排序[未登錄]  回復  更多評論   

          2008-01-07 20:17 by weidagang2046
          10^7 bit和1M誰更大?

          # re: 位圖排序  回復  更多評論   

          2008-01-08 08:53 by dennis
          1M內存限制只是個粗略的估計,嚴格來講會稍微超過

          # re: 位圖排序  回復  更多評論   

          2008-08-06 00:38 by ee
          good
          主站蜘蛛池模板: 郑州市| 峨眉山市| 伊川县| 横山县| 普洱| 台州市| 仪征市| 集安市| 秦安县| 右玉县| 乳山市| 库车县| 灵石县| 哈尔滨市| 遂平县| 蒲城县| 南和县| 白山市| 东光县| 五台县| 临汾市| 卓尼县| 东城区| 曲靖市| 京山县| 武冈市| 东乡县| 射阳县| 南华县| 台山市| 桂阳县| 庆安县| 城市| 临湘市| 清河县| 平乐县| 荥经县| 阿图什市| 于都县| 大邑县| 五峰|