internal AvlTree(ElaValue key, ElaValue value, AvlTree left, AvlTree right) { Key = key; Value = value; Left = left; Right = right; TreeHeight = 1 + Math.Max(Height(left), Height(right)); }
internal virtual AvlTree Add(ElaValue key, ElaValue value) { var result = default(AvlTree); if (key.CompareTo(Key) > 0) result = new AvlTree(Key, Value, Left, Right.Add(key, value)); else result = new AvlTree(Key, Value, Left.Add(key, value), Right); return MakeBalanced(result); }
internal virtual AvlTree Remove(ElaValue key) { var result = default(AvlTree); var compare = key.CompareTo(Key); if (compare == 0) { if (Right.IsEmpty && Left.IsEmpty) result = Empty; else if (Right.IsEmpty && !Left.IsEmpty) result = Left; else if (!Right.IsEmpty && Left.IsEmpty) result = Right; else { var successor = Right; while (!successor.Left.IsEmpty) successor = successor.Left; result = new AvlTree(successor.Key, successor.Value, Left, Right.Remove(successor.Key)); } } else if (compare < 0) result = new AvlTree(Key, Value, Left.Remove(key), Right); else result = new AvlTree(Key, Value, Left, Right.Remove(key)); return MakeBalanced(result); }
private static AvlTree RotateRight(AvlTree tree) { if (tree.Left.IsEmpty) return tree; return new AvlTree(tree.Left.Key, tree.Left.Value, tree.Left.Left, new AvlTree(tree.Key, tree.Value, tree.Left.Right, tree.Right)); }
private static AvlTree MakeBalanced(AvlTree tree) { var result = default(AvlTree); if (IsRightHeavy(tree)) { if (IsLeftHeavy(tree.Right)) result = DoubleLeft(tree); else result = RotateLeft(tree); } else if (IsLeftHeavy(tree)) { if (IsRightHeavy(tree.Left)) result = DoubleRight(tree); else result = RotateRight(tree); } else result = tree; return result; }
private static bool IsRightHeavy(AvlTree tree) { return Balance(tree) >= 2; }
private static bool IsLeftHeavy(AvlTree tree) { return Balance(tree) <= -2; }
private static int Height(AvlTree tree) { return tree.IsEmpty ? 0 : tree.TreeHeight; }
private static AvlTree DoubleRight(AvlTree tree) { if (tree.Left.IsEmpty) return tree; var rotatedLeftChild = new AvlTree(tree.Key, tree.Value, RotateLeft(tree.Left), tree.Right); return RotateRight(rotatedLeftChild); }
private static int Balance(AvlTree tree) { if (tree.IsEmpty) return 0; return Height(tree.Right) - Height(tree.Left); }