上次的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;
}
}