經典演算法題每日演練——第十一題 Bitmap演算法

來源:互聯網
上載者:User

     在所有具有效能最佳化的資料結構中,我想大家使用最多的就是hash表,是的,在具有定位尋找上具有O(1)的常量時間,多麼的簡潔優美,

但是在特定的場合下:

①:對10億個不重複的整數進行排序。

②:找出10億個數字中重複的數字。

當然我只有普通的伺服器,就算2G的記憶體吧,在這種情境下,我們該如何更好的挑選資料結構和演算法呢?

 

一:問題分析

     這年頭,大牛們寫的排序演算法也就那麼幾個,首先我們算下放在記憶體中要多少G: (10億 * 32)/(1024*1024*1024*8)=3.6G,可憐

的2G記憶體直接爆掉,所以各種神馬的資料結構都玩不起來了,當然使用外排序還是可以解決問題的,由於要走IO所以暫時剔除,因為我們

要玩高效能,無望後我們想想可不可以在二進位位上做些手腳?  

比如我要對{1,5,7,2}這四個byte類型的數字做排序,該怎麼做呢?我們知道byte是佔8個bit位,其實我們可以將數組中的值作為bit位的

key,value用”0,1“來標識該key是否出現過?下面看圖:

我們精彩的看到,我們的數組值都已經作為byte中的key了,最後我只要遍曆對應的bit位是否為1就可以了,那麼自然就成有序數組了。

可能有人說,我增加一個13怎麼辦?很簡單,一個位元組可以存放8個數,那我只要兩個byte就可以解決問題了。

可以看出我將一個線性數組變成了一個bit位的二維矩陣,最終我們需要的空間僅僅是:3.6G/32=0.1G即可,要注意的是bitmap排序不

是N的,而是取決於待排序數組中的最大值,在實際應用上關係也不大,比如我開10個線程去讀byte數組,那麼複雜度為:O(Max/10)。

 

二:代碼

  我想bitmap的思想大家都清楚了,這一次又讓我們見證了二進位的魅力,當然這些移位都是位元運算的工作了,熟悉了你就玩轉了。

1:Clear方法(將數組的所有bit位置0)

   比如要將當前4對應的bit位置0的話,只需要1左移4位取反與B[0] & 即可。

 1         #region 初始化所用的bit位為0 2         /// <summary> 3         /// 初始化所用的bit位為0 4         /// </summary> 5         /// <param name="i"></param> 6         static void Clear(byte i) 7         { 8             //相當於 i%8 的功能 9             var shift = i & 0x07;10 11             //計算應該放數組的下標12             var arrindex = i >> 3;13 14             //則將當前byte中的指定bit位取0,&後其他對方數組bit位必然不變,這就是 1 的妙用15             var bitPos = ~(1 << shift);16 17             //將數組中的指定bit位置一  “& 操作”18             a[arrindex] &= (byte)(bitPos);19         }20         #endregion

 

2:Add方法(將bit置1操作)

  同樣也很簡單,要將當前4對應的bit位置1的話,只需要1左移4位與B[0] | 即可。

 1 #region 設定相應bit位上為1 2         /// <summary> 3         /// 設定相應bit位上為1 4         /// </summary> 5         /// <param name="i"></param> 6         static void Add(byte i) 7         { 8             //相當於 i%8 的功能 9             var shift = i & 0x07;10 11             //計算應該放數組的下標12             var arrindex = i >> 3;13 14             //將byte中的 1 移動到i位15             var bitPos = 1 << shift;16 17             //將數組中的指定bit位置一  “| 操作”18             a[arrindex] |= (byte)bitPos;19         }20         #endregion

 

2:Contain方法(判斷當前bit位是否是1)

    如果看懂了Clear和Add,我相信最後一個方法已經不成問題了。

 1         #region 判斷當前的x在數組的位中是否存在 2         /// <summary> 3         ///判斷當前的x在數組的位中是否存在 4         /// </summary> 5         /// <param name="i"></param> 6         /// <returns></returns> 7         static bool Contain(byte i) 8         { 9             var j = a[i >> 3] & (1 << (i & 0x07));10 11             if (j == 0)12                 return false;13             return true;14         }15         #endregion

最後上總的代碼:

View Code

 1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Diagnostics; 6 using System.Threading; 7 using System.IO; 8  9 namespace ConsoleApplication210 {11     public class Program12     {13         static byte n = 7;14 15         static byte[] a;16 17         public static void Main()18         {19             //節省空間的做法20             a = new byte[(n >> 3) + 1];21 22             for (byte i = 0; i < n; i++)23                 Clear(i);24 25             Add(4);26             Console.WriteLine("插入4成功!");27 28             var s = Contain(4);29 30             Console.WriteLine("當前是否包含4:{0}", s);31 32             s = Contain(5);33 34             Console.WriteLine("當前是否包含5:{0}", s);35 36             Console.Read();37         }38 39         #region 初始化所用的bit位為040         /// <summary>41         /// 初始化所用的bit位為042         /// </summary>43         /// <param name="i"></param>44         static void Clear(byte i)45         {46             //相當於 i%8 的功能47             var shift = i & 0x07;48 49             //計算應該放數組的下標50             var arrindex = i >> 3;51 52             //則將當前byte中的指定bit位取0,&後其他對方數組bit位必然不變,這就是 1 的妙用53             var bitPos = ~(1 << shift);54 55             //將數組中的指定bit位置一  “& 操作”56             a[arrindex] &= (byte)(bitPos);57         }58         #endregion59 60         #region 設定相應bit位上為161         /// <summary>62         /// 設定相應bit位上為163         /// </summary>64         /// <param name="i"></param>65         static void Add(byte i)66         {67             //相當於 i%8 的功能68             var shift = i & 0x07;69 70             //計算應該放數組的下標71             var arrindex = i >> 3;72 73             //將byte中的 1 移動到i位74             var bitPos = 1 << shift;75 76             //將數組中的指定bit位置一  “| 操作”77             a[arrindex] |= (byte)bitPos;78         }79         #endregion80 81         #region 判斷當前的x在數組的位中是否存在82         /// <summary>83         ///判斷當前的x在數組的位中是否存在84         /// </summary>85         /// <param name="i"></param>86         /// <returns></returns>87         static bool Contain(byte i)88         {89             var j = a[i >> 3] & (1 << (i & 0x07));90 91             if (j == 0)92                 return false;93             return true;94         }95         #endregion96     }97 }

 

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.