/// <summary> /// Updates the degree of a node, cascading to update the degree of the /// parents if nessecary /// </summary> /// <param name="parentNode"></param> private void UpdateNodesDegree( FibonacciHeapHeapCell <TPriority, TValue> parentNode) { Contract.Requires(parentNode != null); var oldDegree = parentNode.Degree; parentNode.Degree = parentNode.Children.First != null ? Max(parentNode.Children, x => x.Degree) + 1 : 1; FibonacciHeapHeapCell <TPriority, TValue> degreeMapValue; if (oldDegree != parentNode.Degree) { if (degreeToNode.TryGetValue(oldDegree, out degreeMapValue) && degreeMapValue == parentNode) { degreeToNode.Remove(oldDegree); } else if (parentNode.Parent != null) { UpdateNodesDegree(parentNode.Parent); } } }
/// <summary> /// endqueue a node /// </summary> /// <param name="Priority">node prio</param> /// <param name="Value">node value</param> /// <returns>node</returns> public FibonacciHeapHeapCell <TPriority, TValue> Enqueue(TPriority Priority, TValue Value) { var newNode = new FibonacciHeapHeapCell <TPriority, TValue> { Priority = Priority, Value = Value, Marked = false, Children = new FibonacciHeapHeapLinkedList <TPriority, TValue>(), Degree = 1, Next = null, Previous = null, Parent = null, Removed = false }; //We don't do any book keeping or maintenance of the heap on Enqueue, //We just add this node to the end of the list of Heaps, updating the Next if required this.nodes.AddLast(newNode); if (next == null || (this.priorityComparsion(newNode.Priority, next.Priority) * DirectionMultiplier) < 0) { next = newNode; } count++; return(newNode); }
/// <summary> /// Delete a cell /// </summary> /// <param name="node">node</param> public void Delete(FibonacciHeapHeapCell <TPriority, TValue> node) { Contract.Requires(node != null); ChangeKeyInternal(node, default(TPriority), true); Dequeue(); }
/// <summary> /// Remove a cell /// </summary> /// <param name="node">node</param> internal void Remove(FibonacciHeapHeapCell <TPriority, TValue> node) { Contract.Requires(node != null); if (node.Previous != null) { node.Previous.Next = node.Next; } else if (first == node) { this.first = node.Next; } if (node.Next != null) { node.Next.Previous = node.Previous; } else if (last == node) { this.last = node.Previous; } node.Next = null; node.Previous = null; }
/// <summary> /// Merge two heaps /// </summary> /// <param name="other">other heap</param> public void Merge(FibonacciHeap <TPriority, TValue> other) { Contract.Requires(other != null); if (other.Direction != this.Direction) { throw new Exception("Error: Heaps must go in the same direction when merging"); } nodes.MergeLists(other.nodes); if ((priorityComparsion(other.Top.Priority, next.Priority) * DirectionMultiplier) < 0) { next = other.next; } count += other.Count; }
/// <summary> /// Updates the Next pointer, maintaining the heap /// by folding duplicate heap degrees into eachother /// Takes O(lg(N)) time amortized /// </summary> private void UpdateNext() { this.CompressHeap(); var node = this.nodes.First; next = this.nodes.First; while (node != null) { if ((this.priorityComparsion(node.Priority, next.Priority) * DirectionMultiplier) < 0) { next = node; } node = node.Next; } }
/// <summary> /// Add cell at the end /// </summary> /// <param name="node">cell</param> internal void AddLast(FibonacciHeapHeapCell <TPriority, TValue> node) { Contract.Requires(node != null); if (this.last != null) { this.last.Next = node; } node.Previous = this.last; this.last = node; if (this.first == null) { this.first = node; } }
/// <summary> /// Given two nodes, adds the child node as a child of the parent node /// </summary> /// <param name="parentNode"></param> /// <param name="childNode"></param> private void ReduceNodes( FibonacciHeapHeapCell <TPriority, TValue> parentNode, FibonacciHeapHeapCell <TPriority, TValue> childNode) { Contract.Requires(parentNode != null); Contract.Requires(childNode != null); this.nodes.Remove(childNode); parentNode.Children.AddLast(childNode); childNode.Parent = parentNode; childNode.Marked = false; if (parentNode.Degree == childNode.Degree) { parentNode.Degree += 1; } }
/// <summary> /// merging two lists /// </summary> /// <param name="list">second list</param> internal void MergeLists(FibonacciHeapHeapLinkedList <TPriority, TValue> list) { Contract.Requires(list != null); if (list.First != null) { if (last != null) { last.Next = list.first; } list.first.Previous = last; last = list.last; if (first == null) { first = list.first; } } }
/// <summary> /// Change a key /// </summary> /// <param name="node">node</param> /// <param name="newKey">key</param> private void ChangeKeyInternal( FibonacciHeapHeapCell <TPriority, TValue> node, TPriority NewKey, bool deletingNode) { Contract.Requires(node != null); var delta = Math.Sign(this.priorityComparsion(node.Priority, NewKey)); if (delta == 0) { return; } if (delta == this.DirectionMultiplier || deletingNode) { //New value is in the same direciton as the heap node.Priority = NewKey; var parentNode = node.Parent; if (parentNode != null && ((priorityComparsion(NewKey, node.Parent.Priority) * DirectionMultiplier) < 0 || deletingNode)) { node.Marked = false; parentNode.Children.Remove(node); UpdateNodesDegree(parentNode); node.Parent = null; nodes.AddLast(node); //This loop is the cascading cut, we continue to cut //ancestors of the node reduced until we hit a root //or we found an unmarked ancestor while (parentNode.Marked && parentNode.Parent != null) { parentNode.Parent.Children.Remove(parentNode); UpdateNodesDegree(parentNode); parentNode.Marked = false; nodes.AddLast(parentNode); var currentParent = parentNode; parentNode = parentNode.Parent; currentParent.Parent = null; } if (parentNode.Parent != null) { //We mark this node to note that it's had a child //cut from it before parentNode.Marked = true; } } //Update next if (deletingNode || (priorityComparsion(NewKey, next.Priority) * DirectionMultiplier) < 0) { next = node; } } else { //New value is in opposite direction of Heap, cut all children violating heap condition node.Priority = NewKey; if (node.Children != null) { List <FibonacciHeapHeapCell <TPriority, TValue> > toupdate = null; foreach (var child in node.Children) { if ((priorityComparsion(node.Priority, child.Priority) * DirectionMultiplier) > 0) { if (toupdate == null) { toupdate = new List <FibonacciHeapHeapCell <TPriority, TValue> >(); } toupdate.Add(child); } } if (toupdate != null) { foreach (var child in toupdate) { node.Marked = true; node.Children.Remove(child); child.Parent = null; child.Marked = false; nodes.AddLast(child); UpdateNodesDegree(node); } } } UpdateNext(); } }
/// <summary> /// Change a key /// </summary> /// <param name="node">node</param> /// <param name="newKey">key</param> public void ChangeKey(FibonacciHeapHeapCell <TPriority, TValue> node, TPriority newKey) { Contract.Requires(node != null); ChangeKeyInternal(node, newKey, false); }
public NodeLevel(FibonacciHeapHeapCell <TPriority, TValue> node, int level) { this.Node = node; this.Level = level; }
/// <summary> /// list constructor /// </summary> internal FibonacciHeapHeapLinkedList() { first = null; last = null; }