Guest User

Untitled

a guest
Jul 16th, 2018
241
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 35.81 KB | None | 0 0
  1. class _BNode():
  2. __slots__ = ["tree", "contents", "children"]
  3.  
  4. def __init__(self, tree, contents=None, children=None):
  5. self.tree = tree
  6. self.contents = contents or []
  7. self.children = children or []
  8. if self.children:
  9. assert len(self.contents) + 1 == len(self.children), \
  10. "one more child than data item required"
  11.  
  12. def __repr__(self):
  13. name = getattr(self, "children", 0) and "Branch" or "Leaf"
  14. return "<%s %s>" % (name, ", ".join(map(str, self.contents)))
  15.  
  16. def lateral(self, parent, parent_index, dest, dest_index):
  17. if parent_index > dest_index:
  18. dest.contents.append(parent.contents[dest_index])
  19. parent.contents[dest_index] = self.contents.pop(0)
  20. if self.children:
  21. dest.children.append(self.children.pop(0))
  22. else:
  23. dest.contents.insert(0, parent.contents[parent_index])
  24. parent.contents[parent_index] = self.contents.pop()
  25. if self.children:
  26. dest.children.insert(0, self.children.pop())
  27.  
  28. def shrink(self, ancestors):
  29. parent = None
  30.  
  31. if ancestors:
  32. parent, parent_index = ancestors.pop()
  33. # try to lend to the left neighboring sibling
  34. if parent_index:
  35. left_sib = parent.children[parent_index - 1]
  36. if len(left_sib.contents) < self.tree.order:
  37. self.lateral(
  38. parent, parent_index, left_sib, parent_index - 1)
  39. return
  40.  
  41. # try the right neighbor
  42. if parent_index + 1 < len(parent.children):
  43. right_sib = parent.children[parent_index + 1]
  44. if len(right_sib.contents) < self.tree.order:
  45. self.lateral(
  46. parent, parent_index, right_sib, parent_index + 1)
  47. return
  48.  
  49. center = len(self.contents) // 2
  50. sibling, push = self.split()
  51.  
  52. if not parent:
  53. parent, parent_index = self.tree.BRANCH(
  54. self.tree, children=[self]), 0
  55. self.tree._root = parent
  56.  
  57. # pass the median up to the parent
  58. parent.contents.insert(parent_index, push)
  59. parent.children.insert(parent_index + 1, sibling)
  60. if len(parent.contents) > parent.tree.order:
  61. parent.shrink(ancestors)
  62.  
  63. def grow(self, ancestors):
  64. parent, parent_index = ancestors.pop()
  65.  
  66. minimum = self.tree.order // 2
  67. left_sib = right_sib = None
  68.  
  69. # try to borrow from the right sibling
  70. if parent_index + 1 < len(parent.children):
  71. right_sib = parent.children[parent_index + 1]
  72. if len(right_sib.contents) > minimum:
  73. right_sib.lateral(parent, parent_index + 1, self, parent_index)
  74. return
  75.  
  76. # try to borrow from the left sibling
  77. if parent_index:
  78. left_sib = parent.children[parent_index - 1]
  79. if len(left_sib.contents) > minimum:
  80. left_sib.lateral(parent, parent_index - 1, self, parent_index)
  81. return
  82.  
  83. # consolidate with a sibling - try left first
  84. if left_sib:
  85. left_sib.contents.append(parent.contents[parent_index - 1])
  86. left_sib.contents.extend(self.contents)
  87. if self.children:
  88. left_sib.children.extend(self.children)
  89. parent.contents.pop(parent_index - 1)
  90. parent.children.pop(parent_index)
  91. else:
  92. self.contents.append(parent.contents[parent_index])
  93. self.contents.extend(right_sib.contents)
  94. if self.children:
  95. self.children.extend(right_sib.children)
  96. parent.contents.pop(parent_index)
  97. parent.children.pop(parent_index + 1)
  98.  
  99. if len(parent.contents) < minimum:
  100. if ancestors:
  101. # parent is not the root
  102. parent.grow(ancestors)
  103. elif not parent.contents:
  104. # parent is root, and its now empty
  105. self.tree._root = left_sib or self
  106.  
  107. def split(self):
  108. center = len(self.contents) // 2
  109. median = self.contents[center]
  110. sibling = type(self)(
  111. self.tree,
  112. self.contents[center + 1:],
  113. self.children[center + 1:])
  114. self.contents = self.contents[:center]
  115. self.children = self.children[:center + 1]
  116. return sibling, median
  117.  
  118. def insert(self, index, item, ancestors):
  119. self.contents.insert(index, item)
  120. if len(self.contents) > self.tree.order:
  121. self.shrink(ancestors)
  122.  
  123. def remove(self, index, ancestors):
  124. minimum = self.tree.order // 2
  125.  
  126. if self.children:
  127. # try promoting from the right subtree first,
  128. # but only if it won't have to resize
  129. additional_ancestors = [(self, index + 1)]
  130. descendent = self.children[index + 1]
  131. while descendent.children:
  132. additional_ancestors.append((descendent, 0))
  133. descendent = descendent.children[0]
  134. if len(descendent.contents) > minimum:
  135. ancestors.extend(additional_ancestors)
  136. self.contents[index] = descendent.contents[0]
  137. descendent.remove(0, ancestors)
  138. return
  139.  
  140. # fall back to the left child
  141. additional_ancestors = [(self, index)]
  142. descendent = self.children[index]
  143. while descendent.children:
  144. additional_ancestors.append(
  145. (descendent, len(descendent.children) - 1))
  146. descendent = descendent.children[-1]
  147. ancestors.extend(additional_ancestors)
  148. self.contents[index] = descendent.contents[-1]
  149. descendent.remove(len(descendent.children) - 1, ancestors)
  150. else:
  151. self.contents.pop(index)
  152. if len(self.contents) < minimum and ancestors:
  153. self.grow(ancestors)
  154.  
  155.  
  156. class BTree(object):
  157. BRANCH = LEAF = _BNode
  158.  
  159. def __init__(self, order):
  160. self.order = order
  161. self._root = self._bottom = self.LEAF(self)
  162.  
  163. def _path_to(self, item):
  164. current = self._root
  165. ancestry = []
  166.  
  167. while getattr(current, "children", None):
  168. index = bisect.bisect_left(current.contents, item)
  169. ancestry.append((current, index))
  170. if index < len(current.contents) \
  171. and current.contents[index] == item:
  172. return ancestry
  173. current = current.children[index]
  174.  
  175. index = bisect.bisect_left(current.contents, item)
  176. ancestry.append((current, index))
  177. present = index < len(current.contents)
  178. present = present and current.contents[index] == item
  179.  
  180. return ancestry
  181.  
  182. def _present(self, item, ancestors):
  183. last, index = ancestors[-1]
  184. return index < len(last.contents) and last.contents[index] == item
  185.  
  186. def insert(self, item):
  187. current = self._root
  188. ancestors = self._path_to(item)
  189. node, index = ancestors[-1]
  190. while getattr(node, "children", None):
  191. node = node.children[index]
  192. index = bisect.bisect_left(node.contents, item)
  193. ancestors.append((node, index))
  194. node, index = ancestors.pop()
  195. node.insert(index, item, ancestors)
  196.  
  197. def remove(self, item):
  198. current = self._root
  199. ancestors = self._path_to(item)
  200.  
  201. if self._present(item, ancestors):
  202. node, index = ancestors.pop()
  203. node.remove(index, ancestors)
  204. else:
  205. raise ValueError("%r not in %s" % (item, self.__class__.__name__))
  206.  
  207. def __contains__(self, item):
  208. return self._present(item, self._path_to(item))
  209.  
  210. def __iter__(self):
  211. def _recurse(node):
  212. if node.children:
  213. for child, item in zip(node.children, node.contents):
  214. for child_item in _recurse(child):
  215. yield child_item
  216. yield item
  217. for child_item in _recurse(node.children[-1]):
  218. yield child_item
  219. else:
  220. for item in node.contents:
  221. yield item
  222.  
  223. for item in _recurse(self._root):
  224. yield item
  225.  
  226. def __repr__(self):
  227. def recurse(node, accum, depth):
  228. accum.append((" " * depth) + repr(node))
  229. for node in getattr(node, "children", []):
  230. recurse(node, accum, depth + 1)
  231.  
  232. accum = []
  233. recurse(self._root, accum, 0)
  234. return "\n".join(accum)
  235.  
  236. @classmethod
  237. def bulkload(cls, items, order):
  238. tree = BTree(order)
  239. tree.order = order
  240.  
  241. leaves = tree._build_bulkloaded_leaves(items)
  242. tree._build_bulkloaded_branches(leaves)
  243.  
  244. return tree
  245.  
  246. def _build_bulkloaded_leaves(self, items):
  247. minimum = self.order // 2
  248. leaves, seps = [[]], []
  249.  
  250. for item in items:
  251. if len(leaves[-1]) < self.order:
  252. leaves[-1].append(item)
  253. else:
  254. seps.append(item)
  255. leaves.append([])
  256.  
  257. if len(leaves[-1]) < minimum and seps:
  258. last_two = leaves[-2] + [seps.pop()] + leaves[-1]
  259. leaves[-2] = last_two[:minimum]
  260. leaves[-1] = last_two[minimum + 1:]
  261. seps.append(last_two[minimum])
  262.  
  263. return [[self.LEAF(self, contents=node) for node in leaves], seps]
  264.  
  265. def _build_bulkloaded_branches(self, param):
  266. minimum = self.order // 2
  267. leaves = param[0]
  268. seps = param[1]
  269. levels = [leaves]
  270.  
  271. while len(seps) > self.order + 1:
  272. items, nodes, seps = seps, [[]], []
  273.  
  274. for item in items:
  275. if len(nodes[-1]) < self.order:
  276. nodes[-1].append(item)
  277. else:
  278. seps.append(item)
  279. nodes.append([])
  280.  
  281. if len(nodes[-1]) < minimum and seps:
  282. last_two = nodes[-2] + [seps.pop()] + nodes[-1]
  283. nodes[-2] = last_two[:minimum]
  284. nodes[-1] = last_two[minimum + 1:]
  285. seps.append(last_two[minimum])
  286.  
  287. offset = 0
  288. for i, node in enumerate(nodes):
  289. children = levels[-1][offset:offset + len(node) + 1]
  290. nodes[i] = self.BRANCH(self, contents=node, children=children)
  291. offset += len(node) + 1
  292.  
  293. levels.append(nodes)
  294.  
  295. self._root = self.BRANCH(self, contents=seps, children=levels[-1])
  296.  
  297.  
  298. # this class represents a node within a tree within a Fibonacci heap;
  299. # i.e., the actual elements of the heap
  300. # it contains fields for the necessary key, value, and children data,
  301. # but also has fields to describe its relationship with its sibling
  302. # nodes as well as its markedness status
  303. # it contains methods for adding to and cutting children from this node
  304. class TreeNode():
  305. def __init__(self, key, url):
  306. #the key contains the distance value
  307. self.key = key
  308. #this contains the url string of itself
  309. self.self_url = url
  310. # this contains the list of neighbors (e.g., list of tnodes
  311. # corresponding to urls that I link to)
  312. # list will be list of refs to these tnodes
  313. self.neighbors = []
  314. # this contains a ref to the tnode which leads back to the
  315. # starting url in the most shortest route
  316. self.dij_prev = None
  317. # this means that it was processed through Dijkstra's
  318. self.finished = False
  319. # the following are fib heap requirements
  320. self.prev = None
  321. self.next = None
  322. self.children = []
  323. self.marked = False
  324. # added pointer to parent, if any
  325. self.parent = None
  326. # pointer to enclosing CircNode, if any
  327. self.cnode = None
  328.  
  329. # adds a child to this parent node, updating its linked-list of children
  330. # O(1)
  331. def add_child(self, new_child):
  332. if len(self.children) > 0:
  333. # new_child's 'prev' should point to end of children list
  334. new_child.prev = self.children[-1]
  335. # new_child's 'next' should be the same as last child's
  336. # 'next' (e.g., None)
  337. new_child.next = self.children[-1].next
  338. # last child's next now points to the new child
  339. self.children[-1].next = new_child
  340. # new child points to parent
  341. new_child.parent = self
  342. #actually add the child to the children list
  343. self.children.append(new_child)
  344.  
  345. # cuts a child, updating linked-list of children and returning cut node
  346. # also sets this node's marked status to TRUE
  347. # O(n) where n = len(self.children)
  348. def cut_child(self, cut_index):
  349. # in case of out-of-bound values for cut_index
  350. if cut_index >= len(self.children) or cut_index < 0:
  351. return None
  352.  
  353. if cut_index + 1 < len(self.children) and cut_index > 0:
  354. # connect (child after the one to be cut) to
  355. # (child before the one to be cut)
  356. self.children[cut_index + 1].prev = self.children[cut_index - 1]
  357. # connect (child before the one to be cut) to
  358. # (child after the one to be cut)
  359. self.children[cut_index - 1].next = self.children[cut_index + 1]
  360. #case of cutting the first element
  361. elif cut_index + 1 <= len(self.children) - 1 and cut_index - 1 < 0:
  362. self.children[1].prev = None
  363. # case of cutting the last element
  364. elif cut_index + 1 > len(self.children) - 1 and cut_index - 1 >= 0:
  365. self.children[cut_index - 1].next = None
  366.  
  367. # remove that child from the list
  368. # (now that links are re-done to cut this out)
  369. new_root = self.children.pop(cut_index)
  370. # mark the parent
  371. #self.marked = True
  372. new_root.prev = new_root
  373. new_root.next = new_root
  374. new_root.parent = None
  375. new_root.marked = False
  376. # the caller will have to take care of inserting the new root
  377. # into the ring of roots
  378. return new_root
  379.  
  380. def print_treenode_and_children(self, tnode, s):
  381. for child in tnode.children:
  382. if len(child.children) > 0:
  383. child.print_treenode_and_children(child, '\t' + s)
  384.  
  385. def treenode_and_children_to_list(self, tnode):
  386. a_list = []
  387. for child in tnode.children:
  388. a_list.extend(child.self_url)
  389. if len(child.children) > 0:
  390. a_list.extend(child.self_url)
  391. return a_list
  392.  
  393. def find(self, key):
  394. #check your own key
  395. if self.key == key:
  396. return self
  397. #check all your children's recursively
  398. if len(self.children) > 0:
  399. for child in self.children:
  400. temp_answer = child.find(key)
  401. if temp_answer is not None:
  402. return temp_answer
  403. else:
  404. return None
  405.  
  406. def find_on_self_url(self, url):
  407. #check your own url
  408. if self.self_url == url:
  409. return self
  410. #check all your children's recursively
  411. if len(self.children) > 0:
  412. for child in self.children:
  413. temp_answer = child.find_on_self_url(url)
  414. if temp_answer is not None:
  415. return temp_answer
  416. return None
  417.  
  418.  
  419. # this class represents one of the trees the Fibonacci heap is a collection of
  420. # it holds a reference to the root node of the tree and the degree of the
  421. # tree (number of children its root has)
  422. # it has methods for adding to and cutting nodes from the tree, as well as
  423. # for merging this tree with another tree
  424. class Tree():
  425. def __init__(self, tnode):
  426. self.root = tnode
  427.  
  428. def __getattr__(self, attr):
  429. if attr == "degree":
  430. return len(getattr(self.root, "children"))
  431.  
  432. def add(self, tnode):
  433. # YJP: changed this around to be consistent with other functions
  434. # if the node to be added is less than root, root becomes
  435. # child of the node to be added
  436. self.root.add_child(tnode)
  437.  
  438. def cut(self, tnode):
  439. #index returns the index pos of first occurrence of tnode in list
  440. new_root = self.root.cut_child(self.root.children.index(tnode))
  441. return Tree(new_root)
  442.  
  443. def merge_with(self, tree):
  444. if self.root.key < tree.root.key:
  445. self.add(tree.root)
  446. return self
  447. else:
  448. tree.add(self.root)
  449. return tree
  450.  
  451. def print_tree(self):
  452. print('Tree root:' + repr(self.root.key) + 'Tree root self_url:' + repr(
  453. self.root.self_url) + 'Tree root number of neighbors: ' + repr(len(self.root.neighbors)))
  454. print("Tree degree:" + repr(self.degree))
  455. self.root.print_treenode_and_children(self.root, '')
  456.  
  457. def tree_to_list(self):
  458. a_list = [self.root.self_url]
  459. a_list.extend(self.root.treenode_and_children_to_list(
  460. self.root))
  461. return a_list
  462.  
  463.  
  464. # this class represents a node of the linked list at the core of the Fibonacci
  465. # heap; it is a wrapper for the tree that is the actual list element
  466. # it contains the tree as well as fields to maintain the doubly linked list
  467. # it contains methods to look at the key at the top of its tree and to merge
  468. # itself with another CircNode
  469. class CircNode():
  470. def __init__(self, tree):
  471. tree.root.marked = False
  472. tree.root.parent = None
  473. tree.root.prev = tree.root.next = tree.root
  474. tree.root.cnode = self
  475. self.tree = tree
  476. self.prev = self.next = self
  477. self.checked_for_consolidation = False
  478.  
  479. def key(self):
  480. return self.tree.root.key
  481.  
  482. def merge(self, other_node):
  483. lower_key_tree = self.tree.merge_with(other_node.tree)
  484.  
  485.  
  486. class FibHeap():
  487. def __init__(self):
  488. self.min = None
  489. # size here refers to number of nodes in the core doubly-linked
  490. # list/ring, NOT total number of nodes in the heap
  491. self.size = 0
  492. # the below refers to total number of nodes in the fibheap
  493. # (not just in the ring)
  494. self.total_size = 0
  495.  
  496. # returns whether or not this heap is empty
  497. def is_empty(self):
  498. return self.min is None
  499.  
  500. # inserts the given TreeNode into the heap at the circnode level
  501. # ("adds a new tree")
  502. def insert(self, tnode):
  503. tnode.parent = None
  504. cnode = CircNode(Tree(tnode))
  505. if self.is_empty():
  506. self.min = cnode
  507. else:
  508. # always insert cnode before the current min
  509. cnode.prev = self.min.prev
  510. cnode.next = self.min
  511. self.min.prev.next = cnode
  512. self.min.prev = cnode
  513. if cnode.tree.root.key < self.min.tree.root.key:
  514. self.min = cnode
  515. self.size += 1
  516. self.total_size += 1
  517. print("after an insert*************")
  518. self.print_heap()
  519. return cnode
  520.  
  521. # returns the minimum element of the heap (as a TreeNode) without
  522. # removing it
  523. def get_min(self):
  524. return self.min.tree.root
  525.  
  526. # returns the minimum element of the heap (as a TreeNode) and removes
  527. # it from the heap
  528. def pop(self):
  529. print("\npop happened ***************")
  530. if self.is_empty():
  531. return None
  532. else:
  533. returnval = self.min.tree.root
  534. # there is only one cnode left and it has no children
  535. if (self.min.next is self.min) and self.min.tree.degree == 0:
  536. self.min = None
  537. self.total_size -= 1
  538. self.size -= 1
  539. return returnval
  540. # min is not the only cnode left but min has no children
  541. elif (self.min.next is not self.min) and self.min.tree.degree == 0:
  542. self.min.prev.next = self.min.next
  543. self.min.next.prev = self.min.prev
  544. self.min = self.min.next
  545. self.restructure()
  546. self.total_size -= 1
  547. self.size -= 1
  548. return returnval
  549. # min is the only cnode left and it has children
  550. elif self.min.next is self.min:
  551. self.min.tree.root.children[0].parent = None
  552. new_head = CircNode(Tree(self.min.tree.root.children[0]))
  553. new_tail = new_head
  554. if self.min.tree.degree > 1:
  555. curr_child = new_head
  556. for child in self.min.tree.root.children[1:]:
  557. child.parent = None
  558. curr_child.next = CircNode(Tree(child))
  559. curr_child.next.prev = curr_child
  560. curr_child = curr_child.next
  561. if child == self.min.tree.root.children[-1]:
  562. new_tail = curr_child
  563. new_head.prev = new_tail
  564. new_tail.next = new_head
  565. self.size += (len(self.min.tree.root.children) - 1)
  566. self.total_size -= 1
  567. self.min = new_head
  568. self.restructure()
  569. return returnval
  570. # min is not the only cnode left and it has children
  571. else:
  572. self.min.tree.root.children[0].parent = None
  573. new_head = CircNode(Tree(self.min.tree.root.children[0]))
  574. new_tail = new_head
  575. if self.min.tree.degree > 1:
  576. curr_child = new_head
  577. for child in self.min.tree.root.children[1:]:
  578. child.parent = None
  579. curr_child.next = CircNode(Tree(child))
  580. curr_child.next.prev = curr_child
  581. curr_child = curr_child.next
  582. if child == self.min.tree.root.children[-1]:
  583. new_tail = curr_child
  584. self.min.prev.next = new_head
  585. new_head.prev = self.min.prev
  586. self.min.next.prev = new_tail
  587. new_tail.next = self.min.next
  588. self.size += (len(self.min.tree.root.children) - 1)
  589. self.total_size -= 1
  590. self.min = new_head
  591. self.restructure()
  592. return returnval
  593.  
  594. # restructures the heap's core double-linked-list after the removal
  595. # of one of the heap's elements (circnode ring exists but
  596. # consolidation hasn't happened yet
  597. # also, haven't set a new, correct self.min yet
  598. def restructure(self):
  599. degrees = [None]
  600. currCNode = self.min
  601. while True:
  602. #the largest degree that we are tracking
  603. max_degree = len(degrees) - 1
  604. #to get the right min by the end
  605. temp_min_key = self.min.key()
  606. if currCNode.key() <= temp_min_key:
  607. self.min = currCNode
  608. temp_min_key = self.min.key()
  609. # if we run across a cnode with a degree larger than we are tracking
  610. if currCNode.tree.degree > max_degree:
  611. print("THIS IS THE PROBLEM AREA!! (A)**********")
  612. for i in range(max_degree, currCNode.tree.degree):
  613. degrees.append(None)
  614. degrees[currCNode.tree.degree] = currCNode
  615. currCNode = currCNode.next
  616. continue
  617. # if we have come all the way back to the same cnode, and the next
  618. # cnode has been checked to have no duplicates either, we've run
  619. # the whole ring
  620. if degrees[currCNode.tree.degree] is currCNode:
  621. print("THIS IS THE PROBLEM AREA!! (B)**********")
  622. currCNode.checked_for_consolidation = True
  623. if currCNode.next.checked_for_consolidation:
  624. break
  625. else:
  626. currCNode = currCNode.next
  627. continue
  628. if degrees[currCNode.tree.degree] is None:
  629. print("THIS IS THE PROBLEM AREA!! (C)**********")
  630. degrees[currCNode.tree.degree] = currCNode
  631. currCNode = currCNode.next
  632. else:
  633. # this is the cnode prev identified as one having same degree
  634. # as our current cnode
  635. mergeNode = degrees[currCNode.tree.degree]
  636. degrees[currCNode.tree.degree] = None
  637. if mergeNode.key() < currCNode.key():
  638. print("THIS IS THE PROBLEM AREA!! (D)**********")
  639. print("mergeNode is " + repr(mergeNode.tree.root.self_url) + "with key " + repr(
  640. mergeNode.tree.root.key) + "and with degree " + repr(mergeNode.tree.degree))
  641. print("currCNode is " + repr(currCNode.tree.root.self_url) + "with key " + repr(
  642. currCNode.tree.root.key) + "and with degree " + repr(currCNode.tree.degree))
  643. mergeNode.prev.next = mergeNode.next
  644. mergeNode.next.prev = mergeNode.prev
  645. mergeNode.next = currCNode.next
  646. mergeNode.prev = currCNode.prev
  647. currCNode.prev.next = mergeNode
  648. currCNode.next.prev = mergeNode
  649. mergeNode.tree.root.add_child(currCNode.tree.root)
  650. if currCNode is self.min:
  651. self.min = mergeNode
  652. currCNode = mergeNode
  653. else:
  654. print("THIS IS THE PROBLEM AREA!! (E)**********")
  655. self.remove_node(mergeNode)
  656. currCNode.tree.root.add_child(mergeNode.tree.root)
  657. if mergeNode is self.min:
  658. self.min = currCNode
  659. currCNode.checked_for_consolidation = False
  660. self.size -= 1
  661. print("\nafter one iteration of restructure*******************")
  662. self.print_heap()
  663.  
  664. def remove_node(self, cnode):
  665. cnode.prev.next = cnode.next
  666. cnode.next.prev = cnode.prev
  667. cnode.prev = cnode.next = cnode
  668. return cnode
  669.  
  670. # decreases the key of the given TreeNode to the specified value,
  671. # cutting children off into new trees if the min-heap invariant becomes
  672. # violated in the new configuration
  673. def decr_key(self, tnode, new_key):
  674. print("Decr_key happened! ********************")
  675. #print "decr-ing tnode %g to %g" % (tnode.key,new_key)
  676. if new_key >= tnode.key:
  677. print("New key must be less than old key")
  678. else:
  679. tnode.key = new_key
  680. if tnode.parent is not None:
  681. if tnode.key < tnode.parent.key:
  682. #fix_heap uses insert, which should update the min
  683. self.fix_heap_recursive(tnode)
  684. elif tnode.key < self.min.tree.root.key:
  685. self.min = tnode.cnode
  686.  
  687. def fix_heap_recursive(self, tnode):
  688. if tnode.parent is not None:
  689. theParent = tnode.parent
  690. parent_marked = theParent.marked
  691. new_root = theParent.cut_child(theParent.children.index(tnode))
  692. self.insert(new_root)
  693. if parent_marked:
  694. self.fix_heap_recursive(theParent)
  695. else:
  696. theParent.marked = True
  697.  
  698. # removes the given TreeNode from the heap (does not return the node)
  699. def delete(self, tnode):
  700. self.decr_key(tnode, float("-inf"))
  701. self.pop()
  702.  
  703. # merges this heap with another Fibonacci heap
  704. def merge(self, other_heap):
  705. other_heap.min.prev.next = self.min.next
  706. self.min.next.prev = other_heap.min.prev
  707. self.min.next = other_heap.min
  708. other_heap.min.prev = self.min
  709. if other_heap.min.tree.root.key < self.min.tree.root.key:
  710. self.min = other_heap.min
  711. self.size += other_heap.size
  712. self.total_size += other_heap.total_size
  713.  
  714. # returns the TreeNode with the given key, or None if key not in heap
  715. def find(self, key):
  716. start_circnode = self.min
  717. curr_circnode = self.min
  718. answer_tnode = curr_circnode.tree.root.find(key)
  719. if answer_tnode is not None:
  720. return answer_tnode
  721. while True:
  722. if curr_circnode.next == start_circnode:
  723. return None
  724. curr_circnode = curr_circnode.next
  725. answer_tnode = curr_circnode.tree.root.find(key)
  726. if answer_tnode is not None:
  727. return answer_tnode
  728.  
  729. def find_on_self_url(self, url):
  730. #if heap is entirely empty, then return None
  731. if self.is_empty():
  732. return None
  733. start_circnode = self.min
  734. curr_circnode = self.min
  735. answer_tnode = curr_circnode.tree.root.find_on_self_url(url)
  736. if answer_tnode is not None:
  737. return answer_tnode
  738. while True:
  739. if curr_circnode.next == start_circnode:
  740. return None
  741. curr_circnode = curr_circnode.next
  742. answer_tnode = curr_circnode.tree.root.find_on_self_url(url)
  743. if answer_tnode is not None:
  744. return answer_tnode
  745.  
  746. # yjp: prints all the nodes in the heap, and use for testing
  747. def print_heap(self):
  748. print("\nThis is a heap of total size" + repr(self.total_size))
  749. print("This is key of min cnode" + repr(self.min.key()))
  750. curr_circnode = self.min
  751. print("\nthis is a circnode:")
  752. curr_circnode.tree.print_tree()
  753. while curr_circnode.next is not self.min:
  754. curr_circnode = curr_circnode.next
  755. print("\nthis is a circnode:")
  756. curr_circnode.tree.print_tree()
  757.  
  758. #yjp: prints a numbered list of the urls of all the tnodes in the fibheap
  759. def heap_to_list(self):
  760. curr_circnode = self.min
  761. a_list = curr_circnode.tree.tree_to_list()
  762. while curr_circnode.next is not self.min:
  763. curr_circnode = curr_circnode.next
  764. a_list.extend(curr_circnode.tree.tree_to_list())
  765. return a_list
  766.  
  767. # cjl: prints only the keys of the nodes in the core doubly-linked list.
  768. # this is used to check correct circularity of list.
  769. def print_CDDL(self):
  770. print("\nHeap CDDL:")
  771. curr_circnode = self.min
  772. print("Circnode " + repr(curr_circnode.tree.root.key))
  773. while curr_circnode.next is not self.min:
  774. curr_circnode = curr_circnode.next
  775. print("Circnode " + repr(curr_circnode.tree.root.key))
  776.  
  777.  
  778. __author__ = "Evan Jones <evanj@mit.edu>"
  779.  
  780. import bisect
  781. import math
  782.  
  783.  
  784. def log2(n):
  785. return math.log2(n)
  786.  
  787.  
  788. class VEBQueueSmall():
  789. def __init__(self):
  790. """Creates a "VEB" queue containing only 2 items."""
  791. self.values = [False, False]
  792.  
  793. def insert(self, x):
  794. assert 0 <= x < 2
  795. self.values[x] = True
  796.  
  797. def delete(self, x):
  798. assert 0 <= x < 2
  799. self.values[x] = False
  800.  
  801. def find(self, x):
  802. assert 0 <= x < 2
  803. return self.values[x]
  804.  
  805. def max(self):
  806. for i in range(1, -1, -1):
  807. if self.values[i]:
  808. return i
  809. return None
  810.  
  811. def min(self):
  812. for i in range(2):
  813. if self.values[i]:
  814. return i
  815. return None
  816.  
  817. def predecessor(self, x):
  818. assert 0 <= x < 2
  819.  
  820. if x == 0:
  821. return None
  822. assert x == 1
  823. if self.values[0]:
  824. return 0
  825.  
  826.  
  827. def NewVEBQueue(n):
  828. if n == 2:
  829. return VEBQueueSmall()
  830. else:
  831. return VEBQueueBase(n)
  832.  
  833.  
  834. class VEBQueueBase():
  835. def __init__(self, n):
  836. """Create a queue containing (0, n-1). n must be = 2^(2^x)."""
  837.  
  838. try:
  839. power = log2(n)
  840. powpow = log2(n)
  841. except OverflowError:
  842. raise ValueError("n must be = 2^(2^x) for some x")
  843.  
  844. self.sqrtShift = power / 2
  845. sqrtN = 1 << int(self.sqrtShift)
  846. self.sqrtMask = sqrtN - 1
  847. self.n = n
  848.  
  849. self.high = NewVEBQueue(sqrtN)
  850. self.low = [None] * sqrtN
  851. self.minValue = None
  852. self.maxValue = None
  853.  
  854. def split(self, x):
  855. """Returns the high and low portions of x."""
  856.  
  857. xHigh = x >> int(self.sqrtShift)
  858. xLow = x & self.sqrtMask
  859. return xHigh, xLow
  860.  
  861. def insert(self, x):
  862. assert 0 <= x < self.n
  863.  
  864. if self.minValue is None:
  865. # Insert in empty queue: O(1)
  866. assert self.maxValue is None
  867. self.minValue = x
  868. self.maxValue = x
  869. return
  870. if x == self.minValue:
  871. # Inserting the minimum again does nothing
  872. return
  873.  
  874. if x < self.minValue:
  875. # Inserting less than min: actually insert min
  876. oldMin = self.minValue
  877. self.minValue = x
  878. x = oldMin
  879. assert x > self.minValue
  880.  
  881. if x > self.maxValue:
  882. self.maxValue = x
  883.  
  884. xHigh, xLow = self.split(x)
  885.  
  886. if self.low[xHigh] is None:
  887. # Empty sub-queue: Create it
  888. self.low[xHigh] = NewVEBQueue(1 << int(self.sqrtShift))
  889. self.high.insert(xHigh)
  890. self.low[xHigh].insert(xLow)
  891.  
  892. def delete(self, x):
  893. assert 0 <= x < self.n
  894.  
  895. if self.minValue is None:
  896. # Delete in empty queue: do nothing
  897. return
  898. if x < self.minValue:
  899. # x does not exist in the queue
  900. return
  901. assert x >= self.minValue
  902.  
  903. if x == self.minValue:
  904. # Move the successor to the minimum value and delete that instead
  905. index = self.high.min()
  906. if index is None:
  907. # No successor: we are done
  908. assert self.maxValue == self.minValue
  909. self.minValue = None
  910. self.maxValue = None
  911. return
  912.  
  913. self.minValue = (index << self.sqrtShift) | self.low[index].min()
  914. x = self.minValue
  915.  
  916. xHigh, xLow = self.split(x)
  917.  
  918. if self.low[xHigh] is None:
  919. # Nothing to delete
  920. return
  921.  
  922. # The queue for x must exist. Delete it recursively
  923. self.low[xHigh].delete(xLow)
  924.  
  925. if self.low[xHigh].min() is None:
  926. # Sub queue is now empty: delete it from the high queue
  927. self.low[xHigh] = None
  928. self.high.delete(xHigh)
  929.  
  930. if x == self.maxValue:
  931. # If we deleted the maximum, update it in O(1) time
  932. maxHigh = self.high.max()
  933. if maxHigh is None:
  934. # 1 element in this queue
  935. assert self.minValue is not None
  936. self.maxValue = self.minValue
  937. else:
  938. self.maxValue = (maxHigh << self.sqrtShift) | self.low[maxHigh].max()
  939.  
  940. def max(self):
  941. return self.maxValue
  942.  
  943. def min(self):
  944. return self.minValue
  945.  
  946. def find(self, x):
  947. assert 0 <= x < self.n
  948.  
  949. if self.minValue is None:
  950. return False
  951. if x == self.minValue:
  952. return True
  953. xHigh, xLow = self.split(x)
  954. if self.low[xHigh] is None:
  955. return False
  956. return self.low[xHigh].find(xLow)
  957.  
  958. def predecessor(self, x):
  959. assert 0 <= x < self.n
  960.  
  961. if self.minValue is None or x <= self.minValue:
  962. # Empty queue or nothing smaller
  963. return None
  964.  
  965. xHigh, xLow = self.split(x)
  966. if self.low[xHigh] is None or xLow <= self.low[xHigh].min():
  967. # We need to look before this block: recurse on self.high O(sqrt n)
  968. index = self.high.predecessor(xHigh)
  969. if index is None:
  970. # No predecessors in self.high: Return the min
  971. return self.minValue
  972.  
  973. # Combine the index with the max from the lower block
  974. return (index << self.sqrtShift) | self.low[index].max()
  975. else:
  976. assert xLow > self.low[xHigh].min()
  977. # We need to look in this block: recurse on self.low O(sqrt n)
  978. lowerPredecessor = self.low[xHigh].predecessor(xLow)
  979. assert lowerPredecessor is not None
  980. return (xHigh << self.sqrtShift) | lowerPredecessor
  981.  
  982.  
  983. if __name__ == '__main__':
  984.  
  985. bt = BTree(2)
  986. for i in range(97, 112):
  987. bt.insert(i)
  988.  
  989. print(bt)
  990.  
  991. fh = FibHeap()
  992.  
  993. for i in range(0, 20):
  994. new_node = TreeNode(i, "yahoo")
  995. fh.insert(new_node)
  996.  
  997. fh.print_heap()
  998.  
  999. #Need to establish n must be n=2^(2^x)
  1000. veb = NewVEBQueue(256)
  1001. for i in range(0, 256):
  1002. for j in range(0, 10):
  1003. veb.insert(i)
  1004.  
  1005. print("Done")
Add Comment
Please, Sign In to add comment