/// <summary>
        /// Updates the degree of a cell, cascading to update the degree of the
        /// parents if necessary.
        /// </summary>
        /// <param name="cell">Cell to update.</param>
        private void UpdateCellsDegree(
            FibonacciHeapCell <TPriority, TValue> cell
            )
        {
            Debug.Assert(cell != null);
            Debug.Assert(cell.Children != null);

            int oldDegree = cell.Degree;

            cell.Degree = cell.Children.First is null
                ? 1
                : cell.Children.Max(x => x.Degree) + 1;

            if (oldDegree != cell.Degree)
            {
                if (
                    _degreeToCell.TryGetValue(
                        oldDegree,
                        out FibonacciHeapCell <TPriority, TValue> degreeMapValue
                        ) &&
                    degreeMapValue == cell
                    )
                {
                    _degreeToCell.Remove(oldDegree);
                }
                else if (cell.Parent != null)
                {
                    UpdateCellsDegree(cell.Parent);
                }
            }
        }
Ejemplo n.º 2
0
        private FibonacciHeapCell <TPriority, TValue> ReduceCell([NotNull] ref FibonacciHeapCell <TPriority, TValue> cell)
        {
            FibonacciHeapCell <TPriority, TValue> nextCell = cell.Next;

            while (_degreeToCell.TryGetValue(cell.Degree, out FibonacciHeapCell <TPriority, TValue> currentDegreeCell) &&
                   currentDegreeCell != cell)
            {
                _degreeToCell.Remove(cell.Degree);
                if (PriorityComparison(currentDegreeCell.Priority, cell.Priority) * _directionMultiplier <= 0)
                {
                    if (cell == nextCell)
                    {
                        nextCell = cell.Next;
                    }

                    ReduceCells(currentDegreeCell, cell);
                    cell = currentDegreeCell;
                }
                else
                {
                    if (currentDegreeCell == nextCell)
                    {
                        nextCell = currentDegreeCell.Next;
                    }

                    ReduceCells(cell, currentDegreeCell);
                }
            }

            return(nextCell);
        }
        /// <summary>
        /// Merges the given <paramref name="heap"/> into this heap.
        /// </summary>
        /// <param name="heap">Heap to merge.</param>
        /// <exception cref="Exception">If the heap is not in the same direction.</exception>
        public void Merge(FibonacciHeap <TPriority, TValue> heap)
        {
            if (heap is null)
            {
                throw new ArgumentNullException(nameof(heap));
            }
            if (heap.Direction != Direction)
            {
                throw new InvalidOperationException("Heaps must go in the same direction when merging.");
            }
            if (heap.IsEmpty)
            {
                return;
            }

            bool isEmpty = IsEmpty;

            _cells.MergeLists(heap._cells);

            if (
                isEmpty ||
                PriorityComparison(
                    heap.Top.Priority,
                    Top.Priority
                    ) *
                _directionMultiplier
                < 0
                )
            {
                Top = heap.Top;
            }

            Count += heap.Count;
        }
        /// <summary>
        /// Removes the given <paramref name="cell"/> from this cells list.
        /// </summary>
        /// <param name="cell">Cell to remove.</param>
        internal void Remove(
            FibonacciHeapCell <TPriority, TValue> cell
            )
        {
            Debug.Assert(cell != null);

            if (cell.Previous != null)
            {
                cell.Previous.Next = cell.Next;
            }
            else if (First == cell)
            {
                First = cell.Next;
            }

            if (cell.Next != null)
            {
                cell.Next.Previous = cell.Previous;
            }
            else if (_last == cell)
            {
                _last = cell.Previous;
            }

            cell.Next     = null;
            cell.Previous = null;
        }
Ejemplo n.º 5
0
        private void UpdateCellOppositeDirection([NotNull] FibonacciHeapCell <TPriority, TValue> cell, [NotNull] TPriority newKey)
        {
            cell.Priority = newKey;
            if (cell.Children != null)
            {
                List <FibonacciHeapCell <TPriority, TValue> > toUpdate = null;
                foreach (FibonacciHeapCell <TPriority, TValue> child in cell.Children)
                {
                    if (PriorityComparison(cell.Priority, child.Priority) * _directionMultiplier > 0)
                    {
                        if (toUpdate is null)
                        {
                            toUpdate = new List <FibonacciHeapCell <TPriority, TValue> >();
                        }
                        toUpdate.Add(child);
                    }
                }

                if (toUpdate != null)
                {
                    foreach (FibonacciHeapCell <TPriority, TValue> child in toUpdate)
                    {
                        cell.Marked = true;
                        cell.Children.Remove(child);
                        child.Parent = null;
                        child.Marked = false;
                        _cells.AddLast(child);

                        UpdateCellsDegree(cell);
                    }
                }
            }

            UpdateNext();
        }
        private void ChangeKeyInternal(
            FibonacciHeapCell <TPriority, TValue> cell,
// Null authorized if deleting the cell
            TPriority newKey,
            bool deletingCell
            )
        {
            Debug.Assert(cell != null);

            int delta = Math.Sign(PriorityComparison(cell.Priority, newKey));

            if (delta == 0)
            {
                return;
            }

            if (delta == _directionMultiplier || deletingCell)
            {
                // New value is in the same direction as the heap
                UpdateCellSameDirection(cell, newKey, deletingCell);
            }
            else
            {
                // Not removing a cell so the newKey must not be null
                Debug.Assert(newKey != null);

                // New value is in opposite direction of Heap, cut all children violating heap condition
                UpdateCellOppositeDirection(cell, newKey);
            }
        }
        /// <summary>
        /// Enqueues an element in the heap.
        /// </summary>
        /// <param name="priority">Value priority.</param>
        /// <param name="value">Value to add.</param>
        public FibonacciHeapCell <TPriority, TValue> Enqueue(
            TPriority priority,
            TValue value
            )
        {
            if (priority == null)
            {
                throw new ArgumentNullException(nameof(priority));
            }

            var newCell = new FibonacciHeapCell <TPriority, TValue>
            {
                Priority = priority,
                Value    = value,
                Marked   = false,
                Children = new FibonacciHeapLinkedList <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 cell to the end of the list of Heaps, updating the Next if required
            _cells.AddLast(newCell);
            if (Top is null || PriorityComparison(newCell.Priority, Top.Priority) * _directionMultiplier < 0)
            {
                Top = newCell;
            }

            ++Count;

            return(newCell);
        }
 public CellLevel(
     FibonacciHeapCell <TPriority, TValue> cell,
     int level
     )
 {
     Cell  = cell;
     Level = level;
 }
Ejemplo n.º 9
0
        /// <summary>
        /// Changes the priority of the given <paramref name="cell"/>.
        /// </summary>
        /// <param name="cell">Cell to update the priority.</param>
        /// <param name="newPriority">New priority.</param>
        public void ChangeKey([NotNull] FibonacciHeapCell <TPriority, TValue> cell, [NotNull] TPriority newPriority)
        {
            if (cell is null)
            {
                throw new ArgumentNullException(nameof(cell));
            }

            ChangeKeyInternal(cell, newPriority, false);
        }
Ejemplo n.º 10
0
        /// <summary>
        /// Deletes the given <paramref name="cell"/> from this heap.
        /// </summary>
        /// <param name="cell">Cell to delete.</param>
        public void Delete([NotNull] FibonacciHeapCell <TPriority, TValue> cell)
        {
            if (cell is null)
            {
                throw new ArgumentNullException(nameof(cell));
            }

            ChangeKeyInternal(cell, default(TPriority), true);
            Dequeue();
        }
        IEnumerator <FibonacciHeapCell <TPriority, TValue> > GetEnumerator()
        {
            FibonacciHeapCell <TPriority, TValue> current = First;

            while (current != null)
            {
                yield return(current);

                current = current.Next;
            }
        }
Ejemplo n.º 12
0
        public TVertex Dequeue()
        {
            FibonacciHeapCell <TDistance, TVertex> cell = _heap.Top;

            if (cell is null)
            {
                throw new InvalidOperationException("Queue is empty.");
            }

            _heap.Dequeue();
            return(cell.Value);
        }
        private void CompressHeap()
        {
            FibonacciHeapCell <TPriority, TValue> cell = _cells.First;

            while (cell != null)
            {
                var nextCell = ReduceCell(ref cell);

                _degreeToCell[cell.Degree] = cell;
                cell = nextCell;
            }
        }
Ejemplo n.º 14
0
        private void UpdateCellSameDirection(
            [NotNull] FibonacciHeapCell <TPriority, TValue> cell,
            [CanBeNull] TPriority newKey,
            bool deletingCell)
        {
            cell.Priority = newKey;
            FibonacciHeapCell <TPriority, TValue> parentCell = cell.Parent;

            if (parentCell != null &&
                (PriorityComparison(newKey, parentCell.Priority) * _directionMultiplier < 0 || deletingCell))
            {
                cell.Marked = false;

                // ReSharper disable once PossibleNullReferenceException
                // Justification: parentCell must have children because child has parentCell as Parent.
                parentCell.Children.Remove(cell);
                UpdateCellsDegree(parentCell);
                cell.Parent = null;
                _cells.AddLast(cell);

                // This loop is the cascading cut, we continue to cut
                // ancestors of the cell reduced until we hit a root
                // or we found an unmarked ancestor
                while (parentCell.Marked && parentCell.Parent != null)
                {
                    // ReSharper disable once PossibleNullReferenceException
                    // Justification: parentCell must have children because child has parentCell as Parent.
                    parentCell.Parent.Children.Remove(parentCell);
                    UpdateCellsDegree(parentCell);
                    parentCell.Marked = false;
                    _cells.AddLast(parentCell);

                    FibonacciHeapCell <TPriority, TValue> currentParent = parentCell;
                    parentCell           = parentCell.Parent;
                    currentParent.Parent = null;
                }

                if (parentCell.Parent != null)
                {
                    // We mark this cell to note that it had a child
                    // cut from it before
                    parentCell.Marked = true;
                }
            }

            // Update next
            if (deletingCell || PriorityComparison(newKey, Top.Priority) * _directionMultiplier < 0)
            {
                Top = cell;
            }
        }
Ejemplo n.º 15
0
        /// <summary>
        /// Updates the Next pointer, maintaining the heap
        /// by folding duplicate heap degrees into each other.
        /// Takes O(log(N)) time amortized.
        /// </summary>
        private void UpdateNext()
        {
            CompressHeap();
            FibonacciHeapCell <TPriority, TValue> cell = _cells.First;

            Top = cell;
            while (cell != null)
            {
                if (PriorityComparison(cell.Priority, Top.Priority) * _directionMultiplier < 0)
                {
                    Top = cell;
                }

                cell = cell.Next;
            }
        }
Ejemplo n.º 16
0
        /// <summary>
        /// Adds the given <paramref name="cell"/> at the end of this cells list.
        /// </summary>
        /// <param name="cell">Cell to add.</param>
        internal void AddLast([NotNull] FibonacciHeapCell <TPriority, TValue> cell)
        {
            Debug.Assert(cell != null);

            if (_last != null)
            {
                _last.Next = cell;
            }

            cell.Previous = _last;
            _last         = cell;

            if (First is null)
            {
                First = cell;
            }
        }
Ejemplo n.º 17
0
        /// <summary>
        /// Given two cells, adds the child cell as a child of the parent cell.
        /// </summary>
        /// <param name="parentCell">Parent cell.</param>
        /// <param name="childCell">Child cell.</param>
        private void ReduceCells(
            [NotNull] FibonacciHeapCell <TPriority, TValue> parentCell,
            [NotNull] FibonacciHeapCell <TPriority, TValue> childCell)
        {
            Debug.Assert(parentCell != null);
            Debug.Assert(parentCell.Children != null);
            Debug.Assert(childCell != null);

            _cells.Remove(childCell);
            parentCell.Children.AddLast(childCell);
            childCell.Parent = parentCell;
            childCell.Marked = false;

            if (parentCell.Degree == childCell.Degree)
            {
                parentCell.Degree += 1;
            }
        }
Ejemplo n.º 18
0
        /// <inheritdoc />
        public IEnumerator <KeyValuePair <TPriority, TValue> > GetEnumerator()
        {
            var tempHeap   = new FibonacciHeap <TPriority, TValue>(Direction, PriorityComparison);
            var cellsStack = new Stack <FibonacciHeapCell <TPriority, TValue> >();

            _cells.ForEach(x => cellsStack.Push(x));
            while (cellsStack.Count > 0)
            {
                FibonacciHeapCell <TPriority, TValue> topCell = cellsStack.Peek();
                tempHeap.Enqueue(topCell.Priority, topCell.Value);
                cellsStack.Pop();
                topCell.Children?.ForEach(x => cellsStack.Push(x));
            }

            while (!tempHeap.IsEmpty)
            {
                yield return(tempHeap.Top.ToKeyValuePair());

                tempHeap.Dequeue();
            }
        }
Ejemplo n.º 19
0
        /// <summary>
        /// Merges the given <paramref name="cells"/> at the end of this cells list.
        /// </summary>
        /// <param name="cells">Cells to merge.</param>
        internal void MergeLists([NotNull] FibonacciHeapLinkedList <TPriority, TValue> cells)
        {
            Debug.Assert(cells != null);

            if (cells.First is null)
            {
                return;
            }

            if (_last != null)
            {
                _last.Next = cells.First;
            }

            cells.First.Previous = _last;
            _last = cells._last;

            if (First is null)
            {
                First = cells.First;
            }
        }
 internal FibonacciHeapLinkedList()
 {
     First = null;
     _last = null;
 }