/* Copyright 2007-2013 The NGenerics Team (https://github.com/ngenerics/ngenerics/wiki/Team) This program is licensed under the GNU Lesser General Public License (LGPL). You should have received a copy of the license along with the source code. If not, an online copy of the license can be found at http://www.gnu.org/copyleft/lesser.html. */ /* * The insertion and deletion code is based on the code found at http://eternallyconfuzzled.com/tuts/redblack.htm. * It's an excellent tutorial - if you want to understand Red Black trees, look there first. */ using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics.CodeAnalysis; using NGenerics.Comparers; using NGenerics.Patterns.Visitor; namespace NGenerics.DataStructures.Trees { /// /// An implementation of a Red-Black tree. /// /// The type of the keys in the . /// The type of the values in the . [SuppressMessage("Microsoft.Naming", "CA1710:IdentifiersShouldHaveCorrectSuffix")] #if (!SILVERLIGHT && !WINDOWSPHONE) //[Serializable] #endif public class RedBlackTree : RedBlackTree>, IDictionary // BinarySearchTreeBase { #region Construction /// public RedBlackTree() : base(new KeyValuePairComparer()) { // Do nothing - the default Comparer will be used by the base class. } /// public RedBlackTree(IComparer comparer) : base(new KeyValuePairComparer(comparer)) { // Do nothing else. } /// public RedBlackTree(Comparison comparison) : base(new KeyValuePairComparer(comparison)) { // Do nothing else. } #endregion #region Private Members private RedBlackTreeNode> FindNode(TKey key) { return base.FindNode(new KeyValuePair(key, default(TValue))) as RedBlackTreeNode>; } private bool Contains(KeyValuePair item, bool checkValue) { var node = FindNode(item); if ((node != null) && !checkValue) { return true; } return node != null && Equals(item.Value, node.Data.Value); } #endregion #region IDictionary Members /// /// Removes the element with the specified key from the . /// /// The key of the element to remove. /// /// true if the element is successfully removed; otherwise, false. This method also returns false if was not found in the original . /// /// /// is null. /// /// /// The is read-only. /// public bool Remove(TKey key) { return Remove(new KeyValuePair(key, default(TValue))); } /// /// Adds an element with the provided key and value to the . /// /// The object to use as the key of the element to add. /// The object to use as the value of the element to add. /// /// is null. /// /// /// An element with the same key already exists in the . /// /// /// The is read-only. /// public void Add(TKey key, TValue value) { if (Equals(key, null)) { throw new ArgumentNullException("key"); } Add(new KeyValuePair(key, value)); } /// /// Determines whether the contains an element with the specified key. /// /// The key to locate in the . /// /// true if the contains an element with the key; otherwise, false. /// /// /// is null. /// public bool ContainsKey(TKey key) { return Contains(new KeyValuePair(key, default(TValue)), false); } /// /// Gets an containing the keys of the . /// /// /// /// /// /// public ICollection Keys { get { // Get the keys in sorted order var visitor = new KeyTrackingVisitor(); var inOrderVisitor = new InOrderVisitor>(visitor); DepthFirstTraversal(inOrderVisitor); return new ReadOnlyCollection(visitor.TrackingList); } } /// /// /// /// /// public bool TryGetValue(TKey key, out TValue value) { var node = FindNode(new KeyValuePair(key, default(TValue))); if (node == null) { value = default(TValue); return false; } value = node.Data.Value; return true; } /// /// Gets an containing the values in the . /// /// /// /// /// /// public ICollection Values { get { var visitor = new ValueTrackingVisitor(); var inOrderVisitor = new InOrderVisitor>(visitor); DepthFirstTraversal(inOrderVisitor); return new ReadOnlyCollection(visitor.TrackingList); } } /// /// Gets or sets the value with the specified key. /// /// The key of the item to set or get. public TValue this[TKey key] { get { var node = FindNode(key); if (node == null) { throw new KeyNotFoundException("key"); } return node.Data.Value; } set { var node = FindNode(key); if (node == null) { throw new KeyNotFoundException("key"); } node.Data = new KeyValuePair(key, value); } } #endregion #region ICollection> Members /// /// /// /// /// public override bool Contains(KeyValuePair item) { return Contains(item, true); } #endregion } }