AVL树在C#中的表现 [英] Performance of an AVL Tree in C#
问题描述
我已经实现AVL树在C#中的插入矩阵如下
的拍摄时间元素数量插入(秒)
-------------------------------------------------- ----
10 0.067
100 0.073
200 0.112
500 0.388
900 1.205
1000 1.466
5000 44.314
10000 195.435
现在我的问题是,它是一个AVL树有不错的表现还是我必须重新考虑改变算法或重构code?
编辑: 元素是整数,从0开始到移位#of元件 测试code如下:
[测试]
公共无效InsertionTest()
{
AVLTree< INT> _tree =新AVLTree<诠释>();
_stopWatch.Start();
的for(int i = 0; I< 5000;我++){
_tree.Add(ⅰ);
}
_stopWatch.Stop();
Console.WriteLine(时代取=+ _stopWatch.Elapsed);
}
编辑:实现code
BinarySearchTree
[Serializable接口]
公共类BinarySearchTree< T> :ICollection的< T>
{
私人只读的Comparer< T> _comparer =的Comparer< T> .DEFAULT;
公共BinarySearchTree()
{
}
公共BinarySearchTree(IEnumerable的< T>集合)
{
的AddRange(collection.ToArray());
}
公共BinarySearchTree(的Comparer< T>比较器)
{
_comparer =比较器;
}
公共BinaryTreeNode< T>根{获得;保护套; }
#地区的ICollection< T>会员
///<总结>
///增加一个项目的<看到CREF =T:System.Collections.Generic.ICollection`1/取代。
///< /总结>
///<参数名称=值>到添加到对象的<看到CREF =T:System.Collections.Generic.ICollection`1/取代。
///< /参数>
///<异常CREF =T:System.NotSupportedException>的<看到CREF =T:System.Collections.Generic.ICollection`1/>为只读。
///< /异常>
公共虚拟无效添加(T值)
{
变种N =新BinaryTreeNode< T>(值);
INT结果;
BinaryTreeNode< T>目前=根,父= NULL;
而(电流!= NULL)
{
结果= _comparer.Compare(current.Value,价值);
如果(结果== 0)
{
父=电流;
电流= current.Left;
}
如果(结果大于0)
{
父=电流;
电流= current.Left;
}
否则如果(结果℃,)
{
父=电流;
电流= current.Right;
}
}
伯爵++;
如果(家长== NULL)
根= N;
其他
{
结果= _comparer.Compare(parent.Value,价值);
如果(结果大于0)
parent.Left = N;
其他
parent.Right = N;
}
}
///<总结>
///移除的&lt所有项目;看到CREF =T:System.Collections.Generic.ICollection`1/取代。
///< /总结>
///<异常CREF =T:System.NotSupportedException>的<看到CREF =T:System.Collections.Generic.ICollection`1/>为只读。
///< /异常>
公共无效清除()
{
根= NULL;
计数= 0;
}
///<总结>
///确定是否在<看到CREF =T:System.Collections.Generic.ICollection`1/>包含特定值。
///< /总结>
///<返回>
///真实的,如果< paramref名称=项/>被发现在<见的cref =T:System.Collections.Generic.ICollection`1/取代;否则为false。
///< /回报>
///< PARAM NAME =项目>在定位对象的<看到CREF =T:System.Collections.Generic.ICollection`1/取代。
///< /参数>
公共虚拟BOOL包含(T项)
{
BinaryTreeNode< T>电流=根;
而(电流!= NULL)
{
INT结果= _comparer.Compare(current.Value,项目);
如果(结果== 0)
返回true;
如果(结果大于0)
电流= current.Left;
否则如果(结果℃,)
电流= current.Right;
}
返回false;
}
公共无效CopyTo从(T []数组,INT指数)
{
CopyTo从(数组,索引,BinaryTreeTraversalType.InOrder);
}
///<总结>
///移除的&lt特定对象的第一个匹配;看到CREF =T:System.Collections.Generic.ICollection`1/取代。
///< /总结>
///<返回>
///真实的,如果< paramref名称=项/>成功地从在&lt删除;看到CREF =T:System.Collections.Generic.ICollection`1/取代;否则为false。这种方法也返回假,如果< paramref名称=项/>未在原始&其中找到;见的cref =T:System.Collections.Generic.ICollection`1/取代。
///< /回报>
///&所述; PARAM NAME =项>将对象从在&lt除去;见的cref =T:System.Collections.Generic.ICollection`1/取代。
///< /参数>
///<异常CREF =T:System.NotSupportedException>的<看到CREF =T:System.Collections.Generic.ICollection`1/>为只读。
///< /异常>
公共虚拟BOOL删除(T项目)
{
如果(根== NULL)
返回false;
BinaryTreeNode< T>目前=根,父= NULL;
INT结果= _comparer.Compare(current.Value,项目);
而(结果!= 0)
{
如果(结果大于0)
{
父=电流;
电流= current.Left;
}
否则如果(结果℃,)
{
父=电流;
电流= current.Right;
}
如果(当前== NULL)
返回false;
结果= _comparer.Compare(current.Value,项目);
}
计数 - ;
//现在我们需要再穿入树
//案例1:如果当前没有合适的孩子,那么当前的左子变
//指向的节点由父
如果(current.Right == NULL)
{
如果(家长== NULL)
根= current.Left;
其他
{
结果= _comparer.Compare(parent.Value,current.Value);
如果(结果大于0)
parent.Left = current.Left;
否则如果(结果℃,)
parent.Right = current.Left;
}
//案例2:如果当前的右孩子没有左孩子,那么当前的右子
//替换目前的在树
}
否则,如果(current.Right.Left == NULL)
{
current.Right.Left = current.Left;
如果(家长== NULL)
根= current.Right;
其他
{
结果= _comparer.Compare(parent.Value,current.Value);
如果(结果大于0)
parent.Left = current.Right;
否则如果(结果℃,)
parent.Right = current.Right;
}
//案例3:如果当前的右孩子有左孩子,取代目前现行的
//右孩子的最左边的后代
}
其他
{
BinaryTreeNode< T>最左边= current.Right.Left,lmParent = current.Right;
而(leftmost.Left!= NULL)
{
lmParent =最左边;
最左边= leftmost.Left;
}
lmParent.Left = leftmost.Right;
leftmost.Left = current.Left;
leftmost.Right = current.Right;
如果(家长== NULL)
根=最左边;
其他
{
结果= _comparer.Compare(parent.Value,current.Value);
如果(结果大于0)
parent.Left =最左边;
否则如果(结果℃,)
parent.Right =最左边;
}
}
current.Left = current.Right = NULL;
返回true;
}
///<总结>
///获取包含在&lt元件的数量;见的cref =T:System.Collections.Generic.ICollection`1/取代。
///< /总结>
///<返回>
///包含在&lt元素的数目;见的cref =T:System.Collections.Generic.ICollection`1/取代。
///< /回报>
公众诠释计数{获得;私定; }
///<总结>
///获取一个值,指示是否在<看到CREF =T:System.Collections.Generic.ICollection`1/>为只读。
///< /总结>
///<返回>
/// true,如果在<看到CREF =T:System.Collections.Generic.ICollection`1/>是只读;否则为false。
///< /回报>
公共BOOL的IsReadOnly
{
获得{返回false; }
}
#endregion
公共无效的AddRange(IEnumerable的< T>项目)
{
的foreach(在项目VAR项)
{
添加(项目);
}
}
公共无效CopyTo从(T []数组,INT指数,BinaryTreeTraversalType traversalType)
{
Root.ToEnumerable(traversalType)。选择(X => x.Value)。.ToArray()CopyTo从(数组索引);
}
公共BinaryTreeNode< T>查找(T值)
{
BinaryTreeNode< T>电流=根;
而(电流!= NULL)
{
INT结果= _comparer.Compare(current.Value,价值);
如果(结果== 0)
返回电流;
如果(结果大于0)
电流= current.Left;
否则如果(结果℃,)
电流= current.Right;
}
返回null;
}
的IEnumerable的#地区实施
///<总结>
///通过收集返回一个枚举迭代。
///< /总结>
///<返回>
/// A<见CREF =T:System.Collections.Generic.IEnumerator`1/>可用于遍历集合。
///< /回报>
///&其中; filterpriority→1&其中; / filterpriority>
公众的IEnumerator< T>的GetEnumerator()
{
返回Root.ToEnumerable(BinaryTreeTraversalType.InOrder)。选择(X => x.Value).GetEnumerator();
}
///<总结>
///通过集合返回一个枚举迭代。
///< /总结>
///<返回>
///一个<见CREF =T:System.Collections.IEnumerator/>对象可用于遍历集合。
///< /回报>
///&其中; filterpriority→2&其中; / filterpriority>
IEnumerator的IEnumerable.GetEnumerator()
{
返回的GetEnumerator();
}
#endregion
}
AVLTree
公共类AVLTree< T> :BinarySearchTree< T>
{
公共AVLTree()
{
}
公共AVLTree(IEnumerable的< T>集合)
:基地(集合)
{
}
公共AVLTree(的Comparer< T>比较器)
:基地(比较器)
{
}
公众覆盖无效添加(T值)
{
base.Add(值);
VAR节点=查找(值);
是AbstractNode< T> parentNode = node.Parent;
而(parentNode!= NULL)
{
INT余额=为getBalance(parentNode为BinaryTreeNode< T>);
如果(Math.Abs(余量)== 2)
{
BalanceAt(parentNode为BinaryTreeNode< T&GT ;,平衡);
}
parentNode = parentNode.Parent;
}
}
公众覆盖BOOL删除(T项目)
{
如果(根== NULL)
返回false;
BinaryTreeNode< T> valueNode =查找(项目);
是AbstractNode< T> parentNode = valueNode.Parent;
布尔删除= base.Remove(项目);
如果(!删除)
返回false;
而(parentNode!= NULL)
{
INT余额=为getBalance(parentNode为BinaryTreeNode< T>);
如果(Math.Abs(余量)== 1)
打破;
如果(Math.Abs(余量)== 2)
{
BalanceAt(parentNode为BinaryTreeNode< T&GT ;,平衡);
}
parentNode = parentNode.Parent;
}
返回true;
}
///<总结>
///余额AVL树节点
///< /总结>
受保护的虚拟无效BalanceAt(BinaryTreeNode< T>节点,INT余额)
{
如果(余量== 2)
{
INT rightBalance =为getBalance(node.Right);
如果(rightBalance == 1 || rightBalance == 0)
{
RotateLeft(节点);
}
否则,如果(rightBalance == -1)
{
RotateRight(node.Right);
RotateLeft(节点);
}
}
否则,如果(平衡== -2)
{
INT leftBalance =为getBalance(node.Left);
如果(leftBalance == 1)
{
RotateLeft(node.Left);
RotateRight(节点);
}
否则,如果(leftBalance == -1 || leftBalance == 0)
{
RotateRight(节点);
}
}
}
///<总结>
///确定给定节点的平衡
///< /总结>
受保护的虚拟INT所以getBalance(BinaryTreeNode< T>节点)
{
如果(节点!= NULL)
{
IEnumerable的< BinaryTreeNode< T>> leftSubtree = NULL,righSubtree = NULL;
如果(node.Left!= NULL)
leftSubtree = node.Left.ToEnumerable(BinaryTreeTraversalType.InOrder);
如果(node.Right!= NULL)
righSubtree = node.Right.ToEnumerable(BinaryTreeTraversalType.InOrder);
// ReSharper的禁用AssignNullToNotNullAttribute
VAR leftHeight = leftSubtree.IsNullOrEmpty()? 0:leftSubtree.Max(X => x.Depth) - node.Depth;
VAR righHeight = righSubtree.IsNullOrEmpty()? 0:righSubtree.Max(X => x.Depth) - node.Depth;
// ReSharper的恢复AssignNullToNotNullAttribute
返回righHeight - leftHeight;
}
返回0;
}
///<总结>
///旋转内的AVL树的节点向左
///< /总结>
受保护的虚拟无效RotateLeft(BinaryTreeNode< T>节点)
{
如果(节点== NULL)
返回;
BinaryTreeNode< T>透视= node.Right;
如果(支点== NULL)
返回;
VAR rootParent = node.Parent为BinaryTreeNode< T&GT ;;
布尔isLeftChild =(rootParent!= NULL)及和放大器; rootParent.Left ==节点;
布尔makeTreeRoot =节点==根;
node.Right = pivot.Left;
pivot.Left =节点;
node.Parent =支点;
pivot.Parent = rootParent;
如果(node.Right!= NULL)
node.Right.Parent =节点;
如果(makeTreeRoot)
根=支点;
如果(isLeftChild)
rootParent.Left =支点;
否则,如果(rootParent!= NULL)
rootParent.Right =支点;
}
///<总结>
///旋转一个节点内的AVL树权
///< /总结>
受保护的虚拟无效RotateRight(BinaryTreeNode< T>节点)
{
如果(节点== NULL)
返回;
BinaryTreeNode< T>透视= node.Left;
如果(支点== NULL)
返回;
VAR rootParent = node.Parent为BinaryTreeNode< T&GT ;;
布尔isLeftChild =(rootParent!= NULL)及和放大器; rootParent.Left ==节点;
布尔makeTreeRoot =根==节点;
node.Left = pivot.Right;
pivot.Right =节点;
node.Parent =支点;
pivot.Parent = rootParent;
如果(node.Left!= NULL)
node.Left.Parent =节点;
如果(makeTreeRoot)
根=支点;
如果(isLeftChild)
rootParent.Left =支点;
否则,如果(rootParent!= NULL)
rootParent.Right =支点;
}
}
标杆code在.NET中,您需要考虑到JIT编译时间。要做到这一点最简单的方法,就是让你的测试code运行code的两倍 - 并丢弃第一时序结果
这一边 - 你的基准测试结果似乎暗示增幅比预期的更糟糕Ò(log n)的时间AVL树插入
你什么都没有张贴在这里是code为 BinaryTreeNode<>
类。我怀疑你可能有一些有方法的实现一个问题 - 我特别可疑像深物业的
和 ToEnumerable
。
I have implemented an AVL tree in C# whose insertion matrix is as follows
Number of Elements Time taken to insert (sec)
------------------------------------------------------
10 0.067
100 0.073
200 0.112
500 0.388
900 1.205
1000 1.466
5000 44.314
10000 195.435
Now my question is, is it a good performance for an AVL tree or do I have to re-consider changing the algorithm or refactoring the code?
Edit: The elements are integer starting from 0 to #of elements Test code is as follows
[Test]
public void InsertionTest()
{
AVLTree<int> _tree = new AVLTree<int>();
_stopWatch.Start();
for (int i = 0; i < 5000; i++) {
_tree.Add(i);
}
_stopWatch.Stop();
Console.WriteLine("Time taken = " + _stopWatch.Elapsed);
}
Edit: Implementation code
BinarySearchTree
[Serializable]
public class BinarySearchTree<T> : ICollection<T>
{
private readonly Comparer<T> _comparer = Comparer<T>.Default;
public BinarySearchTree()
{
}
public BinarySearchTree(IEnumerable<T> collection)
{
AddRange(collection.ToArray());
}
public BinarySearchTree(Comparer<T> comparer)
{
_comparer = comparer;
}
public BinaryTreeNode<T> Root { get; protected set; }
#region ICollection<T> Members
/// <summary>
/// Adds an item to the <see cref = "T:System.Collections.Generic.ICollection`1" />.
/// </summary>
/// <param name = "value">The object to add to the <see cref = "T:System.Collections.Generic.ICollection`1" />.
/// </param>
/// <exception cref = "T:System.NotSupportedException">The <see cref = "T:System.Collections.Generic.ICollection`1" /> is read-only.
/// </exception>
public virtual void Add(T value)
{
var n = new BinaryTreeNode<T>(value);
int result;
BinaryTreeNode<T> current = Root, parent = null;
while (current != null)
{
result = _comparer.Compare(current.Value, value);
if (result == 0)
{
parent = current;
current = current.Left;
}
if (result > 0)
{
parent = current;
current = current.Left;
}
else if (result < 0)
{
parent = current;
current = current.Right;
}
}
Count++;
if (parent == null)
Root = n;
else
{
result = _comparer.Compare(parent.Value, value);
if (result > 0)
parent.Left = n;
else
parent.Right = n;
}
}
/// <summary>
/// Removes all items from the <see cref = "T:System.Collections.Generic.ICollection`1" />.
/// </summary>
/// <exception cref = "T:System.NotSupportedException">The <see cref = "T:System.Collections.Generic.ICollection`1" /> is read-only.
/// </exception>
public void Clear()
{
Root = null;
Count = 0;
}
/// <summary>
/// Determines whether the <see cref = "T:System.Collections.Generic.ICollection`1" /> contains a specific value.
/// </summary>
/// <returns>
/// true if <paramref name = "item" /> is found in the <see cref = "T:System.Collections.Generic.ICollection`1" />; otherwise, false.
/// </returns>
/// <param name = "item">The object to locate in the <see cref = "T:System.Collections.Generic.ICollection`1" />.
/// </param>
public virtual bool Contains(T item)
{
BinaryTreeNode<T> current = Root;
while (current != null)
{
int result = _comparer.Compare(current.Value, item);
if (result == 0)
return true;
if (result > 0)
current = current.Left;
else if (result < 0)
current = current.Right;
}
return false;
}
public void CopyTo(T[] array, int index)
{
CopyTo(array, index, BinaryTreeTraversalType.InOrder);
}
/// <summary>
/// Removes the first occurrence of a specific object from the <see cref = "T:System.Collections.Generic.ICollection`1" />.
/// </summary>
/// <returns>
/// true if <paramref name = "item" /> was successfully removed from the <see cref = "T:System.Collections.Generic.ICollection`1" />; otherwise, false. This method also returns false if <paramref name = "item" /> is not found in the original <see cref = "T:System.Collections.Generic.ICollection`1" />.
/// </returns>
/// <param name = "item">The object to remove from the <see cref = "T:System.Collections.Generic.ICollection`1" />.
/// </param>
/// <exception cref = "T:System.NotSupportedException">The <see cref = "T:System.Collections.Generic.ICollection`1" /> is read-only.
/// </exception>
public virtual bool Remove(T item)
{
if (Root == null)
return false;
BinaryTreeNode<T> current = Root, parent = null;
int result = _comparer.Compare(current.Value, item);
while (result != 0)
{
if (result > 0)
{
parent = current;
current = current.Left;
}
else if (result < 0)
{
parent = current;
current = current.Right;
}
if (current == null)
return false;
result = _comparer.Compare(current.Value, item);
}
Count--;
// We now need to "rethread" the tree
// CASE 1: If current has no right child, then current's left child becomes
// the node pointed to by the parent
if (current.Right == null)
{
if (parent == null)
Root = current.Left;
else
{
result = _comparer.Compare(parent.Value, current.Value);
if (result > 0)
parent.Left = current.Left;
else if (result < 0)
parent.Right = current.Left;
}
// CASE 2: If current's right child has no left child, then current's right child
// replaces current in the tree
}
else if (current.Right.Left == null)
{
current.Right.Left = current.Left;
if (parent == null)
Root = current.Right;
else
{
result = _comparer.Compare(parent.Value, current.Value);
if (result > 0)
parent.Left = current.Right;
else if (result < 0)
parent.Right = current.Right;
}
// CASE 3: If current's right child has a left child, replace current with current's
// right child's left-most descendent
}
else
{
BinaryTreeNode<T> leftmost = current.Right.Left, lmParent = current.Right;
while (leftmost.Left != null)
{
lmParent = leftmost;
leftmost = leftmost.Left;
}
lmParent.Left = leftmost.Right;
leftmost.Left = current.Left;
leftmost.Right = current.Right;
if (parent == null)
Root = leftmost;
else
{
result = _comparer.Compare(parent.Value, current.Value);
if (result > 0)
parent.Left = leftmost;
else if (result < 0)
parent.Right = leftmost;
}
}
current.Left = current.Right = null;
return true;
}
/// <summary>
/// Gets the number of elements contained in the <see cref = "T:System.Collections.Generic.ICollection`1" />.
/// </summary>
/// <returns>
/// The number of elements contained in the <see cref = "T:System.Collections.Generic.ICollection`1" />.
/// </returns>
public int Count { get; private set; }
/// <summary>
/// Gets a value indicating whether the <see cref = "T:System.Collections.Generic.ICollection`1" /> is read-only.
/// </summary>
/// <returns>
/// true if the <see cref = "T:System.Collections.Generic.ICollection`1" /> is read-only; otherwise, false.
/// </returns>
public bool IsReadOnly
{
get { return false; }
}
#endregion
public void AddRange(IEnumerable<T> items)
{
foreach (var item in items)
{
Add(item);
}
}
public void CopyTo(T[] array, int index, BinaryTreeTraversalType traversalType)
{
Root.ToEnumerable(traversalType).Select(x => x.Value).ToArray().CopyTo(array, index);
}
public BinaryTreeNode<T> Find(T value)
{
BinaryTreeNode<T> current = Root;
while (current != null)
{
int result = _comparer.Compare(current.Value, value);
if (result == 0)
return current;
if (result > 0)
current = current.Left;
else if (result < 0)
current = current.Right;
}
return null;
}
#region Implementation of IEnumerable
/// <summary>
/// Returns an enumerator that iterates through the collection.
/// </summary>
/// <returns>
/// A <see cref = "T:System.Collections.Generic.IEnumerator`1" /> that can be used to iterate through the collection.
/// </returns>
/// <filterpriority>1</filterpriority>
public IEnumerator<T> GetEnumerator()
{
return Root.ToEnumerable(BinaryTreeTraversalType.InOrder).Select(x => x.Value).GetEnumerator();
}
/// <summary>
/// Returns an enumerator that iterates through a collection.
/// </summary>
/// <returns>
/// An <see cref = "T:System.Collections.IEnumerator" /> object that can be used to iterate through the collection.
/// </returns>
/// <filterpriority>2</filterpriority>
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
#endregion
}
AVLTree
public class AVLTree<T> : BinarySearchTree<T>
{
public AVLTree()
{
}
public AVLTree(IEnumerable<T> collection)
: base(collection)
{
}
public AVLTree(Comparer<T> comparer)
: base(comparer)
{
}
public override void Add(T value)
{
base.Add(value);
var node = Find(value);
AbstractNode<T> parentNode = node.Parent;
while (parentNode != null)
{
int balance = GetBalance(parentNode as BinaryTreeNode<T>);
if (Math.Abs(balance) == 2)
{
BalanceAt(parentNode as BinaryTreeNode<T>, balance);
}
parentNode = parentNode.Parent;
}
}
public override bool Remove(T item)
{
if (Root == null)
return false;
BinaryTreeNode<T> valueNode = Find(item);
AbstractNode<T> parentNode = valueNode.Parent;
bool removed = base.Remove(item);
if (!removed)
return false;
while (parentNode != null)
{
int balance = GetBalance(parentNode as BinaryTreeNode<T>);
if (Math.Abs(balance) == 1)
break;
if (Math.Abs(balance) == 2)
{
BalanceAt(parentNode as BinaryTreeNode<T>, balance);
}
parentNode = parentNode.Parent;
}
return true;
}
/// <summary>
/// Balances an AVL Tree node
/// </summary>
protected virtual void BalanceAt(BinaryTreeNode<T> node, int balance)
{
if (balance == 2)
{
int rightBalance = GetBalance(node.Right);
if (rightBalance == 1 || rightBalance == 0)
{
RotateLeft(node);
}
else if (rightBalance == -1)
{
RotateRight(node.Right);
RotateLeft(node);
}
}
else if (balance == -2)
{
int leftBalance = GetBalance(node.Left);
if (leftBalance == 1)
{
RotateLeft(node.Left);
RotateRight(node);
}
else if (leftBalance == -1 || leftBalance == 0)
{
RotateRight(node);
}
}
}
/// <summary>
/// Determines the balance of a given node
/// </summary>
protected virtual int GetBalance(BinaryTreeNode<T> node)
{
if(node != null)
{
IEnumerable<BinaryTreeNode<T>> leftSubtree = null, righSubtree = null;
if (node.Left != null)
leftSubtree = node.Left.ToEnumerable(BinaryTreeTraversalType.InOrder);
if (node.Right != null)
righSubtree = node.Right.ToEnumerable(BinaryTreeTraversalType.InOrder);
// ReSharper disable AssignNullToNotNullAttribute
var leftHeight = leftSubtree.IsNullOrEmpty() ? 0 : leftSubtree.Max(x => x.Depth) - node.Depth;
var righHeight = righSubtree.IsNullOrEmpty() ? 0 : righSubtree.Max(x => x.Depth) - node.Depth;
// ReSharper restore AssignNullToNotNullAttribute
return righHeight - leftHeight;
}
return 0;
}
/// <summary>
/// Rotates a node to the left within an AVL Tree
/// </summary>
protected virtual void RotateLeft(BinaryTreeNode<T> node)
{
if (node == null)
return;
BinaryTreeNode<T> pivot = node.Right;
if (pivot == null)
return;
var rootParent = node.Parent as BinaryTreeNode<T>;
bool isLeftChild = (rootParent != null) && rootParent.Left == node;
bool makeTreeRoot = node == Root;
node.Right = pivot.Left;
pivot.Left = node;
node.Parent = pivot;
pivot.Parent = rootParent;
if (node.Right != null)
node.Right.Parent = node;
if (makeTreeRoot)
Root = pivot;
if (isLeftChild)
rootParent.Left = pivot;
else if (rootParent != null)
rootParent.Right = pivot;
}
/// <summary>
/// Rotates a node to the right within an AVL Tree
/// </summary>
protected virtual void RotateRight(BinaryTreeNode<T> node)
{
if (node == null)
return;
BinaryTreeNode<T> pivot = node.Left;
if (pivot == null)
return;
var rootParent = node.Parent as BinaryTreeNode<T>;
bool isLeftChild = (rootParent != null) && rootParent.Left == node;
bool makeTreeRoot = Root == node;
node.Left = pivot.Right;
pivot.Right = node;
node.Parent = pivot;
pivot.Parent = rootParent;
if (node.Left != null)
node.Left.Parent = node;
if (makeTreeRoot)
Root = pivot;
if (isLeftChild)
rootParent.Left = pivot;
else if (rootParent != null)
rootParent.Right = pivot;
}
}
Benchmarking code in .NET requires that you take into account JIT compilation time. The easiest way to do this, is to have your test code run the code twice - and discard the first timing results.
That aside - your benchmark results seem to imply a growth rate worse than the expected O(log n) time for AVL tree insertion.
What you haven't posted here is the code for the BinaryTreeNode<>
class. I suspect you may have a problem in the implementation of some of the methods there - I'm particularly suspicious of properties like Depth
and ToEnumerable
.
这篇关于AVL树在C#中的表现的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!