[从头学数学] 第253节 Python实现数据结构:比特集(BitSet)
来源:互联网 发布:韩国人看中国知乎 编辑:程序博客网 时间:2024/05/17 06:38
剧情提要:
阿伟看到了一本比较有趣的书,是关于《计算几何》的,2008年由北清派出版。很好奇
它里面讲了些什么,就来看看啦。
正剧开始:
星历2016年08月01日 10:17:09, 银河系厄尔斯星球中华帝国江南行省。
Java中有现成的类,可以直接使用:
彩蛋:
阿伟看到了一本比较有趣的书,是关于《计算几何》的,2008年由北清派出版。很好奇
它里面讲了些什么,就来看看啦。
正剧开始:
星历2016年08月01日 10:17:09, 银河系厄尔斯星球中华帝国江南行省。
[工程师阿伟]正在和[机器小伟]一起研究[计算几何]]。
Python的实现:
<span style="font-size:18px;">#### @usage 比特集# @author mw# @date 2016年08月01日 星期一 08:06:58 # @param# @return####class BitSet(object): # from low to high "00000001 00000010 00000011", the array is [1, 2, 3] def __init__(self, capacity = 64): #"B"类型相当于 C 语言的 unsigned char, 即占用1byte(8位),所以size大小设置为8 self.unit_size = 8 self.unit_count = abs(math.floor((capacity + self.unit_size - 1) / self.unit_size)); self.capacity = capacity self.arr = array.array("B", [0] * self.unit_count) def any(self): #是否存在置为 1 的位 for a in self.arr: if a != 0: return True return False def all(self): #是否所有位都为 1, 即是否存在置为 0 的位 t = (1 << self.unit_size) - 1 for a in self.arr: if (a & t) != t: return False return True def none(self): #是否所有位都为 0,即是否不存在置为 1 的位 for a in self.arr: if a != 0: return False return True #所有位为零为真 def isEmpty(self): return self.none(); #至少一位为1,返回真 def intersects(self): return self.any(); #位的数量 def length(): return self.size(); def __len__(): return self.size(); def size(self): #所有位的个数 return self.unit_count * self.unit_size def count(self): #置为 1 的位的个数 c = 0 for a in self.arr: while a > 0: if a & 1: c += 1 a = a>>1 return c def get(self, pos): #获取第 pos 位的值 index = int(pos / self.unit_size) offset = (self.unit_size - (pos - index * self.unit_size) - 1) % self.unit_size return (self.arr[index] >> offset) & 1 #寻找下一个零位 def nextClearBit(self, startIndex = 0): for i in range(startIndex+1, self.size()): if self.get(i) == 0: return i; return -1; #寻找下一个非零位 def nextSetBit(self, startIndex = 0): for i in range(startIndex+1, self.size()): if self.get(i) == 1: return i; return -1; def test(self, pos): #判断第 pos 位的值是否为 1 if self.get(pos): return True return False def set(self, pos=-1): #设置第 pos 位的值为 1,若 pos 为 -1, 则所有位都置为 1 if pos >= 0: index = int(pos / self.unit_size) offset = (self.unit_size - (pos - index * self.unit_size) - 1) % self.unit_size self.arr[index] = (self.arr[index]) | (1 << offset) else: t = (1 << self.unit_size) - 1 for i in range(self.unit_count): self.arr[i] = self.arr[i] | t def reset(self, pos=-1): #设置第 pos 位的值为 0,若 pos 为 -1, 则所有位都置为 0 if pos >= 0: index = int(pos / self.unit_size) offset = (self.unit_size - (pos - index * self.unit_size) - 1) % self.unit_size x = (1 << offset) self.arr[index] = (self.arr[index]) & (~x) else: for i in range(self.unit_count): self.arr[i] = 0 #所有位清零 def clear(self): self.reset(-1); # def __getitem__(self, idx): if idx < 0 or idx >= self.size(): raise IndexError("index out of range."); return self.get(idx); def __setitem__(self, idx, val): if idx < 0 or idx >= self.size(): raise IndexError("index out of range."); if (val == 0): self.reset(idx); elif(val == 1): self.set(idx); #非操作 def flip(self, pos=-1): #把第 pos 位的值取反,若 pos 为 -1, 则所有位都取反 if pos >= 0: if self.get(pos): self.reset(pos) else: self.set(pos) else: for i in range(self.unit_count): self.arr[i] = ~self.arr[i] + (1 << self.unit_size) #两个bitset的按位与操作 def andOp(self, otherbit): if type(self) != type(otherbit): raise TypeError("and Op undefined for " + str(type(self)) + " + " + str(type(other))) size_1 = self.size(); size_2 = otherbit.size(); minsize = min(size_1, size_2); #如果比特集是从高位到低位排列,而操作应该是低位对齐 #所以应该是逆序迭代,但这种方式在两个比特集位数不等时会有问题 #所以还是默认比特集是小头序,即低字节先读取 #这样这个类设置数据时就是默认把低位设满 for i in range(minsize): a = self.get(i); b = otherbit.get(i); if (a & b == 1): self.set(i); else: self.reset(i); #两个bitset的按位或操作 def orOp(self, otherbit): if type(self) != type(otherbit): raise TypeError("or Op undefined for " + str(type(self)) + " + " + str(type(other))) size_1 = self.size(); size_2 = otherbit.size(); minsize = min(size_1, size_2); #如果比特集是从高位到低位排列,而操作应该是低位对齐 #所以应该是逆序迭代,但这种方式在两个比特集位数不等时会有问题 #所以还是默认比特集是小头序,即低字节先读取 #这样这个类设置数据时就是默认把低位设满 for i in range(minsize): a = self.get(i); b = otherbit.get(i); if (a | b == 1): self.set(i); else: self.reset(i); #两个bitset的按位异或操作 def xorOp(self, otherbit): if type(self) != type(otherbit): raise TypeError("xor Op undefined for " + str(type(self)) + " + " + str(type(other))) size_1 = self.size(); size_2 = otherbit.size(); minsize = min(size_1, size_2); #如果比特集是从高位到低位排列,而操作应该是低位对齐 #所以应该是逆序迭代,但这种方式在两个比特集位数不等时会有问题 #所以还是默认比特集是小头序,即低字节先读取 #这样这个类设置数据时就是默认把低位设满 for i in range(minsize): a = self.get(i); b = otherbit.get(i); if (a != b): self.set(i); else: self.reset(i); #浅拷贝,重复调用BitSet中对象 def clone(self, otherbit): self.unit_size = otherbit.unit_size; self.unit_count = otherbit.unit_count; self.capacity = otherbit.capacity; self.arr = otherbit.arr; #比特集信息显示 def binstr(self): b = "" for a in self.arr: t = bin(a) b += "0" * (self.unit_size - len(t) + 2) + t + "," return "[" + b.replace("0b", "").strip(",") + "]" def show(self): return self.arr #类对象的hash码 def hashCode(self): #return hash(str(self.show())); return hash(self);</span>
用例1:
<span style="font-size:18px;">def main(): #计时开始 startTime = time.clock(); b = BitSet(20) print("size=", b.size()) print("binstr=", b.binstr(), b.show()) # Set first block test b.set(0) print("b.set(0), binstr=", b.binstr(), b.show()) b.reset() b.set(1) print("b.set(1), binstr=", b.binstr(), b.show()) # Set second block test b.reset() b.set(7) print("b.set(7), binstr=", b.binstr(), b.show()) b.reset() b.set(8) print("b.set(8), binstr=", b.binstr(), b.show()) b.reset() b.set(9) print("b.set(9), binstr=", b.binstr(), b.show()) # any test print("\nany() test...") b.reset() print(b.any()) b.set(0) print(b.any()) b.set() print(b.any()) # all test print("\nall() test...") b.reset() print(b.all()) b.set(0) print(b.all()) b.set() print(b.all()) # none test print("\nnone() test...") b.reset() print(b.none()) b.set(0) print(b.none()) b.set() print(b.none()) print("\nflip() test...") b.reset() print(b.binstr()) b.flip() print(b.binstr()) b.reset(1) print(b.binstr()) b.flip() print(b.binstr()) #计时结束 endTime = time.clock(); #打印结果 print('操作用时:{0:.3e} s'.format(endTime-startTime));>>> size= 24binstr= [00000000,00000000,00000000] array('B', [0, 0, 0])b.set(0), binstr= [10000000,00000000,00000000] array('B', [128, 0, 0])b.set(1), binstr= [01000000,00000000,00000000] array('B', [64, 0, 0])b.set(7), binstr= [00000001,00000000,00000000] array('B', [1, 0, 0])b.set(8), binstr= [00000000,10000000,00000000] array('B', [0, 128, 0])b.set(9), binstr= [00000000,01000000,00000000] array('B', [0, 64, 0])any() test...FalseTrueTrueall() test...FalseFalseTruenone() test...TrueFalseFalseflip() test...[00000000,00000000,00000000][11111111,11111111,11111111][10111111,11111111,11111111][01000000,00000000,00000000]操作用时:9.676e-02 s>>> </span>
<span style="font-size:18px;">def main(): #计时开始 startTime = time.clock(); b_1 = BitSet(16) b_2 = BitSet(16) for i in range(16): if (i%2 == 0): b_1.set(i); if (i%5 != 0): b_2.set(i); print("b_1: ", b_1.binstr(), b_1.show()); print("b_2: ", b_2.binstr(), b_2.show()); #AND操作 b_2.andOp(b_1); print("after and, b_2 = ", b_2.binstr(), b_2.show()); #OR操作 b_2.orOp(b_1); print("after or, b_2 = ", b_2.binstr(), b_2.show()); #XOR操作 b_2.xorOp(b_1); print("after xor, b_2 = ", b_2.binstr(), b_2.show()); #clone操作 b_3 = BitSet(8); b_3.clone(b_2); print(b_3.binstr(), b_3.show()); #XOR操作 b_2.xorOp(b_1); print("after xor, b_2 = ", b_2.binstr(), b_2.show()); print(b_3.binstr(), b_3.show()); print(b_2.hashCode(), b_3.hashCode()); b_3.clone(b_1); print(b_1.hashCode(), b_3.hashCode()); print(b_1.show()); print(b_3.binstr(), b_3.nextSetBit(5)); #计时结束 endTime = time.clock(); #打印结果 print('操作用时:{0:.3e} s'.format(endTime-startTime));>>> b_1: [10101010,10101010] array('B', [170, 170])b_2: [01111011,11011110] array('B', [123, 222])after and, b_2 = [00101010,10001010] array('B', [42, 138])after or, b_2 = [10101010,10101010] array('B', [170, 170])after xor, b_2 = [00000000,00000000] array('B', [0, 0])[00000000,00000000] array('B', [0, 0])after xor, b_2 = [10101010,10101010] array('B', [170, 170])[10101010,10101010] array('B', [170, 170])1094709 10853711094705 1085371array('B', [170, 170])[10101010,10101010] 6操作用时:6.627e-02 s</span>
Java中有现成的类,可以直接使用:
<span style="font-size:18px;">import java.util.BitSet;public class BitSetDemo { public static void main(String args[]) { BitSet bits1 = new BitSet(16); BitSet bits2 = new BitSet(16); // set some bits for(int i=0; i<16; i++) { if((i%2) == 0) bits1.set(i); if((i%5) != 0) bits2.set(i); } System.out.println("Initial pattern in bits1: "); System.out.println(bits1); System.out.println("Initial pattern in bits2: "); System.out.println(bits2); // AND bits bits2.and(bits1); System.out.println("bits2 AND bits1: "); System.out.println(bits2); // OR bits bits2.or(bits1); System.out.println("bits2 OR bits1: "); System.out.println(bits2); // XOR bits bits2.xor(bits1); System.out.println("bits2 XOR bits1: "); System.out.println(bits2); }}//结果:Initial pattern in bits1:{0, 2, 4, 6, 8, 10, 12, 14}Initial pattern in bits2:{1, 2, 3, 4, 6, 7, 8, 9, 11, 12, 13, 14}bits2 AND bits1:{2, 4, 6, 8, 12, 14}bits2 OR bits1:{0, 2, 4, 6, 8, 10, 12, 14}bits2 XOR bits1:{}</span>
彩蛋:
本节到此结束,欲知后事如何,请看下回分解。
0 0
- [从头学数学] 第253节 Python实现数据结构:比特集(BitSet)
- [从头学数学] 第244节 Python实现数据结构:列表
- [从头学数学] 第245节 Python实现数据结构:排序
- [从头学数学] 第246节 Python实现数据结构:链表
- [从头学数学] 第247节 Python实现数据结构:栈
- [从头学数学] 第248节 Python实现数据结构:队列
- [从头学数学] 第249节 Python实现数据结构:集合(HashSet)
- [从头学数学] 第250节 Python实现数据结构:映射(HashMap, Dict)
- [从头学数学] 第251节 Python实现数据结构:二叉查找树
- [从头学数学] 第252节 Python实现数据结构:图(Graph)
- [从头学数学] 第254节 Python实现数据结构:bloom Filter
- [从头学数学] 第255节 Python实现数据结构:字典树(Trie)
- [从头学数学] 第256节 Python实现数据结构:堆(Heap)
- [从头学数学] 第257节 Python实现数据结构:平衡二叉树(AVL)
- [从头学数学] 第258节 Python实现数据结构:伸展树(splay tree)
- [从头学数学] 第259节 Python实现数据结构:平衡多路搜索树(B-Tree)
- [从头学数学] 第260节 Python实现数据结构:B+树
- [从头学数学] 第261节 Python实现数据结构:红黑树(RB Tree)
- 栈实验之回文串判定
- Java review--NIO
- Android百度地图开发(一)之初体验
- DP为王——动态规划法学习笔记
- UE4 调节面板参数问题
- [从头学数学] 第253节 Python实现数据结构:比特集(BitSet)
- 算法6_二叉树遍历
- js对象继承
- 目前市面上流行的几种VR头盔设备介绍
- Servlet3.0实现的简单mvc框架
- IOS和H5混合开发
- Java连接程序数据源
- unity 全屏
- 关于C语言字符串初始化问题的探讨