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); } } } }
/// <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); }
/// <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)); }
/// <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)); }
/// <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); } }
/// <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); }
/// <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); }
/// <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); }
/// <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); }
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); }
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; }
/// <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); }
/// <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); }
/// <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));