C#AVL二叉树(2)

        上次的AVL二叉树很不成熟,在测试过程中有很多问题,以下AVL树比上次好点。以下一种自平衡二叉搜索树,其中每个节点的两个子树的高度最多相差1。如果任何时候节点的两个子树的高度差超过1,则会通过旋转操作来重新平衡这棵树。以下是代码的主要组成部分和功能:实现了插入、删除、搜索和遍历功能,同时保持了树的平衡性。

//代表AVL树中的一个节点,包含键(`Key`)、值(`Value`)、父节点、左子节点、右子节点以及平衡因子(`Balance`)。

public sealed class AvlNode<TKey, TValue>
	{
		public AvlNode<TKey, TValue> Parent;
		public AvlNode<TKey, TValue> Left;
		public AvlNode<TKey, TValue> Right;
		public TKey Key;
		public TValue Value;
		public int Balance;
	}
//实现了 `IEnumerator<AvlNode<TKey, TValue>>` 接口,用于遍历AVL树中的节点。它使用中序遍历的方式,即先遍历左子树,然后访问根节点,最后遍历右子树。
public sealed class AvlNodeEnumerator<TKey, TValue> : IEnumerator<AvlNode<TKey, TValue>>
	{
		private AvlNode<TKey, TValue> _root;
		private Action _action;
		private AvlNode<TKey, TValue> _current;
		private AvlNode<TKey, TValue> _right;

		public AvlNodeEnumerator(AvlNode<TKey, TValue> root)
		{
			_right = _root = root;
			_action = _root == null ? Action.End : Action.Right;
		}

		public bool MoveNext()
		{
			switch (_action)
			{
				case Action.Right:
					_current = _right;

					while (_current.Left != null)
					{
						_current = _current.Left;
					}

					_right = _current.Right;
					_action = _right != null ? Action.Right : Action.Parent;

					return true;

				case Action.Parent:
					while (_current.Parent != null)
					{
						AvlNode<TKey, TValue> previous = _current;

						_current = _current.Parent;

						if (_current.Left == previous)
						{
							_right = _current.Right;
							_action = _right != null ? Action.Right : Action.Parent;

							return true;
						}
					}

					_action = Action.End;

					return false;

				default:
					return false;
			}
		}

		public void Reset()
		{
			_right = _root;
			_action = _root == null ? Action.End : Action.Right;
		}

		public AvlNode<TKey, TValue> Current
		{
			get
			{
				return _current;
			}
		}

		object IEnumerator.Current
		{
			get
			{
				return Current;
			}
		}

		public void Dispose()
		{
		}

		enum Action//用于指示 `AvlNodeEnumerator` 在遍历过程中的当前动作,可以是 `Parent`(向上遍历到父节点)、`Right`(向下遍历到右子树)或 `End`(遍历结束)。
		{
			Parent,
			Right,
			End
		}
	}

//实现了 `IEnumerable<AvlNode<TKey, TValue>>` 接口,代表整个AVL树。它包含一个比较器(`_comparer`),用于比较键值,以及根节点(`_root`)。
public class AvlTree<TKey, TValue> : IEnumerable<AvlNode<TKey, TValue>>
	{
		private IComparer<TKey> _comparer;
		private AvlNode<TKey, TValue> _root;

		public AvlTree(IComparer<TKey> comparer)
		{
			_comparer = comparer;
		}

		public AvlTree()
		   : this(Comparer<TKey>.Default)
		{

		}

		public AvlNode<TKey, TValue> Root
		{
			get
			{
				return _root;
			}
		}

		public IEnumerator<AvlNode<TKey, TValue>> GetEnumerator()
		{
			return new AvlNodeEnumerator<TKey, TValue>(_root);
		}

		public bool Search(TKey key, out TValue value)//用于在AVL树中搜索一个键,如果找到,则将对应的值输出。
		{
			AvlNode<TKey, TValue> node = _root;

			while (node != null)
			{
				if (_comparer.Compare(key, node.Key) < 0)
				{
					node = node.Left;
				}
				else if (_comparer.Compare(key, node.Key) > 0)
				{
					node = node.Right;
				}
				else
				{
					value = node.Value;

					return true;
				}
			}

			value = default(TValue);

			return false;
		}

		public bool Insert(TKey key, TValue value)//用于将一个新的键值对插入AVL树中。如果插入后树失去平衡,则会调用 `InsertBalance` 方法进行平衡。
		{
			AvlNode<TKey, TValue> node = _root;

			while (node != null)
			{
				int compare = _comparer.Compare(key, node.Key);

				if (compare < 0)
				{
					AvlNode<TKey, TValue> left = node.Left;

					if (left == null)
					{
						node.Left = new AvlNode<TKey, TValue> { Key = key, Value = value, Parent = node };

						InsertBalance(node, 1);

						return true;
					}
					else
					{
						node = left;
					}
				}
				else if (compare > 0)
				{
					AvlNode<TKey, TValue> right = node.Right;

					if (right == null)
					{
						node.Right = new AvlNode<TKey, TValue> { Key = key, Value = value, Parent = node };

						InsertBalance(node, -1);

						return true;
					}
					else
					{
						node = right;
					}
				}
				else
				{
					node.Value = value;

					return false;
				}
			}
			
			_root = new AvlNode<TKey, TValue> { Key = key, Value = value };

			return true;
		}

		private void InsertBalance(AvlNode<TKey, TValue> node, int balance)//用于在插入操作后重新平衡AVL树。它会根据节点的平衡因子进行单旋转或双旋转。
		{
			while (node != null)
			{
				balance = (node.Balance += balance);

				if (balance == 0)
				{
					return;
				}
				else if (balance == 2)
				{
					if (node.Left.Balance == 1)
					{
						RotateRight(node);
					}
					else
					{
						RotateLeftRight(node);
					}

					return;
				}
				else if (balance == -2)
				{
					if (node.Right.Balance == -1)
					{
						RotateLeft(node);
					}
					else
					{
						RotateRightLeft(node);
					}

					return;
				}

				AvlNode<TKey, TValue> parent = node.Parent;

				if (parent != null)
				{
					balance = parent.Left == node ? 1 : -1;
				}

				node = parent;
			}
		}

		private AvlNode<TKey, TValue> RotateLeft(AvlNode<TKey, TValue> node)//旋转操作,用于在树失去平衡时进行调整。
		{
			AvlNode<TKey, TValue> right = node.Right;
			AvlNode<TKey, TValue> rightLeft = right.Left;
			AvlNode<TKey, TValue> parent = node.Parent;

			right.Parent = parent;
			right.Left = node;
			node.Right = rightLeft;
			node.Parent = right;

			if (rightLeft != null)
			{
				rightLeft.Parent = node;
			}

			if (node == _root)
			{
				_root = right;
			}
			else if (parent.Right == node)
			{
				parent.Right = right;
			}
			else
			{
				parent.Left = right;
			}

			right.Balance++;
			node.Balance = -right.Balance;

			return right;
		}

		private AvlNode<TKey, TValue> RotateRight(AvlNode<TKey, TValue> node)//旋转操作,用于在树失去平衡时进行调整。
		{
			AvlNode<TKey, TValue> left = node.Left;
			AvlNode<TKey, TValue> leftRight = left.Right;
			AvlNode<TKey, TValue> parent = node.Parent;

			left.Parent = parent;
			left.Right = node;
			node.Left = leftRight;
			node.Parent = left;

			if (leftRight != null)
			{
				leftRight.Parent = node;
			}

			if (node == _root)
			{
				_root = left;
			}
			else if (parent.Left == node)
			{
				parent.Left = left;
			}
			else
			{
				parent.Right = left;
			}

			left.Balance--;
			node.Balance = -left.Balance;

			return left;
		}

		private AvlNode<TKey, TValue> RotateLeftRight(AvlNode<TKey, TValue> node)//旋转操作,用于在树失去平衡时进行调整。
		{
			AvlNode<TKey, TValue> left = node.Left;
			AvlNode<TKey, TValue> leftRight = left.Right;
			AvlNode<TKey, TValue> parent = node.Parent;
			AvlNode<TKey, TValue> leftRightRight = leftRight.Right;
			AvlNode<TKey, TValue> leftRightLeft = leftRight.Left;

			leftRight.Parent = parent;
			node.Left = leftRightRight;
			left.Right = leftRightLeft;
			leftRight.Left = left;
			leftRight.Right = node;
			left.Parent = leftRight;
			node.Parent = leftRight;

			if (leftRightRight != null)
			{
				leftRightRight.Parent = node;
			}

			if (leftRightLeft != null)
			{
				leftRightLeft.Parent = left;
			}

			if (node == _root)
			{
				_root = leftRight;
			}
			else if (parent.Left == node)
			{
				parent.Left = leftRight;
			}
			else
			{
				parent.Right = leftRight;
			}

			if (leftRight.Balance == -1)
			{
				node.Balance = 0;
				left.Balance = 1;
			}
			else if (leftRight.Balance == 0)
			{
				node.Balance = 0;
				left.Balance = 0;
			}
			else
			{
				node.Balance = -1;
				left.Balance = 0;
			}

			leftRight.Balance = 0;

			return leftRight;
		}

		private AvlNode<TKey, TValue> RotateRightLeft(AvlNode<TKey, TValue> node)//旋转操作,用于在树失去平衡时进行调整。
		{
			AvlNode<TKey, TValue> right = node.Right;
			AvlNode<TKey, TValue> rightLeft = right.Left;
			AvlNode<TKey, TValue> parent = node.Parent;
			AvlNode<TKey, TValue> rightLeftLeft = rightLeft.Left;
			AvlNode<TKey, TValue> rightLeftRight = rightLeft.Right;

			rightLeft.Parent = parent;
			node.Right = rightLeftLeft;
			right.Left = rightLeftRight;
			rightLeft.Right = right;
			rightLeft.Left = node;
			right.Parent = rightLeft;
			node.Parent = rightLeft;

			if (rightLeftLeft != null)
			{
				rightLeftLeft.Parent = node;
			}

			if (rightLeftRight != null)
			{
				rightLeftRight.Parent = right;
			}

			if (node == _root)
			{
				_root = rightLeft;
			}
			else if (parent.Right == node)
			{
				parent.Right = rightLeft;
			}
			else
			{
				parent.Left = rightLeft;
			}

			if (rightLeft.Balance == 1)
			{
				node.Balance = 0;
				right.Balance = -1;
			}
			else if (rightLeft.Balance == 0)
			{
				node.Balance = 0;
				right.Balance = 0;
			}
			else
			{
				node.Balance = 1;
				right.Balance = 0;
			}

			rightLeft.Balance = 0;

			return rightLeft;
		}

		public bool Delete(TKey key)//用于从AVL树中删除一个节点。删除节点后,可能会破坏树的平衡,因此会调用 `DeleteBalance` 方法进行平衡。
		{
			AvlNode<TKey, TValue> node = _root;

			while (node != null)
			{
				if (_comparer.Compare(key, node.Key) < 0)
				{
					node = node.Left;
				}
				else if (_comparer.Compare(key, node.Key) > 0)
				{
					node = node.Right;
				}
				else
				{
					AvlNode<TKey, TValue> left = node.Left;
					AvlNode<TKey, TValue> right = node.Right;

					if (left == null)
					{
						if (right == null)
						{
							if (node == _root)
							{
								_root = null;
							}
							else
							{
								AvlNode<TKey, TValue> parent = node.Parent;

								if (parent.Left == node)
								{
									parent.Left = null;

									DeleteBalance(parent, -1);
								}
								else
								{
									parent.Right = null;

									DeleteBalance(parent, 1);
								}
							}
						}
						else
						{
							Replace(node, right);

							DeleteBalance(node, 0);
						}
					}
					else if (right == null)
					{
						Replace(node, left);

						DeleteBalance(node, 0);
					}
					else
					{
						AvlNode<TKey, TValue> successor = right;

						if (successor.Left == null)
						{
							AvlNode<TKey, TValue> parent = node.Parent;

							successor.Parent = parent;
							successor.Left = left;
							successor.Balance = node.Balance;
							left.Parent = successor;

							if (node == _root)
							{
								_root = successor;
							}
							else
							{
								if (parent.Left == node)
								{
									parent.Left = successor;
								}
								else
								{
									parent.Right = successor;
								}
							}

							DeleteBalance(successor, 1);
						}
						else
						{
							while (successor.Left != null)
							{
								successor = successor.Left;
							}

							AvlNode<TKey, TValue> parent = node.Parent;
							AvlNode<TKey, TValue> successorParent = successor.Parent;
							AvlNode<TKey, TValue> successorRight = successor.Right;

							if (successorParent.Left == successor)
							{
								successorParent.Left = successorRight;
							}
							else
							{
								successorParent.Right = successorRight;
							}

							if (successorRight != null)
							{
								successorRight.Parent = successorParent;
							}

							successor.Parent = parent;
							successor.Left = left;
							successor.Balance = node.Balance;
							successor.Right = right;
							right.Parent = successor;
							left.Parent = successor;

							if (node == _root)
							{
								_root = successor;
							}
							else
							{
								if (parent.Left == node)
								{
									parent.Left = successor;
								}
								else
								{
									parent.Right = successor;
								}
							}

							DeleteBalance(successorParent, -1);
						}
					}

					return true;
				}
			}

			return false;
		}

		private void DeleteBalance(AvlNode<TKey, TValue> node, int balance)//用于在删除操作后重新平衡AVL树。
		{
			while (node != null)
			{
				balance = (node.Balance += balance);

				if (balance == 2)
				{
					if (node.Left.Balance >= 0)
					{
						node = RotateRight(node);

						if (node.Balance == -1)
						{
							return;
						}
					}
					else
					{
						node = RotateLeftRight(node);
					}
				}
				else if (balance == -2)
				{
					if (node.Right.Balance <= 0)
					{
						node = RotateLeft(node);

						if (node.Balance == 1)
						{
							return;
						}
					}
					else
					{
						node = RotateRightLeft(node);
					}
				}
				else if (balance != 0)
				{
					return;
				}

				AvlNode<TKey, TValue> parent = node.Parent;

				if (parent != null)
				{
					balance = parent.Left == node ? -1 : 1;
				}

				node = parent;
			}
		}

		private static void Replace(AvlNode<TKey, TValue> target, AvlNode<TKey, TValue> source)//在AVL树中替换一个节点为目标节点
		{
			AvlNode<TKey, TValue> left = source.Left;
			AvlNode<TKey, TValue> right = source.Right;

			target.Balance = source.Balance;
			target.Key = source.Key;
			target.Value = source.Value;
			target.Left = left;
			target.Right = right;

			if (left != null)
			{
				left.Parent = target;
			}

			if (right != null)
			{
				right.Parent = target;
			}
		}

		IEnumerator IEnumerable.GetEnumerator()//返回一个 `AvlNodeEnumerator` 实例,用于遍历AVL树。
		{
			return GetEnumerator();
		}
	}

以下测试类:

    public class AvlEnumeratorTests
    {
        [Fact]
        public void Sorting()
        {
            var tree = SetupTree(5, 4, 3, 2, 1);

            var enumerator = new AvlNodeEnumerator<int, int>(tree.Root);

            for (int i = 1; i <= 5; i++)
            {
                Assert.True(enumerator.MoveNext());

                Assert.Equal(i, enumerator.Current.Key);
            }

            Assert.False(enumerator.MoveNext());
            Assert.False(enumerator.MoveNext());
        }

        [Fact]
        public void Reset()
        {
            var tree = SetupTree(5, 4, 3, 2, 1);

            var enumerator = tree.GetEnumerator();

            int count1 = 0;

            while (enumerator.MoveNext())
            {
                count1++;
            }

            enumerator.Reset();

            int count2 = 0;

            while (enumerator.MoveNext())
            {
                count2++;
            }

            Assert.Equal(5, count1);
            Assert.Equal(5, count2);
        }

        [Fact]
        public void TreeForEach()
        {
            var tree = SetupTree(5, 4, 3,2, 1);

            int count = 0;

            foreach (var node in tree)
            {
                count++;

                Assert.Equal(count, node.Key);
            }

            Assert.Equal(5, count);
        }

        [Fact]
        public void LegacyEnumerator()
        {
            var tree = SetupTree(5, 4,3, 2, 1);
        int count = 0;

            IEnumerable<AvlNode<int, int>> enumerable = tree;

            IEnumerator<AvlNode<int, int>> enumerator = enumerable.GetEnumerator();

            while (enumerator.MoveNext())
            {
                count++;

                Assert.Equal(count, ((AvlNode<int, int>)enumerator.Current).Key);
            }

            Assert.Equal(5, count);
        }
    
        private AvlTree<int, int> SetupTree(params int[] values)
        {
            var tree = new AvlTree<int, int>();

            foreach (int value in values)
            {
                tree.Insert(value, value);
            }

            return tree;
        }
    }
public static class AvlNodeExtensions
{
    public static int Count<TKey>(this AvlNode<TKey, TKey> source)
    {
        int count = 1;

        AvlNode<TKey, TKey> left = source.Left;
        AvlNode<TKey, TKey> right = source.Right;

        if (right != null)
        {
            count += Count(left);
        }

        if (right != null)
        {
            count += Count(right);
        }

        return count;
    }
}

public class AvlTreeDeleteTests
{
    [Fact]
    public void ParentNullAndReplaceWithRight()
    {
        var tree = SetupTree(1, 2);

        AssertTreeValid("1-:{~,2}", tree);

        tree.Delete(1);

        AssertTreeValid("2", tree);
    }

    [Fact]
    public void ParentNullAndReplaceWithLeft()
    {
        var tree = SetupTree(2, 1);

        AssertTreeValid("2+:{1,~}", tree);

        tree.Delete(2);

        AssertTreeValid("1", tree);
    }

    [Fact]
    public void Empty()
    {
        var tree = SetupTree(1);

        AssertTreeValid("1", tree);

        tree.Delete(1);

        AssertTreeValid("", tree);
    }

    [Fact]
    public void NotFound()
    {
        var tree = SetupTree(1);

        AssertTreeValid("1", tree);

        tree.Delete(2);

        AssertTreeValid("1", tree);
    }

    [Fact]
    public void LeftRight()
    {
        var tree = SetupTree(4, 2, 5, 3);

        AssertTreeValid("4+:{2-:{~,3},5}", tree);

        tree.Delete(5);

        AssertTreeValid("3:{2,4}", tree);
    }

    [Fact]
    public void RightRight()
    {
        var tree = SetupTree(4, 2, 5, 6);

        AssertTreeValid("4-:{2,5-:{~,6}}", tree);

        tree.Delete(2);

        AssertTreeValid("5:{4,6}", tree);
    }

    [Fact]
    public void RightLeft()
    {
        var tree = SetupTree(4, 2, 6, 5);

        AssertTreeValid("4-:{2,6+:{5,~}}", tree);

        tree.Delete(2);

        AssertTreeValid("5:{4,6}", tree);
    }

    [Fact]
    public void LeftLeft()
    {
        var tree = SetupTree(4, 2, 5, 1);

        AssertTreeValid("4+:{2+:{1,~},5}", tree);

        tree.Delete(1);

        AssertTreeValid("4:{2,5}", tree);
    }

    [Fact]
    public void RightNull_NonNullParentToLeft()
    {
        var tree = SetupTree(9, 4, 20, 3, 19, 21, 27);

        AssertTreeValid("9-:{4+:{3,~},20-:{19,21-:{~,27}}}", tree);

        tree.Delete(4);

        AssertTreeValid("20:{9:{3,19},21-:{~,27}}", tree);
    }

    [Fact]
    public void RightNull_NonNullParentToRight()
    {
        var tree = SetupTree(9, 4, 20, 3, 5, 19, 2);

        AssertTreeValid("9+:{4+:{3+:{2,~},5},20+:{19,~}}", tree);

        tree.Delete(20);

        AssertTreeValid("4:{3+:{2,~},9:{5,19}}", tree);
    }

    [Fact]
    public void LeftNull_NonNullParentToRight()
    {
        var tree = SetupTree(9, 4, 20, 3, 5, 26, 2);

        AssertTreeValid("9+:{4+:{3+:{2,~},5},20-:{~,26}}", tree);

        tree.Delete(20);

        AssertTreeValid("4:{3+:{2,~},9:{5,26}}", tree);
    }

    [Fact]
    public void LeftNull_NonNullParentToLeft()
    {
        var tree = SetupTree(9, 4, 20, 5, 19, 21, 27);

        AssertTreeValid("9-:{4-:{~,5},20-:{19,21-:{~,27}}}", tree);

        tree.Delete(4);

        AssertTreeValid("20:{9:{5,19},21-:{~,27}}", tree);
    }

    [Fact]
    public void SuccessorLeftNull()
    {
        var tree = SetupTree(20, 4, 26);

        AssertTreeValid("20:{4,26}", tree);

        tree.Delete(20);

        AssertTreeValid("26+:{4,~}", tree);
    }

    [Fact]
    public void LeftParentSuccessorLeftNull()
    {
        var tree = SetupTree(20, 10, 40, 30, 50);

        AssertTreeValid("20-:{10,40:{30,50}}", tree);

        tree.Delete(40);

        AssertTreeValid("20-:{10,50+:{30,~}}", tree);
    }

    [Fact]
    public void RightParentSuccessorLeftNull()
    {
        var tree = SetupTree(20, 10, 40, 5, 15);

        AssertTreeValid("20+:{10:{5,15},40}", tree);

        tree.Delete(10);

        AssertTreeValid("20+:{15+:{5,~},40}", tree);
    }

    [Fact]
    public void SuccessorRight()
    {
        var tree = SetupTree(20, 4, 26, 25);

        AssertTreeValid("20-:{4,26+:{25,~}}", tree);

        tree.Delete(20);

        AssertTreeValid("25:{4,26}", tree);
    }

    [Fact]
    public void RightParentSuccessorRight()
    {
        var tree = SetupTree(20, 10, 40, 15, 30, 50, 45);

        AssertTreeValid("20-:{10-:{~,15},40-:{30,50+:{45,~}}}", tree);

        tree.Delete(40);

        AssertTreeValid("20:{10-:{~,15},45:{30,50}}", tree);
    }

    [Fact]
    public void LeftParentSuccessorRight()
    {
        var tree = SetupTree(20, 10, 40, 5, 15, 30, 14);

        AssertTreeValid("20+:{10-:{5,15+:{14,~}},40+:{30,~}}", tree);

        tree.Delete(10);

        AssertTreeValid("20:{14:{5,15},40+:{30,~}}", tree);
    }


    [Fact]
    public void ExitRebalanceRightEarly()
    {
        var tree = SetupTree(20, 10, 30, 5, 15, 35, 4, 16);

        AssertTreeValid("20+:{10:{5+:{4,~},15-:{~,16}},30-:{~,35}}", tree);

        tree.Delete(35);

        AssertTreeValid("10-:{5+:{4,~},20+:{15-:{~,16},30}}", tree);
    }

    [Fact]
    public void ExitRebalanceLeftEarly()
    {
        var tree = SetupTree(20, 10, 30, 5, 25, 35, 24, 36);

        AssertTreeValid("20-:{10+:{5,~},30:{25+:{24,~},35-:{~,36}}}", tree);

        tree.Delete(5);

        AssertTreeValid("30+:{20-:{10,25+:{24,~}},35-:{~,36}}", tree);
    }

    private void AssertTreeValid(string description, AvlTree<int, int> tree)
    {
        Console.WriteLine(tree.Description());

        Assert.Equal(description, tree.Description());

        if (tree.Root != null)
        {
            Assert.Null(tree.Root.Parent);
        }
        else if (description == "")
        {
            Assert.Null(tree.Root);
        }
    }

    private AvlTree<int, int> SetupTree(params int[] values)
    {
        var tree = new AvlTree<int, int>();

        foreach (int value in values)
        {
            tree.Insert(value);
        }

        return tree;
    }
}

public static class AvlTreeExtensions
{
    public static string Description<TKey>(this AvlTree<TKey, TKey> tree)
    {
        StringBuilder builder = new StringBuilder();

        Description(builder, tree.Root);

        return builder.ToString();
    }

    public static bool Insert<TKey>(this AvlTree<TKey, TKey> source, TKey key)
    {
        return source.Insert(key, key);
    }

    public static int Count<TKey>(this AvlTree<TKey, TKey> source)
    {
        AvlNode<TKey, TKey> node = source.Root;

        if (node == null)
        {
            return 0;
        }
        else
        {
            return node.Count();
        }
    }

    private static void Description<TKey>(StringBuilder builder, AvlNode<TKey, TKey> node)
    {
        if (node != null)
        {
            builder.Append(node.Key);

            for (int i = 0; i < node.Balance; i++)
            {
                builder.Append("+");
            }

            for (int i = node.Balance; i < 0; i++)
            {
                builder.Append("-");
            }

            if (node.Left != null || node.Right != null)
            {
                builder.Append(":{");

                if (node.Left == null)
                {
                    builder.Append("~");
                }
                else
                {
                    Description(builder, node.Left);
                }

                builder.Append(",");

                if (node.Right == null)
                {
                    builder.Append("~");
                }
                else
                {
                    Description(builder, node.Right);
                }

                builder.Append("}");
            }
        }
    }
}

public class AvlTreeInsertTests
{
    [Fact]
    public void Empty()
    {
        var tree = new AvlTree<int, int>();

        Assert.Equal(0, tree.Count());
        AssertTreeValid("", tree);
    }

    [Fact]
    public void CountMultiple()
    {
        var tree = SetupTree(20, 8, 22);

        Assert.Equal(3, tree.Count());
    }

    [Fact]
    public void DuplicateFails()
    {
        var tree = new AvlTree<int, int>();

        bool success0a = tree.Insert(0);
        bool success0b = tree.Insert(0);

        Assert.True(success0a);
        Assert.False(success0b);

        AssertTreeValid("0", tree);
    }

    [Fact]
    public void LeftLeft()
    {
        var tree = SetupTree(20, 8);

        AssertTreeValid("20+:{8,~}", tree);

        tree.Insert(4);

        AssertTreeValid("8:{4,20}", tree);
    }

    [Fact]
    public void LeftRight()
    {
        var tree = SetupTree(20, 4);

        AssertTreeValid("20+:{4,~}", tree);

        tree.Insert(8);

        AssertTreeValid("8:{4,20}", tree);
    }

    [Fact]
    public void RightLeft()
    {
        var tree = SetupTree(4, 20);

        AssertTreeValid("4-:{~,20}", tree);

        tree.Insert(8);

        AssertTreeValid("8:{4,20}", tree);
    }

    [Fact]
    public void RightRight()
    {
        var tree = SetupTree(4, 8);

        AssertTreeValid("4-:{~,8}", tree);

        tree.Insert(20);

        AssertTreeValid("8:{4,20}", tree);
    }

    [Fact]
    public void RootLeftRightRight()
    {
        var tree = SetupTree(20, 4, 26, 3, 9);

        AssertTreeValid("20+:{4:{3,9},26}", tree);

        tree.Insert(15);

        AssertTreeValid("9:{4+:{3,~},20:{15,26}}", tree);
    }

    [Fact]
    public void RootLeftRightLeft()
    {
        var tree = SetupTree(20, 4, 26, 3, 9);

        AssertTreeValid("20+:{4:{3,9},26}", tree);

        tree.Insert(8);

        AssertTreeValid("9:{4:{3,8},20-:{~,26}}", tree);
    }

    [Fact]
    public void RootRightLeftLeft()
    {
        var tree = SetupTree(20, 4, 26, 24, 30);

        AssertTreeValid("20-:{4,26:{24,30}}", tree);

        tree.Insert(23);

        AssertTreeValid("24:{20:{4,23},26-:{~,30}}", tree);
    }

    [Fact]
    public void RootRightLeftRight()
    {
        var tree = SetupTree(20, 4, 26, 24, 30);

        AssertTreeValid("20-:{4,26:{24,30}}", tree);

        tree.Insert(25);

        AssertTreeValid("24:{20+:{4,~},26:{25,30}}", tree);
    }

    [Fact]
    public void RightParentedLeftLeft()
    {
        var tree = SetupTree(2, 1, 20, 8);

        AssertTreeValid("2-:{1,20+:{8,~}}", tree);

        tree.Insert(4);

        AssertTreeValid("2-:{1,8:{4,20}}", tree);
    }

    [Fact]
    public void LeftParentedLeftLeft()
    {
        var tree = SetupTree(24, 28, 20, 8);

        AssertTreeValid("24+:{20+:{8,~},28}", tree);

        tree.Insert(4);

        AssertTreeValid("24+:{8:{4,20},28}", tree);
    }

    [Fact]
    public void LeftParentedLeftRight()
    {
        var tree = SetupTree(24, 28, 20, 4);

        AssertTreeValid("24+:{20+:{4,~},28}", tree);

        tree.Insert(8);

        AssertTreeValid("24+:{8:{4,20},28}", tree);
    }

    [Fact]
    public void RightParentedLeftRight()
    {
        var tree = SetupTree(2, 1, 20, 4);

        AssertTreeValid("2-:{1,20+:{4,~}}", tree);

        tree.Insert(8);

        AssertTreeValid("2-:{1,8:{4,20}}", tree);
    }

    [Fact]
    public void LeftParentedRightLeft()
    {
        var tree = SetupTree(24, 28, 4, 20);

        AssertTreeValid("24+:{4-:{~,20},28}", tree);

        tree.Insert(8);

        AssertTreeValid("24+:{8:{4,20},28}", tree);
    }

    [Fact]
    public void RightParentedRightLeft()
    {
        var tree = SetupTree(2, 1, 4, 20);

        AssertTreeValid("2-:{1,4-:{~,20}}", tree);

        tree.Insert(8);

        AssertTreeValid("2-:{1,8:{4,20}}", tree);
    }

    [Fact]
    public void LeftParentedRightRight()
    {
        var tree = SetupTree(24, 28, 4, 8);

        AssertTreeValid("24+:{4-:{~,8},28}", tree);

        tree.Insert(20);

        AssertTreeValid("24+:{8:{4,20},28}", tree);
    }

    [Fact]
    public void RightParentedRightRight()
    {
        var tree = SetupTree(2, 1, 4, 8);

        AssertTreeValid("2-:{1,4-:{~,8}}", tree);

        tree.Insert(20);

        AssertTreeValid("2-:{1,8:{4,20}}", tree);
    }

    private void AssertTreeValid(string description, AvlTree<int, int> tree)
    {
        Assert.Equal(description, tree.Description());

        if (tree.Root != null)
        {
            Assert.Null(tree.Root.Parent);
        }
        else if (description == "")
        {
            Assert.Null(tree.Root);
        }
    }

    private AvlTree<int, int> SetupTree(params int[] values)
    {
        var tree = new AvlTree<int, int>();

        foreach (int value in values)
        {
            tree.Insert(value);
        }

        return tree;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值