Пример #1
0
        public T Dequeue()
        {
            if (_tree == null)             // return default(T) instead?
            {
                throw new InvalidOperationException("The queue is empty.");
            }

            var element = _tree.Element;

            _tree = _tree.DeleteMin();
            _dictionary.Remove(element);
            return(element);
        }
Пример #2
0
        public void Enqueue(T item)
        {
            RandomMeldablePriorityTree <T> node;

            if (_dictionary.TryGetValue(item, out node))
            {
                _tree = _tree.DecreaseKey(node, item);
            }
            else
            {
                node  = new RandomMeldablePriorityTree <T>(item);
                _tree = RandomMeldablePriorityTree <T> .Meld(_tree, node);
            }
            _dictionary[item] = node;
        }
Пример #3
0
        /// <summary>
        /// Modify a node in the heap that has a new score and return the new heap.
        /// </summary>
        public RandomMeldablePriorityTree <T> DecreaseKey(RandomMeldablePriorityTree <T> elementToBeChanged, T newElement)
        {
            if (elementToBeChanged.Element.CompareTo(newElement) <= 0)
            {
                return(this);
            }

            elementToBeChanged.Element = newElement;
            if (elementToBeChanged.Parent != null)
            {
                BreakConnectionToParent(elementToBeChanged);
                return(Meld(this, elementToBeChanged));
            }

            return(this);            // we must already be the lowest value item
        }
Пример #4
0
 private static void BreakConnectionToParent(RandomMeldablePriorityTree <T> node, RandomMeldablePriorityTree <T> replacement = null)
 {
     if (node == null)
     {
         return;
     }
     if (node.Parent == null)
     {
         return;
     }
     for (int i = 0; i < node.Parent._children.Length; i++)
     {
         if (node.Parent._children[i] == node)
         {
             node.Parent._children[i] = replacement;
             break;
         }
     }
     node.Parent = null;
 }
Пример #5
0
        /// <summary>
        /// Merge two heaps into one.
        /// </summary>
        public static RandomMeldablePriorityTree <T> Meld(RandomMeldablePriorityTree <T> q1, RandomMeldablePriorityTree <T> q2,
                                                          Func <int, byte> getChildIndex)
        {
            // think this through:
            // we will return either q1 or q2 (and if either is null, return is obvious)
            if (q1 == null)
            {
                BreakConnectionToParent(q2);
                return(q2);
            }
            if (q2 == null)
            {
                BreakConnectionToParent(q1);
                return(q1);
            }
            if (q1 == q2)
            {
#if DEBUG
                throw new InvalidOperationException("Merging with self was not expected.");
#else
                return(q1);
#endif
            }

            // q1 > q2, swap them so that q1 is the smallest
            if (q1.Element.CompareTo(q2.Element) > 0)
            {
                var tmp = q1;
                q1 = q2;
                q2 = tmp;
            }

            var ret = q1;
            BreakConnectionToParent(ret);

            do
            {
                // pick a random child branch
                var childIdx = getChildIndex.Invoke(q1._children.Length);

                // at this point q2 is larger than or equal to q1
                if (q1._children[childIdx] == null)
                {
                    q2.Parent = q1;
                    q1._children[childIdx] = q2;
                    break;
                }

                // if the random child of q1 is less than or equal to q2 make that q1 the new head
                if (q1._children[childIdx].Element.CompareTo(q2.Element) <= 0)
                {
                    q1 = q1._children[childIdx];
                    continue;
                }

                // our random child is larger than our q2 needing to be merged
                // things just got ugly: do the insert
                // we are going to disconnect the q1Child and replace it with q2
                // we are then going to continue with q2 in place of q1 and the child that needs to be merged as q2
                var tmp = q1._children[childIdx];
                q1._children[childIdx] = q2;
                q2.Parent = q1;
                q1        = q2;          // q1 has to be the smaller
                q2        = tmp;         // tmp is larger than q2
            } while (true);

            return(ret);
        }
Пример #6
0
 /// <summary>
 /// Merge two heaps into one.
 /// </summary>
 public static RandomMeldablePriorityTree <T> Meld(RandomMeldablePriorityTree <T> q1, RandomMeldablePriorityTree <T> q2)
 {
     return(Meld(q1, q2, x => ThreadLocalXorShifter.NextRandom(q1._children.Length)));
 }
Пример #7
0
 /// <summary>
 /// Return a new heap containing the additional element.
 /// </summary>
 public static RandomMeldablePriorityTree <T> Meld(RandomMeldablePriorityTree <T> q1, T element)
 {
     return(Meld(q1, new RandomMeldablePriorityTree <T>(element)));
 }
Пример #8
0
        /// <summary>
        /// Returns the best path.
        /// TPosition will be used as a dictionary key.
        /// </summary>
        /// <param name="getNeighbors">Given a position, return all the neighbors directly accessible from that position.</param>
        public static List <TNode> FindMinimalPath <TNode, TPosition>(
            TNode startingNode,
            Func <Dictionary <TPosition, RandomMeldablePriorityTree <TNode> >, TNode, bool> isDone,
            Func <TNode, IEnumerable <TNode> > getNeighbors)
            where TNode : SearchNodeBase <TPosition>
        {
            TNode best;
            var   lookup = new Dictionary <TPosition, RandomMeldablePriorityTree <TNode> >();
            var   opens  = new RandomMeldablePriorityTree <TNode>(startingNode);

            do
            {
                var lowest = opens.Element;

                // for dual direction, change this ending situation to be a lambda.
                // spawn two instances of the search method
                // in their lambda to see if they're done see if their position passed
                // exists in the lookup table here (and is open)
                // if that happens they are both done

                if (isDone.Invoke(lookup, lowest))
                {
                    best = lowest;
                    break;
                }

                opens = opens.DeleteMin();
#if DEBUG
                if (opens != null && opens.Parent != null)
                {
                    throw new InvalidOperationException("Expected opens to always point to the root.");
                }
#endif
                lookup[lowest.Position] = null;                 // keep this below the isDone check

                foreach (var neighbor in getNeighbors.Invoke(lowest))
                {
                    RandomMeldablePriorityTree <TNode> existing;
                    if (lookup.TryGetValue(neighbor.Position, out existing))
                    {
                        if (existing == null)
                        {
                            continue;
                        }
                        opens = opens.DecreaseKey(existing, neighbor);
                    }
                    else
                    {
                        existing = new RandomMeldablePriorityTree <TNode>(neighbor);
                        opens    = RandomMeldablePriorityTree <TNode> .Meld(opens, existing);

                        lookup[neighbor.Position] = existing;
                    }
                }

                if (opens == null)
                {
                    best = lowest;
                    break;
                }
            } while (true);

            LastExpansionCount = lookup.Count;

            var ret = new List <TNode>();
            while (best != null)
            {
                ret.Add(best);
                best = best.Parent as TNode;
            }
            ret.Reverse();
            return(ret);
        }
Пример #9
0
 public void Clear()
 {
     _tree = null;
     _dictionary.Clear();
 }