**Bug** No, it is not correct: self.right.set_height `set_height` is not run due to the lack of parenthesis, hence the height is not correctly set. **Swapping** In many places such as for example: temp = self self = self.right self.right = temp self.right.set_height self.set_height You are swapping values in an obfuscated manner, just use the built-in `a, b = b, a` syntax: >>> a, b = 1, 2 >>> a, b = b, a >>> a, b (2, 1) **Naming** Universally, names of classes are written in `PascalCase`, and you should really stick to it, even if the compiler does not enforce it: binary_tree -> BinaryTree **`get`ters** Getters are highly frowned upon in Python. Values are generally accessed directly. If you really do not want the user to access values directly you may make them "private" by prefixing `__` and letting a `@property` return them. **Decide for your `nil` values** `None` is the standard `nil` (nothing) value in Python but in `get_right_height` you return -1 if the value is`None`. If so just make the default `-1` and remove the getter as suggested above. **Repetition Repetition** You repeat `b.add` 6 times, use a loop to avoid such waste. --- There must be a way to avoid repetition in the below code-blocks, the problem is that you have duplicate functions for left and right, maybe a single rotate function could help you here. '''Adding to left subtree''' if self.left is None: self.left = Node(data) else: self.left.add_node(data) if ( self.get_left_height() - self.get_right_height() == 2): ''' Then we need to balance a subtree''' print("Rebalancing after inserting", data) if (data < self.left.data): self.rotate_left() else: self.double_rotate_left() --- '''Adding to right subtree''' if self.right is None: self.right = Node(data) else: self.right.add_node(data) if ( self.get_right_height() - self.get_left_height() == 2): ''' Then we need to balance a subtree''' print("Rebalancing after inserting", data) if (data < self.right.data): self.rotate_right() else: self.double_rotate_right()