/// <summary> /// Finds the min node in the subtree and returns the root of the new subtree /// </summary> private SplayTreeMapNode <TKey, TValue> FindAndRemoveMin(SplayTreeMapNode <TKey, TValue> subtreeRoot, ref SplayTreeMapNode <TKey, TValue> min) { if (subtreeRoot.Left == null) { if (subtreeRoot.Right == null) { min = subtreeRoot; return(null); } else { min = subtreeRoot; return(subtreeRoot.Right); } } var curNode = subtreeRoot; var lastNode = subtreeRoot; while (curNode.Left != null) { lastNode = curNode; curNode = curNode.Left; } lastNode.Left = curNode.Right; min = curNode; return(subtreeRoot); }
/// <summary> /// Standard right rotation. /// </summary> private SplayTreeMapNode <TKey, TValue> RotateRight(SplayTreeMapNode <TKey, TValue> node) { SplayTreeMapNode <TKey, TValue> m = node.Left; node.Left = m.Right; m.Right = node; return(m); }
/// <summary> /// Adds an element with the specified key and value into the <see cref="SplayTreeMap{TKey, TValue}"/>. /// </summary> /// <param name="key">The key of the element to add.</param> /// <param name="value">The value of the element to add.</param> public override void Add(TKey key, TValue value) { if (Root == null) { Root = new SplayTreeMapNode <TKey, TValue>(key, value); Count++; return; } var curNode = Root; bool addToLeftSide = true; var traversedNodes = new SinglyLinkedList <SplayTreeMapNode <TKey, TValue> >(); while (curNode != null) { traversedNodes.AddFirst(curNode); int cmp = comparer.Compare(key, curNode.Key); if (cmp < 0) { curNode = curNode.Left; addToLeftSide = true; } else if (cmp > 0) { curNode = curNode.Right; addToLeftSide = false; } else { throw new ArgumentException("Tried to insert duplicate value!"); } } if (addToLeftSide) { var newNode = new SplayTreeMapNode <TKey, TValue>(key, value); traversedNodes.First.Value.Left = newNode; traversedNodes.AddFirst(newNode); Count++; } else { var newNode = new SplayTreeMapNode <TKey, TValue>(key, value); traversedNodes.First.Value.Right = newNode; traversedNodes.AddFirst(newNode); Count++; } //Have to splay tree after adding Splay(traversedNodes); }
/// <summary> /// Determines whether an element with the specified value is contained in the <see cref="SplayTreeMap{TKey, TValue}"/> and then it splays it. /// </summary> /// <param name="value">The value to check.</param> /// <returns>true if value is found; otherwise false.</returns> public override bool ContainsValue(TValue value) { if (Root == null) { return(false); } // Pre order traversal of the tree, because we need to get the traversed nodes if values is found HashSet <SplayTreeMapNode <TKey, TValue> > cleared = new HashSet <SplayTreeMapNode <TKey, TValue> >(); SinglyLinkedList <SplayTreeMapNode <TKey, TValue> > sList = new SinglyLinkedList <SplayTreeMapNode <TKey, TValue> >(); sList.AddFirst(Root); while (sList.Count > 0) { SplayTreeMapNode <TKey, TValue> curNode = sList.First.Value; if (object.Equals(value, curNode.Value)) { // have to splay for the searched node Splay(sList); return(true); } if (curNode.Left == null || cleared.Contains(curNode.Left)) { if (curNode.Right == null || cleared.Contains(curNode.Right)) { cleared.Add(curNode); sList.RemoveFirst(); } else { sList.AddFirst(curNode.Right); } } else { sList.AddFirst(curNode.Left); } } return(false); }
/// <summary> /// Gets or sets the value associated with the specified key in the <see cref="SplayTreeMap{TKey, TValue}"/>. The tree is splayed afterwards. /// </summary> /// <param name="key">The key of the value to get or set.</param> /// <returns>The value associated with the specified key. If the specified key is not found, /// the get operation throws a <see cref="KeyNotFoundException"/>, and /// the set operation creates a new element with the specified key.</returns> public override TValue this[TKey key] { get { TValue value; if (TryGetValue(key, out value)) { return(value); } else { throw new KeyNotFoundException(); } } set { if (Root == null) { Root = new SplayTreeMapNode <TKey, TValue>(key, value); Count++; return; } var curNode = Root; bool addToLeftSide = true; var traversedNodes = new SinglyLinkedList <SplayTreeMapNode <TKey, TValue> >(); while (curNode != null) { traversedNodes.AddFirst(curNode); int cmp = comparer.Compare(key, curNode.Key); if (cmp < 0) { curNode = curNode.Left; addToLeftSide = true; } else if (cmp > 0) { curNode = curNode.Right; addToLeftSide = false; } else { curNode.Value = value; Splay(traversedNodes); return; } } if (addToLeftSide) { var newNode = new SplayTreeMapNode <TKey, TValue>(key, value); traversedNodes.First.Value.Left = newNode; traversedNodes.AddFirst(newNode); Count++; } else { var newNode = new SplayTreeMapNode <TKey, TValue>(key, value); traversedNodes.First.Value.Right = newNode; traversedNodes.AddFirst(newNode); Count++; } //Have to splay tree after adding Splay(traversedNodes); } }
/// <summary> /// Removes an element with the specified key from the <see cref="BinarySearchTreeMap{TKey, TValue}"/>. /// </summary> /// <param name="key">The key of the element to remove.</param> /// <returns>true if the element is successfully removed; otherwise false. Also returns false if element is not found.</returns> public override bool Remove(TKey key) { if (Root == null) { return(false); } var curNode = Root; var traversedNodes = new SinglyLinkedList <SplayTreeMapNode <TKey, TValue> >(); bool lastWasLeftSide = true; while (curNode != null) { traversedNodes.AddFirst(curNode); int cmp = comparer.Compare(key, curNode.Key); if (cmp < 0) { curNode = curNode.Left; lastWasLeftSide = true; } else if (cmp > 0) { curNode = curNode.Right; lastWasLeftSide = false; } else// found the value { Count--; // remove the current node from the traversed nodes we don't need it traversedNodes.RemoveFirst(); // deleting the node and replacing it with the min node in the right subtree if (curNode.Right == null) { if (lastWasLeftSide) { if (curNode == Root) { // if node for removal is the root node // no more operations are required Root = curNode.Left; curNode.Invalidate(); return(true); } else { traversedNodes.First.Value.Left = curNode.Left; } } else { traversedNodes.First.Value.Right = curNode.Left; } } else { SplayTreeMapNode <TKey, TValue> min = null; var rightNode = FindAndRemoveMin(curNode.Right, ref min); min.Right = rightNode; min.Left = curNode.Left; if (lastWasLeftSide) { if (curNode == Root) { // if node for removal is the root node // no more operations are required Root = min; curNode.Invalidate(); return(true); } else { traversedNodes.First.Value.Left = min; } } else { traversedNodes.First.Value.Right = min; } } // Note: if the node for deletion was the root we want be here // because everything is ok and no splaying is needed // When removing a node from the tree we have to // splay the tree for its parent Splay(traversedNodes); curNode.Invalidate(); return(true); } } return(false); }