It is the depth of the binary search that affects the performance of it. We say that a binary search tree with n nodes is balanced if its depth is of order O(logn) (hence we can perform find, insert and delete operations in time O(logn)).
If a tree is unbalanced, we can maintain the balance by rotation. Further, we need some criteria to guide the rotation. In what's follows we discuss some of the popular design of the criteria.
By the number of elements of the subtree.
Denote a note v and its left and right child v.left and v.right respectively. Define the size of v (s(v)) the number of elements contained in the subtree rooted at v.
A critical observation is that, if for each node v of the tree, the size of each of it subtrees is at most a constant fraction ( denoted as ϵ∈(21,1);
Exercise: why can't we pick ϵ∈[0,21]) of its size, i.e.,
s(v.left)≤ϵs(v)s(v.right)≤ϵs(v)
then the depth of the tree is in the order of O(logn). The reason is obvious: let r=v0,v1,v2,...,vk be any root-to-leaf path of the tree, then
s(v1)≤ϵs(v0)s(v2)≤ϵs(v1)...s(vk)≤ϵs(vk−1)
it follows that 1=s(vk)≤ϵks(v0)=ϵkn and k≤logϵn1=O(logn).
Therefore, we can pick arbitrary ϵ∈(21,1) and maintain this criteria explicitly and recursively.
WLOG, suppose a new element is inserted into the left subtree of a vertex v. Denote the new size function s as s′ after insertion. If after insertion, s′(v.left)≤ϵs′(v), we do nothing and check the balance of v's parent (if there is any). Otherwise, we may try a right rotation on v:
/v.left.leftv/v.left∖v.left.right∖v.right
the subtree transform into:
v.left.leftv.left/∖v/v.left.right∖v.right
Since before insertion, s(v.left)≤ϵs(v), it holds that s′(v.left.left)≤ϵs′(v.left)=ϵ(s(v)+1). Therefore, the left subtree no longer violate the balance constraint. However, the constraint could be violated by the right subtree. Since it is possible that
For example, suppose that ϵ=0.8 and s(v.left.right)=0.8s(v.left)=0.64s(v) and s(v.right)=0.2s(v)−1, then
s(v.left.right)+s(v.right)+1=0.84s(v)
The reason is that there is so much weight that v.left.right has. Therefore, we don't want to rotate it to the right subtree. An alternative is to perform a left rotate on the left subtree first