欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

python實現(xiàn)bitmap數(shù)據(jù)結構詳解

 更新時間:2014年02月17日 10:58:14   作者:  
bitmap是很常用的數(shù)據(jù)結構,比如用于Bloom Filter中,下面是使用python實現(xiàn)bitmap數(shù)據(jù)結構的代碼講解,需要的朋友可以參考下

bitmap是很常用的數(shù)據(jù)結構,比如用于Bloom Filter中;用于無重復整數(shù)的排序等等。bitmap通?;跀?shù)組來實現(xiàn),數(shù)組中每個元素可以看成是一系列二進制數(shù),所有元素組成更大的二進制集合。對于Python來說,整數(shù)類型默認是有符號類型,所以一個整數(shù)的可用位數(shù)為31位。

bitmap實現(xiàn)思路

bitmap是用于對每一位進行操作。舉例來說,一個Python數(shù)組包含4個32位有符號整型,則總共可用位為4 * 31 = 124位。如果要在第90個二進制位上操作,則要先獲取到操作數(shù)組的第幾個元素,再獲取相應的位索引,然后執(zhí)行操作。



上圖所示為一個32位整型,在Python中默認是有符號類型,最高位為符號位,bitmap不能使用它。左邊是高位,右邊是低位,最低位為第0位。

bitmap是用于對每一位進行操作。舉例來說,一個Python數(shù)組包含4個32位有符號整型,則總共可用位為4 * 31 = 124位。如果要在第90個二進制位上操作,則要先獲取到操作數(shù)組的第幾個元素,再獲取相應的位索引,然后執(zhí)行操作。

初始化bitmap

首先需要初始化bitmap。拿90這個整數(shù)來說,因為單個整型只能使用31位,所以90除以31并向上取整則可得知需要幾個數(shù)組元素。代碼如下:

復制代碼 代碼如下:

#!/usr/bin/env python
#coding: utf8

class Bitmap(object):
 def __init__(self, max):
  self.size = int((max + 31 - 1) / 31) #向上取整

if __name__ == '__main__':
 bitmap = Bitmap(90)
 print '需要 %d 個元素。' % bitmap.size

復制代碼 代碼如下:

$ python bitmap.py
需要 3 個元素。


計算在數(shù)組中的索引

計算在數(shù)組中的索引其實是跟之前計算數(shù)組大小是一樣的。只不過之前是對最大數(shù)計算,現(xiàn)在換成任一需要存儲的整數(shù)。但是有一點不同,計算在數(shù)組中的索引是向下取整,所以需要修改calcElemIndex方法的實現(xiàn)。代碼改為如下:

復制代碼 代碼如下:

#!/usr/bin/env python
#coding: utf8

class Bitmap(object):
 def __init__(self, max):
  self.size  = self.calcElemIndex(max, True)
  self.array = [0 for i in range(self.size)]

 def calcElemIndex(self, num, up=False):
  '''up為True則為向上取整, 否則為向下取整'''
  if up:
   return int((num + 31 - 1) / 31) #向上取整
  return num / 31

if __name__ == '__main__':
 bitmap = Bitmap(90)
 print '數(shù)組需要 %d 個元素。' % bitmap.size
 print '47 應存儲在第 %d 個數(shù)組元素上。' % bitmap.calcElemIndex(47)

復制代碼 代碼如下:

$ python bitmap.py
數(shù)組需要 3 個元素。
47 應存儲在第 1 個數(shù)組元素上。

所以獲取最大整數(shù)很重要,否則有可能創(chuàng)建的數(shù)組容納不下某些數(shù)據(jù)。

計算在數(shù)組元素中的位索引

數(shù)組元素中的位索引可以通過取模運算來得到。令需存儲的整數(shù)跟31取模即可得到位索引。代碼改為如下:

復制代碼 代碼如下:

#!/usr/bin/env python
#coding: utf8

class Bitmap(object):
 def __init__(self, max):
  self.size  = self.calcElemIndex(max, True)
  self.array = [0 for i in range(self.size)]

 def calcElemIndex(self, num, up=False):
  '''up為True則為向上取整, 否則為向下取整'''
  if up:
   return int((num + 31 - 1) / 31) #向上取整
  return num / 31

 def calcBitIndex(self, num):
  return num % 31

if __name__ == '__main__':
 bitmap = Bitmap(90)
 print '數(shù)組需要 %d 個元素。' % bitmap.size
 print '47 應存儲在第 %d 個數(shù)組元素上。' % bitmap.calcElemIndex(47)
 print '47 應存儲在第 %d 個數(shù)組元素的第 %d 位上。' % (bitmap.calcElemIndex(47), bitmap.calcBitIndex(47),)

別忘了是從第0位算起哦。

置1操作

二進制位默認是0,將某位置1則表示在此位存儲了數(shù)據(jù)。代碼改為如下:

復制代碼 代碼如下:

#!/usr/bin/env python
#coding: utf8

class Bitmap(object):
 def __init__(self, max):
  self.size  = self.calcElemIndex(max, True)
  self.array = [0 for i in range(self.size)]

 def calcElemIndex(self, num, up=False):
  '''up為True則為向上取整, 否則為向下取整'''
  if up:
   return int((num + 31 - 1) / 31) #向上取整
  return num / 31

 def calcBitIndex(self, num):
  return num % 31

 def set(self, num):
  elemIndex = self.calcElemIndex(num)
  byteIndex = self.calcBitIndex(num)
  elem      = self.array[elemIndex]
  self.array[elemIndex] = elem | (1 << byteIndex)

if __name__ == '__main__':
 bitmap = Bitmap(90)
 bitmap.set(0)
 print bitmap.array

因為從第0位算起,所以如需要存儲0,則需要把第0位置1。

清0操作

將某位置0,也即丟棄已存儲的數(shù)據(jù)。代碼如下:

復制代碼 代碼如下:

#!/usr/bin/env python
#coding: utf8

class Bitmap(object):
 def __init__(self, max):
  self.size  = self.calcElemIndex(max, True)
  self.array = [0 for i in range(self.size)]

 def calcElemIndex(self, num, up=False):
  '''up為True則為向上取整, 否則為向下取整'''
  if up:
   return int((num + 31 - 1) / 31) #向上取整
  return num / 31

 def calcBitIndex(self, num):
  return num % 31

 def set(self, num):
  elemIndex = self.calcElemIndex(num)
  byteIndex = self.calcBitIndex(num)
  elem      = self.array[elemIndex]
  self.array[elemIndex] = elem | (1 << byteIndex)

 def clean(self, i):
  elemIndex = self.calcElemIndex(i)
  byteIndex = self.calcBitIndex(i)
  elem      = self.array[elemIndex]
  self.array[elemIndex] = elem & (~(1 << byteIndex))

if __name__ == '__main__':
 bitmap = Bitmap(87)
 bitmap.set(0)
 bitmap.set(34)
 print bitmap.array
 bitmap.clean(0)
 print bitmap.array
 bitmap.clean(34)
 print bitmap.array

清0和置1是互反操作。

測試某位是否為1

判斷某位是否為1是為了取出之前所存儲的數(shù)據(jù)。代碼如下:

復制代碼 代碼如下:

#!/usr/bin/env python
#coding: utf8

class Bitmap(object):
 def __init__(self, max):
  self.size  = self.calcElemIndex(max, True)
  self.array = [0 for i in range(self.size)]

 def calcElemIndex(self, num, up=False):
  '''up為True則為向上取整, 否則為向下取整'''
  if up:
   return int((num + 31 - 1) / 31) #向上取整
  return num / 31

 def calcBitIndex(self, num):
  return num % 31

 def set(self, num):
  elemIndex = self.calcElemIndex(num)
  byteIndex = self.calcBitIndex(num)
  elem      = self.array[elemIndex]
  self.array[elemIndex] = elem | (1 << byteIndex)

 def clean(self, i):
  elemIndex = self.calcElemIndex(i)
  byteIndex = self.calcBitIndex(i)
  elem      = self.array[elemIndex]
  self.array[elemIndex] = elem & (~(1 << byteIndex))

 def test(self, i):
  elemIndex = self.calcElemIndex(i)
  byteIndex = self.calcBitIndex(i)
  if self.array[elemIndex] & (1 << byteIndex):
   return True
  return False

if __name__ == '__main__':
 bitmap = Bitmap(90)
 bitmap.set(0)
 print bitmap.array
 print bitmap.test(0)
 bitmap.set(1)
 print bitmap.test(1)
 print bitmap.test(2)
 bitmap.clean(1)
 print bitmap.test(1)

復制代碼 代碼如下:

$ python bitmap.py
[1, 0, 0]
True
True
False
False


接下來實現(xiàn)一個不重復數(shù)組的排序。已知一個無序非負整數(shù)數(shù)組的最大元素為879,請對其自然排序。代碼如下:

復制代碼 代碼如下:

#!/usr/bin/env python
#coding: utf8

class Bitmap(object):
 def __init__(self, max):
  self.size  = self.calcElemIndex(max, True)
  self.array = [0 for i in range(self.size)]

 def calcElemIndex(self, num, up=False):
  '''up為True則為向上取整, 否則為向下取整'''
  if up:
   return int((num + 31 - 1) / 31) #向上取整
  return num / 31

 def calcBitIndex(self, num):
  return num % 31

 def set(self, num):
  elemIndex = self.calcElemIndex(num)
  byteIndex = self.calcBitIndex(num)
  elem      = self.array[elemIndex]
  self.array[elemIndex] = elem | (1 << byteIndex)

 def clean(self, i):
  elemIndex = self.calcElemIndex(i)
  byteIndex = self.calcBitIndex(i)
  elem      = self.array[elemIndex]
  self.array[elemIndex] = elem & (~(1 << byteIndex))

 def test(self, i):
  elemIndex = self.calcElemIndex(i)
  byteIndex = self.calcBitIndex(i)
  if self.array[elemIndex] & (1 << byteIndex):
   return True
  return False

if __name__ == '__main__':
 MAX = 879
 suffle_array = [45, 2, 78, 35, 67, 90, 879, 0, 340, 123, 46]
 result       = []
 bitmap = Bitmap(MAX)
 for num in suffle_array:
  bitmap.set(num)

 for i in range(MAX + 1):
  if bitmap.test(i):
   result.append(i)

 print '原始數(shù)組為:    %s' % suffle_array
 print '排序后的數(shù)組為: %s' % result

bitmap實現(xiàn)了,則利用其進行排序就非常簡單了。其它語言也同樣可以實現(xiàn)bitmap,但對于靜態(tài)類型語言來說,比如C/Golang這樣的語言,因為可以直接聲明無符號整型,所以可用位就變成32位,只需將上述代碼中的31改成32即可,這點請大家注意。

相關文章

最新評論