You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

127 lines
3.2 KiB

  1. class BSTNode:
  2. def __init__(self, value):
  3. self.value = value
  4. self.left = None
  5. self.right = None
  6. def size(self):
  7. ls = 0
  8. rs = 0
  9. if self.left is not None:
  10. ls = self.left.size()
  11. if self.right is not None:
  12. rs = self.right.size()
  13. return rs + ls + 1
  14. def height(self):
  15. lh = 0
  16. rh = 0
  17. if self.left is not None:
  18. lh = self.left.height()
  19. if self.right is not None:
  20. rh = self.right.height()
  21. return 1 + max(lh, rh)
  22. class BST:
  23. def __init__(self):
  24. self.root = None
  25. self.size = 0
  26. def clear(self):
  27. self.root = None
  28. self.size = 0
  29. def add(self, value):
  30. to_add = BSTNode(value)
  31. if self.root is None:
  32. self.root = to_add
  33. self.size += 1
  34. else:
  35. current = self.root
  36. parent = None
  37. while current is not None:
  38. if value > current.value:
  39. parent = current
  40. current = current.right
  41. elif value < current.value:
  42. parent = current
  43. current = current.left
  44. else:
  45. return
  46. if value > parent.value:
  47. parent.right = to_add
  48. else:
  49. parent.left = to_add
  50. self.size += 1
  51. def lookup(self, value):
  52. current = self.root
  53. while current.value != value and current is not None:
  54. if value < current.value:
  55. current = current.left
  56. elif value > current.value:
  57. current = current.right
  58. return current
  59. def in_order(self):
  60. ret = []
  61. in_order_rec(self.root, ret)
  62. return ret
  63. def height(self):
  64. return self.root.height()
  65. class BalancedBST(BST):
  66. def by_index(self, i):
  67. instructions = []
  68. while i > 0:
  69. instructions.append(i & 1 == 0)
  70. i = (i - 1) // 2
  71. current = self.root
  72. while len(instructions) > 0:
  73. go_right = instructions.pop()
  74. if go_right:
  75. current = current.right
  76. else:
  77. current = current.left
  78. return current
  79. @classmethod
  80. def balanced(cls, list_param):
  81. tree = cls()
  82. add_rec(0, len(list_param) - 1, list_param, tree)
  83. return tree
  84. def in_order_rec(top, ret):
  85. if top is None:
  86. return
  87. if top.left:
  88. in_order_rec(top.left, ret)
  89. ret.append(top)
  90. if top.right:
  91. in_order_rec(top.right, ret)
  92. def add_rec(start, end, list_param, tree: BST):
  93. if end - start >= 0:
  94. mid = (start + end) // 2
  95. tree.add(list_param[mid])
  96. add_rec(start, mid - 1, list_param, tree)
  97. add_rec(mid + 1, end, list_param, tree)
  98. if __name__ == "__main__":
  99. test = 17
  100. list_param = list(range(test))
  101. tree = BalancedBST.balanced(list_param)
  102. tree2 = BST()
  103. for i in range(test):
  104. tree2.add(i)
  105. r = list(node.value for node in tree.in_order())
  106. r2 = list(node.value for node in tree2.in_order())
  107. assert r == r2
  108. tree.by_index(6)