Note that there are some explanatory texts on larger screens.

plurals
  1. POPerformance of an AVL Tree in C#
    primarykey
    data
    text
    <p>I have implemented an AVL tree in C# whose insertion matrix is as follows</p> <pre><code>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 </code></pre> <p>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?</p> <hr> <p>Edit: The elements are integer starting from 0 to #of elements Test code is as follows</p> <pre><code> [Test] public void InsertionTest() { AVLTree&lt;int&gt; _tree = new AVLTree&lt;int&gt;(); _stopWatch.Start(); for (int i = 0; i &lt; 5000; i++) { _tree.Add(i); } _stopWatch.Stop(); Console.WriteLine("Time taken = " + _stopWatch.Elapsed); } </code></pre> <hr> <p>Edit: Implementation code</p> <p>BinarySearchTree</p> <pre><code>[Serializable] public class BinarySearchTree&lt;T&gt; : ICollection&lt;T&gt; { private readonly Comparer&lt;T&gt; _comparer = Comparer&lt;T&gt;.Default; public BinarySearchTree() { } public BinarySearchTree(IEnumerable&lt;T&gt; collection) { AddRange(collection.ToArray()); } public BinarySearchTree(Comparer&lt;T&gt; comparer) { _comparer = comparer; } public BinaryTreeNode&lt;T&gt; Root { get; protected set; } #region ICollection&lt;T&gt; Members /// &lt;summary&gt; /// Adds an item to the &lt;see cref = "T:System.Collections.Generic.ICollection`1" /&gt;. /// &lt;/summary&gt; /// &lt;param name = "value"&gt;The object to add to the &lt;see cref = "T:System.Collections.Generic.ICollection`1" /&gt;. /// &lt;/param&gt; /// &lt;exception cref = "T:System.NotSupportedException"&gt;The &lt;see cref = "T:System.Collections.Generic.ICollection`1" /&gt; is read-only. /// &lt;/exception&gt; public virtual void Add(T value) { var n = new BinaryTreeNode&lt;T&gt;(value); int result; BinaryTreeNode&lt;T&gt; current = Root, parent = null; while (current != null) { result = _comparer.Compare(current.Value, value); if (result == 0) { parent = current; current = current.Left; } if (result &gt; 0) { parent = current; current = current.Left; } else if (result &lt; 0) { parent = current; current = current.Right; } } Count++; if (parent == null) Root = n; else { result = _comparer.Compare(parent.Value, value); if (result &gt; 0) parent.Left = n; else parent.Right = n; } } /// &lt;summary&gt; /// Removes all items from the &lt;see cref = "T:System.Collections.Generic.ICollection`1" /&gt;. /// &lt;/summary&gt; /// &lt;exception cref = "T:System.NotSupportedException"&gt;The &lt;see cref = "T:System.Collections.Generic.ICollection`1" /&gt; is read-only. /// &lt;/exception&gt; public void Clear() { Root = null; Count = 0; } /// &lt;summary&gt; /// Determines whether the &lt;see cref = "T:System.Collections.Generic.ICollection`1" /&gt; contains a specific value. /// &lt;/summary&gt; /// &lt;returns&gt; /// true if &lt;paramref name = "item" /&gt; is found in the &lt;see cref = "T:System.Collections.Generic.ICollection`1" /&gt;; otherwise, false. /// &lt;/returns&gt; /// &lt;param name = "item"&gt;The object to locate in the &lt;see cref = "T:System.Collections.Generic.ICollection`1" /&gt;. /// &lt;/param&gt; public virtual bool Contains(T item) { BinaryTreeNode&lt;T&gt; current = Root; while (current != null) { int result = _comparer.Compare(current.Value, item); if (result == 0) return true; if (result &gt; 0) current = current.Left; else if (result &lt; 0) current = current.Right; } return false; } public void CopyTo(T[] array, int index) { CopyTo(array, index, BinaryTreeTraversalType.InOrder); } /// &lt;summary&gt; /// Removes the first occurrence of a specific object from the &lt;see cref = "T:System.Collections.Generic.ICollection`1" /&gt;. /// &lt;/summary&gt; /// &lt;returns&gt; /// true if &lt;paramref name = "item" /&gt; was successfully removed from the &lt;see cref = "T:System.Collections.Generic.ICollection`1" /&gt;; otherwise, false. This method also returns false if &lt;paramref name = "item" /&gt; is not found in the original &lt;see cref = "T:System.Collections.Generic.ICollection`1" /&gt;. /// &lt;/returns&gt; /// &lt;param name = "item"&gt;The object to remove from the &lt;see cref = "T:System.Collections.Generic.ICollection`1" /&gt;. /// &lt;/param&gt; /// &lt;exception cref = "T:System.NotSupportedException"&gt;The &lt;see cref = "T:System.Collections.Generic.ICollection`1" /&gt; is read-only. /// &lt;/exception&gt; public virtual bool Remove(T item) { if (Root == null) return false; BinaryTreeNode&lt;T&gt; current = Root, parent = null; int result = _comparer.Compare(current.Value, item); while (result != 0) { if (result &gt; 0) { parent = current; current = current.Left; } else if (result &lt; 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 &gt; 0) parent.Left = current.Left; else if (result &lt; 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 &gt; 0) parent.Left = current.Right; else if (result &lt; 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&lt;T&gt; 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 &gt; 0) parent.Left = leftmost; else if (result &lt; 0) parent.Right = leftmost; } } current.Left = current.Right = null; return true; } /// &lt;summary&gt; /// Gets the number of elements contained in the &lt;see cref = "T:System.Collections.Generic.ICollection`1" /&gt;. /// &lt;/summary&gt; /// &lt;returns&gt; /// The number of elements contained in the &lt;see cref = "T:System.Collections.Generic.ICollection`1" /&gt;. /// &lt;/returns&gt; public int Count { get; private set; } /// &lt;summary&gt; /// Gets a value indicating whether the &lt;see cref = "T:System.Collections.Generic.ICollection`1" /&gt; is read-only. /// &lt;/summary&gt; /// &lt;returns&gt; /// true if the &lt;see cref = "T:System.Collections.Generic.ICollection`1" /&gt; is read-only; otherwise, false. /// &lt;/returns&gt; public bool IsReadOnly { get { return false; } } #endregion public void AddRange(IEnumerable&lt;T&gt; items) { foreach (var item in items) { Add(item); } } public void CopyTo(T[] array, int index, BinaryTreeTraversalType traversalType) { Root.ToEnumerable(traversalType).Select(x =&gt; x.Value).ToArray().CopyTo(array, index); } public BinaryTreeNode&lt;T&gt; Find(T value) { BinaryTreeNode&lt;T&gt; current = Root; while (current != null) { int result = _comparer.Compare(current.Value, value); if (result == 0) return current; if (result &gt; 0) current = current.Left; else if (result &lt; 0) current = current.Right; } return null; } #region Implementation of IEnumerable /// &lt;summary&gt; /// Returns an enumerator that iterates through the collection. /// &lt;/summary&gt; /// &lt;returns&gt; /// A &lt;see cref = "T:System.Collections.Generic.IEnumerator`1" /&gt; that can be used to iterate through the collection. /// &lt;/returns&gt; /// &lt;filterpriority&gt;1&lt;/filterpriority&gt; public IEnumerator&lt;T&gt; GetEnumerator() { return Root.ToEnumerable(BinaryTreeTraversalType.InOrder).Select(x =&gt; x.Value).GetEnumerator(); } /// &lt;summary&gt; /// Returns an enumerator that iterates through a collection. /// &lt;/summary&gt; /// &lt;returns&gt; /// An &lt;see cref = "T:System.Collections.IEnumerator" /&gt; object that can be used to iterate through the collection. /// &lt;/returns&gt; /// &lt;filterpriority&gt;2&lt;/filterpriority&gt; IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } #endregion } </code></pre> <hr> <h2>AVLTree</h2> <pre><code>public class AVLTree&lt;T&gt; : BinarySearchTree&lt;T&gt; { public AVLTree() { } public AVLTree(IEnumerable&lt;T&gt; collection) : base(collection) { } public AVLTree(Comparer&lt;T&gt; comparer) : base(comparer) { } public override void Add(T value) { base.Add(value); var node = Find(value); AbstractNode&lt;T&gt; parentNode = node.Parent; while (parentNode != null) { int balance = GetBalance(parentNode as BinaryTreeNode&lt;T&gt;); if (Math.Abs(balance) == 2) { BalanceAt(parentNode as BinaryTreeNode&lt;T&gt;, balance); } parentNode = parentNode.Parent; } } public override bool Remove(T item) { if (Root == null) return false; BinaryTreeNode&lt;T&gt; valueNode = Find(item); AbstractNode&lt;T&gt; parentNode = valueNode.Parent; bool removed = base.Remove(item); if (!removed) return false; while (parentNode != null) { int balance = GetBalance(parentNode as BinaryTreeNode&lt;T&gt;); if (Math.Abs(balance) == 1) break; if (Math.Abs(balance) == 2) { BalanceAt(parentNode as BinaryTreeNode&lt;T&gt;, balance); } parentNode = parentNode.Parent; } return true; } /// &lt;summary&gt; /// Balances an AVL Tree node /// &lt;/summary&gt; protected virtual void BalanceAt(BinaryTreeNode&lt;T&gt; 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); } } } /// &lt;summary&gt; /// Determines the balance of a given node /// &lt;/summary&gt; protected virtual int GetBalance(BinaryTreeNode&lt;T&gt; node) { if(node != null) { IEnumerable&lt;BinaryTreeNode&lt;T&gt;&gt; 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 =&gt; x.Depth) - node.Depth; var righHeight = righSubtree.IsNullOrEmpty() ? 0 : righSubtree.Max(x =&gt; x.Depth) - node.Depth; // ReSharper restore AssignNullToNotNullAttribute return righHeight - leftHeight; } return 0; } /// &lt;summary&gt; /// Rotates a node to the left within an AVL Tree /// &lt;/summary&gt; protected virtual void RotateLeft(BinaryTreeNode&lt;T&gt; node) { if (node == null) return; BinaryTreeNode&lt;T&gt; pivot = node.Right; if (pivot == null) return; var rootParent = node.Parent as BinaryTreeNode&lt;T&gt;; bool isLeftChild = (rootParent != null) &amp;&amp; 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; } /// &lt;summary&gt; /// Rotates a node to the right within an AVL Tree /// &lt;/summary&gt; protected virtual void RotateRight(BinaryTreeNode&lt;T&gt; node) { if (node == null) return; BinaryTreeNode&lt;T&gt; pivot = node.Left; if (pivot == null) return; var rootParent = node.Parent as BinaryTreeNode&lt;T&gt;; bool isLeftChild = (rootParent != null) &amp;&amp; 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; } } </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload