简体   繁体   中英

Remove element from list of Tuple<int, int> if any component is in another list of HashSet<int> in C#

I am performing DFS on an undirected graph and the goal is to get all the clusters that I want to read out later on. For this, I have instantiated edges of type List<Tuple<int, int>> and vertices is a simple array of integers. DFS(graph, vertex) returns a HashSet of integers. The problem is the last line inside the while-loop, how do I remove all the elements from edges that have already been visited?

using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;

public class Test {
    static public void Main(String[] args)
    {
        var vertices = Enumerable.Range(0, 10).ToArray();
        var edges = new List<Tuple<int, int>> {};
        edges.Add(Tuple.Create(1, 4));
        edges.Add(Tuple.Create(4, 1));
        edges.Add(Tuple.Create(3, 5));
        edges.Add(Tuple.Create(5, 3));

        var graph = new Graph<int>(vertices, edges);
        var algorithms = new GraphAlgorithms();
        var visited = new List<HashSet<int>>();

        // Apply DFS while there are clusters left
        while (edges.Any())
        {
            visited.Add(algorithms.DFS(graph, edges[0].Item1));
            edges.RemoveAll(node => visited.Contains(node));
        }
    }
}

Here are the referenced classes Graph and GraphAlgorithms if you want to try it out yourselves:

using System;
using System.Collections.Generic;

public class Graph<T> 
{
    public Graph() {}
    public Graph(IEnumerable<T> vertices, IEnumerable<Tuple<T,T>> edges)
    {
        foreach(var vertex in vertices)
            AddVertex(vertex);

        foreach(var edge in edges)
            AddEdge(edge);
    }

    public Dictionary<T, HashSet<T>> AdjacencyList { get; } = new Dictionary<T, HashSet<T>>();

    public void AddVertex(T vertex) 
    {
        AdjacencyList[vertex] = new HashSet<T>();
    }

    public void AddEdge(Tuple<T,T> edge) 
    {
        if (AdjacencyList.ContainsKey(edge.Item1) && AdjacencyList.ContainsKey(edge.Item2)) 
        {
            AdjacencyList[edge.Item1].Add(edge.Item2);
            AdjacencyList[edge.Item2].Add(edge.Item1);
        }
    }
}

using System.Collections.Generic; 

public class GraphAlgorithms {
    public HashSet<T> DFS<T>(Graph<T> graph, T start) {
        var visited = new HashSet<T>();

        if (!graph.AdjacencyList.ContainsKey(start))
            return visited;
            
        var stack = new Stack<T>();
        stack.Push(start);

        while (stack.Count > 0) {
            var vertex = stack.Pop();

            if (visited.Contains(vertex))
                continue;

            visited.Add(vertex);

            foreach(var neighbor in graph.AdjacencyList[vertex])
                if (!visited.Contains(neighbor))
                    stack.Push(neighbor);
        }

        return visited;
    }
}

Any help is greatly appreciated :)

I am reposting an edited version of my former question that I deleted now because the earlier one lacked a minimal reproducible example.

From what I see your visited should be not a List<Hashset<int>> but rather just a Hashset<int> , so your code will change to something like:

var visited = new HashSet<int>();
while(edges.Any())
{
    visited.UnionWith(algorithms.DFS(graph, edges[0].Item1));
    edges.RemoveAll(tuple => visited.Contains(tuple.Item1));
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM