|
@@ -0,0 +1,140 @@
|
|
|
+class TreeNode(object):
|
|
|
+ def __init__(self, val):
|
|
|
+ self.val = val
|
|
|
+ self.left = None
|
|
|
+ self.right = None
|
|
|
+ self.height = 1
|
|
|
+ self.size = 1
|
|
|
+
|
|
|
+ def __repr__(self) -> str:
|
|
|
+ return f'{self.val}({self.size})'
|
|
|
+
|
|
|
+
|
|
|
+class AVL_Tree(object):
|
|
|
+ @staticmethod
|
|
|
+ def insert(root, key):
|
|
|
+ if not root:
|
|
|
+ return TreeNode(key)
|
|
|
+ elif key < root.val:
|
|
|
+ root.left = AVL_Tree.insert(root.left, key)
|
|
|
+ else:
|
|
|
+ root.right = AVL_Tree.insert(root.right, key)
|
|
|
+
|
|
|
+ root.height = 1 + max(AVL_Tree.getHeight(root.left),
|
|
|
+ AVL_Tree.getHeight(root.right))
|
|
|
+ root.size = 1 + \
|
|
|
+ AVL_Tree.getSize(root.left) + AVL_Tree.getSize(root.right)
|
|
|
+ balance = AVL_Tree.getBalance(root)
|
|
|
+
|
|
|
+ if balance > 1 and key <= root.left.val:
|
|
|
+ return AVL_Tree.rightRotate(root)
|
|
|
+
|
|
|
+ if balance < -1 and key >= root.right.val:
|
|
|
+ return AVL_Tree.leftRotate(root)
|
|
|
+
|
|
|
+ if balance > 1 and key >= root.left.val:
|
|
|
+ root.left = AVL_Tree.leftRotate(root.left)
|
|
|
+ return AVL_Tree.rightRotate(root)
|
|
|
+
|
|
|
+ if balance < -1 and key <= root.right.val:
|
|
|
+ root.right = AVL_Tree.rightRotate(root.right)
|
|
|
+ return AVL_Tree.leftRotate(root)
|
|
|
+
|
|
|
+ return root
|
|
|
+
|
|
|
+ @staticmethod
|
|
|
+ def leftRotate(z):
|
|
|
+ y = z.right
|
|
|
+ T2 = y.left
|
|
|
+
|
|
|
+ y.left = z
|
|
|
+ z.right = T2
|
|
|
+
|
|
|
+ z.height = 1 + max(AVL_Tree.getHeight(z.left),
|
|
|
+ AVL_Tree.getHeight(z.right))
|
|
|
+ y.height = 1 + max(AVL_Tree.getHeight(y.left),
|
|
|
+ AVL_Tree.getHeight(y.right))
|
|
|
+ ty = AVL_Tree.getSize(y.right)
|
|
|
+ tz = AVL_Tree.getSize(z.left)
|
|
|
+ z.size -= (ty + 1)
|
|
|
+ y.size += (tz + 1)
|
|
|
+ return y
|
|
|
+
|
|
|
+ @staticmethod
|
|
|
+ def rightRotate(z):
|
|
|
+ y = z.left
|
|
|
+ T3 = y.right
|
|
|
+
|
|
|
+ y.right = z
|
|
|
+ z.left = T3
|
|
|
+
|
|
|
+ z.height = 1 + max(AVL_Tree.getHeight(z.left),
|
|
|
+ AVL_Tree.getHeight(z.right))
|
|
|
+ y.height = 1 + max(AVL_Tree.getHeight(y.left),
|
|
|
+ AVL_Tree.getHeight(y.right))
|
|
|
+
|
|
|
+ ty = AVL_Tree.getSize(y.left)
|
|
|
+ tz = AVL_Tree.getSize(z.right)
|
|
|
+ z.size -= (ty + 1)
|
|
|
+ y.size += (tz + 1)
|
|
|
+ return y
|
|
|
+
|
|
|
+ @staticmethod
|
|
|
+ def getHeight(root):
|
|
|
+ if not root:
|
|
|
+ return 0
|
|
|
+ return root.height
|
|
|
+
|
|
|
+ @staticmethod
|
|
|
+ def getSize(root):
|
|
|
+ if not root:
|
|
|
+ return 0
|
|
|
+ return root.size
|
|
|
+
|
|
|
+ @staticmethod
|
|
|
+ def getBalance(root):
|
|
|
+ if not root:
|
|
|
+ return 0
|
|
|
+ return AVL_Tree.getHeight(root.left) - AVL_Tree.getHeight(root.right)
|
|
|
+
|
|
|
+ @staticmethod
|
|
|
+ def preOrder(root, depth=0):
|
|
|
+ if not root:
|
|
|
+ return
|
|
|
+ print("{0}{1}".format(' ' * depth, root))
|
|
|
+ AVL_Tree.preOrder(root.left, depth+1)
|
|
|
+ AVL_Tree.preOrder(root.right, depth+1)
|
|
|
+
|
|
|
+ @staticmethod
|
|
|
+ def getitem(root, idx):
|
|
|
+ #print(root, idx)
|
|
|
+ s = AVL_Tree.getSize(root.left)
|
|
|
+ if s == idx:
|
|
|
+ return root.val
|
|
|
+ elif idx > s:
|
|
|
+ return AVL_Tree.getitem(root.right, idx - s - 1)
|
|
|
+ else:
|
|
|
+ return AVL_Tree.getitem(root.left, idx)
|
|
|
+
|
|
|
+ @staticmethod
|
|
|
+ def index(root, val):
|
|
|
+ if not root:
|
|
|
+ return 0
|
|
|
+ if root.val < val:
|
|
|
+ return AVL_Tree.index(root.right, val) + AVL_Tree.getSize(root.left) + 1
|
|
|
+ else:
|
|
|
+ return AVL_Tree.index(root.left, val)
|
|
|
+# Driver program to test above function
|
|
|
+
|
|
|
+root = None
|
|
|
+
|
|
|
+
|
|
|
+z = [6,21,-27,17,-20,3,1,-2,10,2,23,15,-3,1,9,19,-9,-24,-30,-26,-13,23,2,-10,20,0,27,24,-28,26,0,-29,-16,0,12,-28,7,1,22,-23,20,-22,-11,7,-10,-5,27,27,0,19,-9,28,-2,6,23,-9,-9,1,8,-15]
|
|
|
+
|
|
|
+for i in z:
|
|
|
+ root = AVL_Tree.insert(root, i)
|
|
|
+
|
|
|
+AVL_Tree.preOrder(root)
|
|
|
+
|
|
|
+for i in range(root.size):
|
|
|
+ print(AVL_Tree.getitem(root, i))
|