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.

109 lines
2.7 KiB

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