/// <summary> /// Removes the specified key. Callers are expected to validate arguments. /// </summary> /// <param name="key">The key.</param> /// <param name="mutated">Receives a value indicating whether this node tree has mutated because of this operation.</param> /// <returns>The new AVL tree.</returns> private SortedInt32KeyNode <TValue> RemoveRecursive(int key, out bool mutated) { if (this.IsEmpty) { mutated = false; return(this); } else { SortedInt32KeyNode <TValue> result = this; if (key == _key) { // We have a match. mutated = true; // If this is a leaf, just remove it // by returning Empty. If we have only one child, // replace the node with the child. if (_right.IsEmpty && _left.IsEmpty) { result = EmptyNode; } else if (_right.IsEmpty && !_left.IsEmpty) { result = _left; } else if (!_right.IsEmpty && _left.IsEmpty) { result = _right; } else { // We have two children. Remove the next-highest node and replace // this node with it. var successor = _right; while (!successor._left.IsEmpty) { successor = successor._left; } bool dummyMutated; var newRight = _right.Remove(successor._key, out dummyMutated); result = successor.Mutate(left: _left, right: newRight); } } else if (key < _key) { var newLeft = _left.Remove(key, out mutated); if (mutated) { result = this.Mutate(left: newLeft); } } else { var newRight = _right.Remove(key, out mutated); if (mutated) { result = this.Mutate(right: newRight); } } return(result.IsEmpty ? result : MakeBalanced(result)); } }
/// <summary> /// Creates a node mutation, either by mutating this node (if not yet frozen) or by creating a clone of this node /// with the described changes. /// </summary> /// <param name="left">The left branch of the mutated node.</param> /// <param name="right">The right branch of the mutated node.</param> /// <returns>The mutated (or created) node.</returns> private SortedInt32KeyNode <TValue> Mutate(SortedInt32KeyNode <TValue> left = null, SortedInt32KeyNode <TValue> right = null) { if (_frozen) { return(new SortedInt32KeyNode <TValue>(_key, _value, left ?? _left, right ?? _right)); } else { if (left != null) { _left = left; } if (right != null) { _right = right; } _height = checked ((byte)(1 + Math.Max(_left._height, _right._height))); return(this); } }
/// <summary> /// Performs the set operation on a given data structure. /// </summary> private static MutationResult Except(IEnumerable <T> other, IEqualityComparer <T> equalityComparer, IEqualityComparer <HashBucket> hashBucketEqualityComparer, SortedInt32KeyNode <HashBucket> root) { Requires.NotNull(other, nameof(other)); Requires.NotNull(equalityComparer, nameof(equalityComparer)); Requires.NotNull(root, nameof(root)); int count = 0; var newRoot = root; foreach (var item in other.GetEnumerableDisposable <T, Enumerator>()) { int hashCode = item != null?equalityComparer.GetHashCode(item) : 0; HashBucket bucket; if (newRoot.TryGetValue(hashCode, out bucket)) { OperationResult result; HashBucket newBucket = bucket.Remove(item, equalityComparer, out result); if (result == OperationResult.SizeChanged) { count--; newRoot = UpdateRoot(newRoot, hashCode, hashBucketEqualityComparer, newBucket); } } } return(new MutationResult(newRoot, count)); }
private static bool IsLeftHeavy(SortedInt32KeyNode <TValue> tree) { Requires.NotNull(tree, nameof(tree)); Debug.Assert(!tree.IsEmpty); return(Balance(tree) <= -2); }
/// <summary> /// Initializes a new instance of the <see cref="ImmutableDictionary<TKey, TValue>.MutationInput"/> struct. /// </summary> /// <param name="map">The map.</param> internal MutationInput(ImmutableDictionary <TKey, TValue> map) { this.root = map.root; this.comparers = map.comparers; this.count = map.count; }
/// <summary> /// Wraps the specified data structure with an immutable collection wrapper. /// </summary> /// <param name="root">The root of the data structure.</param> /// <param name="adjustedCountIfDifferentRoot">The adjusted count if the root has changed.</param> /// <returns>The immutable collection.</returns> private ImmutableHashSet <T> Wrap(SortedInt32KeyNode <HashBucket> root, int adjustedCountIfDifferentRoot) { return((root != _root) ? new ImmutableHashSet <T>(root, _equalityComparer, adjustedCountIfDifferentRoot) : this); }
/// <summary> /// Removes all items from the <see cref="ICollection{T}"/>. /// </summary> /// <exception cref="NotSupportedException">The <see cref="ICollection{T}"/> is read-only. </exception> public void Clear() { this.Root = SortedInt32KeyNode <HashBucket> .EmptyNode; _count = 0; }
/// <summary> /// Applies the result of some mutation operation to this instance. /// </summary> /// <param name="result">The result.</param> private bool Apply(MutationResult result) { this.Root = result.Root; _count += result.CountAdjustment; return(result.CountAdjustment != 0); }
/// <summary> /// Initializes a new instance of the <see cref="ImmutableHashSet{T}.NodeEnumerable"/> struct. /// </summary> /// <param name="root">The root.</param> internal NodeEnumerable(SortedInt32KeyNode <HashBucket> root) { Requires.NotNull(root, nameof(root)); _root = root; }
/// <summary> /// Initializes a new instance of the <see cref="SortedInt32KeyNode{TValue}"/> class that is not yet frozen. /// </summary> /// <param name="key">The key.</param> /// <param name="value">The value.</param> /// <param name="left">The left.</param> /// <param name="right">The right.</param> /// <param name="frozen">Whether this node is prefrozen.</param> private SortedInt32KeyNode(int key, TValue value, SortedInt32KeyNode <TValue> left, SortedInt32KeyNode <TValue> right, bool frozen = false) { Requires.NotNull(left, nameof(left)); Requires.NotNull(right, nameof(right)); Debug.Assert(!frozen || (left._frozen && right._frozen)); _key = key; _value = value; _left = left; _right = right; _frozen = frozen; _height = checked ((byte)(1 + Math.Max(left._height, right._height))); }
/// <summary> /// Initializes a new instance of the <see cref="ImmutableDictionary{TKey, TValue}"/> class. /// </summary> /// <param name="comparers">The comparers.</param> private ImmutableDictionary(Comparers comparers = null) { _comparers = comparers ?? Comparers.Get(EqualityComparer <TKey> .Default, EqualityComparer <TValue> .Default); _root = SortedInt32KeyNode <HashBucket> .EmptyNode; }
private static bool IsRightHeavy(SortedInt32KeyNode <TValue> tree) { Requires.NotNull(tree, "tree"); Debug.Assert(!tree.IsEmpty); return(Balance(tree) >= 2); }
/// <summary> /// Initializes a new instance of the <see cref="ImmutableDictionary{TKey, TValue}.MutationInput"/> struct. /// </summary> /// <param name="map">The map.</param> internal MutationInput(ImmutableDictionary <TKey, TValue> map) { _root = map._root; _comparers = map._comparers; }
/// <summary> /// Initializes a new instance of the <see cref="ImmutableDictionary<TKey, TValue>.MutationResult"/> struct. /// </summary> /// <param name="root">The root.</param> /// <param name="countAdjustment">The count adjustment.</param> internal MutationResult(SortedInt32KeyNode <HashBucket> root, int countAdjustment) { Requires.NotNull(root, "root"); _root = root; _countAdjustment = countAdjustment; }
/// <summary> /// Initializes a new instance of the <see cref="ImmutableDictionary<TKey, TValue>.MutationResult"/> struct. /// </summary> /// <param name="unchangedInput">The unchanged input.</param> internal MutationResult(MutationInput unchangedInput) { _root = unchangedInput.Root; _countAdjustment = 0; }