示例#1
0
        private void BFSImpl(ReadOnlyNode startNode, Action <ReadOnlyNode> map)
        {
            var queue = new Queue <Node>();
            var start = startNode.ThisNode as Node;

            start.Distance = 0;
            queue.Enqueue(start);
            while (queue.Count > 0)
            {
                var node = queue.Dequeue();
                map?.Invoke(ReadOnlyNode.Create(node).Value);
                node.Color = NodeColor.Black; // seen and leaving
                foreach (var edge in node.OutEdges)
                {
                    var targetNode = edge.NodeTo.ThisNode as Node;
                    if (targetNode.Color == NodeColor.White)
                    {
                        targetNode.Color        = NodeColor.Gray; // seen and has not left yet
                        targetNode.Distance     = node.Distance + 1;
                        targetNode.PreviousNode = node;
                        queue.Enqueue(targetNode);
                    }
                }
            }
        }
示例#2
0
        /// <summary>
        /// Add value to graph and create node for it.
        /// </summary>
        /// <param name="value">Value to add</param>
        /// <returns>Node created for this value</returns>
        public ReadOnlyNode AddNode(T value)
        {
            var node = new Node(value);

            nodes.Add(node);
            return(ReadOnlyNode.Create(node).Value);
        }
示例#3
0
 /// <summary>
 /// Remove all nodes that match given predicate.
 /// </summary>
 /// <param name="predicate">Predicate to match</param>
 public void RemoveAllNodes(Predicate <ReadOnlyNode> predicate)
 {
     if (predicate == null)
     {
         throw new ArgumentNullException("Predicate is null");
     }
     nodes.RemoveAll(node => predicate(ReadOnlyNode.Create(node).Value));
 }
示例#4
0
        /// <summary>
        /// Run DFS (Depth first search) algorithm.
        /// </summary>
        /// <param name="startNode">Starting node</param>
        /// <param name="map">Node's mapping function</param>
        public void DFS(ReadOnlyNode startNode, Action <ReadOnlyNode> map)
        {
            PrepareForGraphTraverse();
            var start = startNode.ThisNode as Node;

            start.Distance = 0;
            DFSRecursive(start, null, map);
        }
示例#5
0
        /// <summary>
        /// Add edge to graph.
        /// </summary>
        /// <param name="nodeFrom">Source node</param>
        /// <param name="nodeTo">Target node</param>
        /// <param name="length">Length (weight) of node</param>
        /// <returns>Edge added to the graph</returns>
        public Edge AddEdge(ReadOnlyNode nodeFrom, ReadOnlyNode nodeTo, double length)
        {
            var edge = new Edge(length, nodeFrom, nodeTo);

            (nodeFrom.ThisNode as Node).OutEdges.Add(edge);
            (nodeTo.ThisNode as Node).InEdges.Add(edge);
            return(edge);
        }
        /// <summary>
        /// Swap values in given nodes.
        /// </summary>
        /// <param name="nodeA">First node</param>
        /// <param name="nodeB">Second node</param>
        public void Swap(ReadOnlyNode nodeA, ReadOnlyNode nodeB)
        {
            var swapNodeA = (Node)nodeA.ThisNode;
            var swapNodeB = (Node)nodeB.ThisNode;
            var tmpValue  = swapNodeA.Value;

            swapNodeA.Value = swapNodeB.Value;
            swapNodeB.Value = tmpValue;
        }
示例#7
0
 /// <summary>
 /// Run Bellman-Ford algorithm and count minimum distance from given node.
 /// </summary>
 /// <param name="startNode">Starting node</param>
 public void BellmanFord(ReadOnlyNode startNode)
 {
     if (NumberOfConnectivityComponents() > 1)
     {
         throw new InvalidOperationException("Unable to perform BellmanFord on graph with more than one connectivity component");
     }
     PrepareForGraphTraverse();
     BellmanFordImpl(startNode.ThisNode as Node);
 }
示例#8
0
 public Edge(double length, ReadOnlyNode nodeFrom, ReadOnlyNode nodeTo)
 {
     unchecked
     {
         Id = IdCounter++;
     }
     Length   = length;
     NodeFrom = nodeFrom;
     NodeTo   = nodeTo;
 }
        /// <summary>
        /// Find node with given key.
        /// </summary>
        /// <param name="key">Key of node to find</param>
        /// <returns>Node that contains given key if any found, otherwise null</returns>
        public ReadOnlyNode?Find(TKey key)
        {
            var result = FindNodeImpl(key);

            if (result.Node != null)
            {
                Splay(result.Node);
            }
            return(ReadOnlyNode.Create(result.Node));
        }
示例#10
0
 private ReadOnlyNode(IEnumerator <T> elements, ReadOnlyNode <T> prev, bool first)
 {
     if (first)
     {
         elements.MoveNext();
     }
     Value = elements.Current;
     Next  = elements.MoveNext() ? new ReadOnlyNode <T>(elements, this, false) : null;
     Prev  = prev;
 }
示例#11
0
 /// <summary>
 /// Get node at given index.
 /// </summary>
 /// <param name="index">Node's index</param>
 /// <returns>Node at given index</returns>
 public ReadOnlyNode this[int index]
 {
     get
     {
         if (index < 0 || index >= Count)
         {
             throw new ArgumentOutOfRangeException("Index out of range");
         }
         return(ReadOnlyNode.Create(nodes[index]).Value);
     }
 }
示例#12
0
        /// <summary>
        /// Find all nodes with values that match given predicate.
        /// </summary>
        /// <param name="predicate">Predicate</param>
        /// <returns>List of nodes that match given predicate</returns>
        public List <ReadOnlyNode> FindAll(Predicate <T> predicate)
        {
            var list = new List <ReadOnlyNode>();
            var node = FindFrom(predicate, frontNode);

            while (node != null)
            {
                list.Add(ReadOnlyNode.Create(node).Value);
                node = FindFrom(predicate, node.Next);
            }
            return(list);
        }
示例#13
0
 private ReadOnlyNode(IEnumerable <T> elements, ReadOnlyNode <T> prev)
 {
     if (elements == null || !elements.Any())
     {
         throw new ArgumentException(
                   "Enumerable must not be null and must have at least one element");
     }
     Next = elements.Count() == 1
            ? null
            : new ReadOnlyNode <T>(elements.Skip(1), this);
     Value = elements.First();
     Prev  = prev;
 }
示例#14
0
        /// <summary>
        /// Remove first node that match given predicate.
        /// </summary>
        /// <param name="predicate">Predicate to match</param>
        /// <returns>True if any node was removed, false otherwise</returns>
        public bool RemoveNode(Predicate <ReadOnlyNode> predicate)
        {
            if (predicate == null)
            {
                throw new ArgumentNullException("Predicate is null");
            }
            var index = nodes.FindIndex(node => predicate(ReadOnlyNode.Create(node).Value));

            if (index >= 0 && index < Count)
            {
                RemoveAllEdgesConnectedToNode(nodes[index]);
                nodes.RemoveAt(index);
                return(true);
            }
            return(false);
        }
示例#15
0
        /// <summary>
        /// Count number connectivity components in graph using BFS.
        /// </summary>
        /// <returns>Number of connectivity components in graph</returns>
        public int NumberOfConnectivityComponents()
        {
            PrepareForGraphTraverse();
            int componentsCounter = 0;

            foreach (var node in nodes)
            {
                if (node.Color == NodeColor.White)
                {
                    componentsCounter++;
                    BFS(ReadOnlyNode.Create(node).Value, null);
                }
            }
            ClearTraversingStats();
            return(componentsCounter);
        }
示例#16
0
        private List <Edge> JarnikImpl()
        {
            PrepareForGraphTraverse();
            DijkstraImpl(nodes[0], EdgeRelaxJarnik);
            var spanningTree = new List <Edge>();

            foreach (var node in nodes)
            {
                if (node.PreviousNode == null)
                {
                    continue;
                }
                var from = ReadOnlyNode.Create(node.PreviousNode).Value;
                var to   = ReadOnlyNode.Create(node).Value;
                spanningTree.Add(new Edge(node.Distance, from, to));
            }
            return(spanningTree);
        }
示例#17
0
        /// <summary>
        /// Insert value before given node.
        /// </summary>
        /// <param name="node">Insert value before this node</param>
        /// <param name="value">Value to insert</param>
        public void InsertBefore(ReadOnlyNode node, T value)
        {
            if (node.ThisNode == frontNode)
            {
                PushFront(value);
                return;
            }
            var nextNode = (Node)node.ThisNode;
            var newNode  = new Node(value)
            {
                Previous = nextNode.Previous,
                Next     = nextNode
            };

            nextNode.Previous     = newNode;
            newNode.Previous.Next = newNode;
            Count++;
        }
示例#18
0
        /// <summary>
        /// Insert value after given node.
        /// </summary>
        /// <param name="node">Insert value after this node</param>
        /// <param name="value">Value to insert</param>
        public void InsertAfter(ReadOnlyNode node, T value)
        {
            if (node.ThisNode == backNode)
            {
                PushBack(value);
                return;
            }
            var previousNode = (Node)node.ThisNode;
            var newNode      = new Node(value)
            {
                Previous = previousNode,
                Next     = previousNode.Next
            };

            previousNode.Next     = newNode;
            newNode.Next.Previous = newNode;
            Count++;
        }
示例#19
0
        /// <summary>
        /// Remove node from list.
        /// </summary>
        /// <param name="node">Node to remove</param>
        public void RemoveNode(ReadOnlyNode node)
        {
            if (node.ThisNode == frontNode)
            {
                PopFront();
                return;
            }
            if (node.ThisNode == backNode)
            {
                PopBack();
                return;
            }
            var removeNode = (Node)node.ThisNode;

            removeNode.Previous.Next = removeNode.Next;
            removeNode.Next.Previous = removeNode.Previous;
            Count--;
        }
示例#20
0
        /// <summary>
        /// Return node at given index.
        /// </summary>
        /// <param name="index">Index of node to return</param>
        /// <returns>Node at given index</returns>
        public ReadOnlyNode NodeAt(int index)
        {
            if (index < 0 || index >= Count)
            {
                throw new ArgumentOutOfRangeException("Index is out of range");
            }
            var node = frontNode;

            for (int i = 0; i < index && node != null; i++)
            {
                node = node.Next;
            }
            if (node == null)
            {
                throw new InvalidOperationException("Linked list is corrupted");
            }
            return(ReadOnlyNode.Create(node).Value);
        }
示例#21
0
 private void DFSRecursive(Node node, Node previousNode, Action <ReadOnlyNode> map)
 {
     if (node.Color == NodeColor.White)
     {
         node.PreviousNode = previousNode;
         node.Distance     = previousNode != null ? previousNode.Distance + 1 : 0;
     }
     // In case of cycle detection
     map?.Invoke(ReadOnlyNode.Create(node).Value);
     if (node.Color != NodeColor.White)
     {
         return;
     }
     node.Color = NodeColor.Gray;
     foreach (var edge in node.OutEdges)
     {
         DFSRecursive(edge.NodeTo.ThisNode as Node, node, map);
     }
     node.Color = NodeColor.Black;
 }
示例#22
0
    private ReadOnlyNode(IEnumerator <T> elements, ReadOnlyNode <T> prev, bool first)
    {
        if (elements == null)
        {
            throw new ArgumentNullException("elements");
        }
        var empty = false;

        if (first)
        {
            empty = elements.MoveNext();
        }

        if (!empty)
        {
            Value = elements.Current;
            Next  = elements.MoveNext() ? new ReadOnlyNode <T>(elements, this, false) : null;
            Prev  = prev;
        }
    }
示例#23
0
        /// <summary>
        /// Check whether graph contains a cycle (using DFS).
        /// </summary>
        /// <returns>True whether graph containst cycle, false otherwise</returns>
        public bool ContainsCycle()
        {
            PrepareForGraphTraverse();
            bool cycleDetected = false;

            foreach (var node in nodes)
            {
                if (node.Color == NodeColor.White)
                {
                    DFS(ReadOnlyNode.Create(node).Value, (readOnlyNode) => {
                        cycleDetected = (readOnlyNode.ThisNode as Node).Color == NodeColor.Gray;
                    });
                    if (cycleDetected)
                    {
                        break;
                    }
                }
            }
            ClearTraversingStats();
            return(cycleDetected);
        }
示例#24
0
        /// <summary>
        /// Add element (key-value pair) to tree.
        /// </summary>
        /// <param name="key">Element's key</param>
        /// <param name="value">Element's value</param>
        /// <returns>Added node</returns>
        public ReadOnlyNode Add(TKey key, TValue value)
        {
            if (root == null) // Insert root
            {
                root  = new Node(key, value, null);
                Count = 1;
                return(Root.Value);
            }
            var result = FindNodeImpl(key);
            var node   = result.Node;

            if (node != null) // Key-Value already present, just overwrite current value
            {
                node.Value = value;
            }
            else
            {
                node = InsertNewNode(key, value, result.ParentNode);
            }
            return(ReadOnlyNode.Create(node).Value);
        }
示例#25
0
 /// <summary>
 /// Run Dijkstra algorithm and count minimum distance from given node.
 /// </summary>
 /// <param name="startNode">Starting node</param>
 public void Dijkstra(ReadOnlyNode startNode)
 {
     PrepareForGraphTraverse();
     DijkstraImpl(startNode.ThisNode as Node, EdgeRelax);
 }
示例#26
0
 /// <summary>
 /// Return index of given node in graph.
 /// </summary>
 /// <param name="readOnlyNode">Node to find out an index in graph</param>
 /// <returns>Index of given node</returns>
 public int GetIndex(ReadOnlyNode readOnlyNode) => nodes.FindIndex(node => node.Id == (readOnlyNode.ThisNode as Node).Id);
示例#27
0
 /// <summary>
 /// Return first node that match given predicate.
 /// </summary>
 /// <param name="predicate">Predicate</param>
 /// <returns>Node with value that match given predicate, otherwise null</returns>
 public ReadOnlyNode?Find(Predicate <T> predicate) => ReadOnlyNode.Create(FindFrom(predicate, frontNode));
 public Node(T value, ReadOnlyNode <T> next, ReadOnlyNode <T> prev)
 {
     Value = value;
     Next  = next;
     Prev  = prev;
 }
示例#29
0
 /// <summary>
 /// Run BFS (Breadth first search) algorithm.
 /// </summary>
 /// <param name="startNode">Starting node</param>
 /// <param name="map">Node's mapping function</param>
 public void BFS(ReadOnlyNode startNode, Action <ReadOnlyNode> map)
 {
     PrepareForGraphTraverse();
     BFSImpl(startNode, map);
 }
示例#30
0
 /// <summary>
 /// Remove given node from graph with all it's in/out going edges.
 /// </summary>
 /// <param name="readOnlyNode">Node to remove</param>
 public void RemoveNode(ReadOnlyNode readOnlyNode) => RemoveNode(node => (node.ThisNode as Node).Id == (readOnlyNode.ThisNode as Node).Id);