Exemple #1
0
        /// <summary>
        /// Joins two heaps. O(1)
        /// </summary>
        /// <param name="h1"></param>
        /// <param name="h2"></param>
        /// <returns></returns>
        public static FibonacciHeap <T, TKey> Union(FibonacciHeap <T, TKey> h1, FibonacciHeap <T, TKey> h2)
        {
            var h = new FibonacciHeap <T, TKey>(h1._minKeyValue.CompareTo(h2._minKeyValue) < 0 ? h1._minKeyValue : h2._minKeyValue);

            if ((h1 != null) && (h2 != null))
            {
                h._minNode = h1._minNode;

                if (h._minNode != null)
                {
                    if (h2._minNode != null)
                    {
                        h._minNode.Right.Left  = h2._minNode.Left;
                        h2._minNode.Left.Right = h._minNode.Right;
                        h._minNode.Right       = h2._minNode;
                        h2._minNode.Left       = h._minNode;

                        if (h2._minNode.Key.CompareTo(h1._minNode.Key) < 0)
                        {
                            h._minNode = h2._minNode;
                        }
                    }
                }
                else
                {
                    h._minNode = h2._minNode;
                }

                h._nNodes = h1._nNodes + h2._nNodes;
            }

            return(h);
        }
Exemple #2
0
        /// <summary>
        /// Executes one command from the input.
        /// </summary>
        /// <param name="command">Command to be executed.</param>
        private void ExecuteCommand(string command)
        {
            string[] tokens = command.Split(new char[] { ' ' });
            switch (tokens[0])
            {
            // new heap
            case "#":
                if (totalCurNodes > 0)
                {
                    FinishCurrentHeap();
                }
                totalCurNodes = int.Parse(tokens[1]);
                Heap          = new FibonacciHeap <int, int>();
                Nodes         = new Node <int, int> [totalCurNodes];
                Heap.Naive    = naive;
                break;

            // insert
            case "I":
                int id = int.Parse(tokens[1]);
                var n  = new Node <int, int>(id, int.Parse(tokens[2]));
                Heap.Insert(n);
                Nodes[id] = n;
                break;

            // delete minimum
            case "M":
                if (Heap.NodesCount > 0)
                {
                    Nodes[Heap.Minimum.Identifier] = null;
                }
                var min = Heap.DeleteMinimum();
                if (min != null)
                {
                    totalMin++;
                    AverageDeleteMinimumSteps += Heap.LastOperationSteps;
                    if (Heap.LastOperationSteps > MaxDeleteMinimumSteps)
                    {
                        MaxDeleteMinimumSteps = Heap.LastOperationSteps;
                    }
                }
                break;

            // decrease key
            case "D":
                var decreased = Heap.DecreaseKey(int.Parse(tokens[2]), Nodes[int.Parse(tokens[1])]);
                if (decreased)
                {
                    totalDK++;
                    AverageDecreaseKeySteps += Heap.LastOperationSteps;
                    if (Heap.LastOperationSteps > MaxDecreaseKeySteps)
                    {
                        MaxDecreaseKeySteps = Heap.LastOperationSteps;
                    }
                }
                break;
            }
        }
Exemple #3
0
        /// <summary>
        /// Auxiliary testing method - randomly executes 1M inserts/deletes/decreases key in a 1K nodes heap.
        /// </summary>
        public static void TestHeap()
        {
            var sequenceLength = 1000000;
            var n           = 1000;
            var maxPriority = 1000;
            var random      = new Random(0);
            var nodes       = new Node <int, int> [n];
            var heap1       = new FibonacciHeap <int, int>();

            for (var i = 0; i < sequenceLength; i++)
            {
                var r = random.Next(5);

                if (r != 1 && r != 2) // Insert
                {
                    var id  = random.Next(n);
                    var key = random.Next(maxPriority);
                    if (nodes[id] != null)
                    {
                        continue;
                    }
                    Node <int, int> node = new Node <int, int>(id, key);
                    heap1.Insert(node);
                    nodes[id] = node;
                }
                else if (r == 1) // Delete min
                {
                    var min1 = heap1.Minimum;
                    if (min1 == null)
                    {
                        continue;
                    }
                    heap1.DeleteMinimum();
                    nodes[min1.Identifier] = null;
                }
                else if (r == 2) // Decrease
                {
                    var id    = random.Next(n);
                    var key   = random.Next(maxPriority);
                    var node1 = nodes[id];
                    heap1.DecreaseKey(key, node1);
                }
            }
        }
        public static Dictionary <Node, double> shortestPaths(DirectedGraph <Node> graph, Node source)
        {
            // фибоначчиевая куча которая будет хранить расстояния до узлов
            var pq = new FibonacciHeap <double, Node>();
            // словарь для соответствия узла в куче и узла в графе
            var entries = new Dictionary <Node, HeapNode <double, Node> >();
            //  узел и итоговое расстояние до него
            var result = new Dictionary <Node, double>();

            // добавить все узлы в фибоначчиеву кучу
            foreach (var node in graph)
            {
                entries.Add(node, pq.Insert(double.PositiveInfinity, node));
            }
            pq.DecreasePriority(entries[source], 0.0);
            // пока куча не пуста
            while (pq.Count != 0)
            {
                // извлечь минимум
                var curr = pq.ExtractMin();
                // доавить в список результатов
                result.Add(curr.Value, curr.Priority);
                // рассмотреть все исходящие ребра для минимума
                foreach (var arc in graph.edgesFrom(curr.Value))
                {
                    // если уже записано в результат продолжить
                    if (result.ContainsKey(arc.Key))
                    {
                        continue;
                    }
                    // инче прибавить пройденый путь к пути от curr до acr
                    double pathCost = curr.Priority + arc.Value;
                    // обновить самый короткий если текущий меньше
                    var dest = entries[arc.Key];
                    if (pathCost < dest.Priority)
                    {
                        pq.DecreasePriority(dest, pathCost);
                    }
                }
            }
            return(result);
        }