高级农民
- 积分
- 2723
- 大米
- 颗
- 鳄梨
- 个
- 水井
- 尺
- 蓝莓
- 颗
- 萝卜
- 根
- 小米
- 粒
- 学分
- 个
- 注册时间
- 2017-6-18
- 最后登录
- 1970-1-1
|
糊了一个简易实现,不过元素数量上10^5 ~ 10^6之后就性能爆炸了...
- class TreeNode:
- def __init__(self, slots = None, links = None):
- self.slots = slots or []
- self.links = links or [None]
- def getKey(self, pos):
- return self.slots[pos][0]
- def insertSlot(self, pos, slot, link, degree):
- self.slots.insert(pos, slot)
- self.links.insert(pos, link)
- sibling = popup = None
- if len(self.slots) > degree * 2:
- # Split
- sibling = TreeNode(self.slots[:degree], self.links[:degree+1])
- popup = self.slots[degree]
- self.slots = self.slots[-degree:]
- self.links = self.links[-degree-1:]
- return (slot, sibling, popup)
- # B Tree.
- class TreeMap:
- def __init__(self, degree = 8):
- self.degree = degree
- self.root = TreeNode()
- self.size = 0
- def __setitem__(self, key, value):
- slot = self._locateSlot([], self.root, key, True)
- slot[1] = value
- if not slot[2]:
- slot[2] = True
- self.size += 1
- def __getitem__(self, key):
- slot = self._locateSlot([], self.root, key, False)
- if slot is None or not slot[2]:
- raise Exception('key "' + str(key) + '" does not exist')
- return slot[1]
- def __len__(self):
- return self.size
- def pop(self, key):
- # Mark as deleted
- slot = self._locateSlot([], self.root, key, False)
- if slot is not None and slot[2]:
- slot[2] = False
- self.size -= 1
- return slot[1]
- return None
- def range(self, lower_bound, upper_bound):
- for slot in self._traverse(self.root, lower_bound, upper_bound):
- if slot[2]:
- yield (slot[0], slot[1])
- def _traverse(self, node, lower_bound, upper_bound):
- size = len(node.slots)
- begin = next(i for i in range(size+1) if i == size or node.getKey(i) >= lower_bound)
- for i in range(begin, size+1):
- if node.links[i] is not None:
- for slot in self._traverse(node.links[i], lower_bound, upper_bound):
- yield slot
- if i == size or node.getKey(i) > upper_bound:
- break
- yield node.slots[i]
- def _locateSlot(self, ancestors, node, key, insert):
- size = len(node.slots)
- pivot = next(i for i in range(size + 1) if i == size or key <= node.getKey(i))
- if pivot != size and node.getKey(pivot) == key:
- return node.slots[pivot]
- child = node.links[pivot]
- ancestors.append((node, pivot))
- return self._locateSlot(ancestors, child, key, insert) if child is not None \
- else self._insertSlot(ancestors, [key, None, False], None) if insert \
- else None
- def _insertSlot(self, ancestors, slot, link):
- node, pos = ancestors.pop()
- slot, sibling, popup = node.insertSlot(pos, slot, link, self.degree)
- if sibling is not None:
- if len(ancestors) == 0:
- self.root = TreeNode([popup], [sibling, node])
- else:
- self._insertSlot(ancestors, popup, sibling)
- return slot
- # Example.
- from sys import stdout
- tree = TreeMap()
- tree["A"] = 1
- tree["B"] = 2
- tree["C"] = 3
- tree["D"] = 4
- tree["E"] = 5
- tree["F"] = 6
- tree["G"] = 7
- stdout.write("Before, # of entries = " + str(len(tree)) + "\n")
- tree.pop("C")
- tree.pop("E")
- stdout.write("After, # of entries = " + str(len(tree)) + "\n")
- for key, value in tree.range("B", "F"):
- stdout.write("[" + key + "]: " + str(value) + "\n")
复制代码 |
|