【问题标题】:How do I show the path of Bfs?如何显示 Bfs 的路径?
【发布时间】:2015-12-26 23:41:24
【问题描述】:

所以我正在尝试制作 BFS 算法,并且能够计算出每 2 个节点之间的最短路径距离。但是每个节点(即节点 A)的邻居不仅是节点,它还是作为键的节点字典和每两个节点参与的匹配哈希集。现在,我不知道如何在 BFS 时存储路径正在工作......这是返回每个节点的邻居的邻接函数

    Dictionary<string, Dictionary<string, HashSet<string>>> dic= new Dictionary<string, Dictionary < string,, HashSet < string >>>;

  public IEnumerable<KeyValuePair<string, HashSet<string>>> adjacentto(string v)
    {
        return dic[v];
    }

这是我的 BFS 函数:

    private Dictionary<string, int> dist = new Dictionary<string, int>();
    public void BFSDegree(Graph g, string s, string p)
    {
        Queue<string> q = new Queue<string>();

        dist.Add(s, 0);
        q.Enqueue(s);

        while (q.Count() != 0)
        {
            string j = q.Dequeue();
            //count = 0;
            foreach (KeyValuePair<string, HashSet<string>> h in g.adjacentto(j))
            {
                    if (!dist.ContainsKey(h.Key))
                    {
                        q.Enqueue(h.Key);
                        dist.Add(h.Key, 1 + dist[j]);


                    }

                    if (j == p)
                    {
                        Console.WriteLine("             " + dist[j]);                            
                        return;

                    }
                }


            }


        }

所以,我需要的是去查看路径并读取哈希集的值,例如节点 A 和节点 B 一起玩了 3 场比赛,比赛 1,比赛 2,比赛 7,所以这应该是路径。所以我要打印到控制台“路径是匹配 1、匹配 2 或匹配 7)。如果我有 2 个节点没有一起出现在匹配中,但它们都与节点 A 一起出现在2 个单独的匹配项,因此路径应该通过这 2 个匹配项中的任何一个。在操作 BFS 时如何跟踪路径并存储路径?这是我正在从中读取图表的文件。

这就是我构建图表的方式

这就是我想要实现的

通过使用 BFS,我能够实现第一个目标(学位)。但现在我不知道如何实现“链”或路径。链条只是路径中电影的数量,所以我认为如果我能够在 BFS 工作时保存路径(显示路径),我将能够实现链条。所以我的问题是我如何保存路径并显示它的最后一个目标。

【问题讨论】:

  • 你的问题很难理解。你能举例说明你的意思吗?也许举个例子说明你的图表会是什么样子以及结果?
  • 我编辑了这个问题。希望你现在能理解我的问题。

标签: c# graph breadth-first-search


【解决方案1】:

为了找到从一个节点到另一个节点的最短路径,您可以跟踪每个节点的父节点。例如下图,当我从 0 到 9 运行 bfs 时,我会跟踪每个节点到达一个指定的父节点。一旦分配了父母,我就不会重新分配。因此,例如,如果我想找到从 0 到 9 的路径和长度,我只需回溯,即 9-7-3-1-0,所以从 9 的父节点开始并检查 7 的父节点,依此类推,直到你开始节点。我们可以很容易地得到长度。

至于查询,当您执行 C/E 之类的操作时,您可以先运行 bfs 来检查路径“应该是 2 从 C-A-E 去”,当然可能还有其他路径,但我猜最短路径是最适合你想要什么? 无论如何,假设我们选择路径 C-A-E,我们可以更新 Rel。通过边数,所以 Rel = 2,然后 Chain 将是

//Nodes -> [C, A, E] 
//Parents ->[C, C, A]
Start from E // which is destination
Get movies of parent // parent is A, returns Movies 2
move to parent // now we are checking A
Get movies of parent // parent is C, returns Movies 1 Movies 7
break;

一到达源就中断,反之亦然 最后你有电影 2,1 和 7

父节点只是节点的前身。例如,当你运行 Bfs 时,如果你从 0 到 1,那么 0 是 1 的父级

这是一个实现,希望能帮助你更好地理解它。

private Map<Integer, List<Integer>> _adjacencyList;
private Map<Integer, String> _movies; // will store neighbors here
private Queue<Integer> queue;
private int [] visited;

public BaconNumber(int V){// v here is number of vertices
    _adjacencyList = new HashMap<Integer, List<Integer>>();
    _movies = new HashMap<Integer, String>();
    queue = new LinkedList<Integer>();
    visited = new int[V];
    for(int i = 0; i < V; i++){
        _adjacencyList.put(i, new LinkedList<Integer>());// add a linkedlist             for each vertex
        visited[i] = -1;
    }
}

在此处填充电影

private void fillNeighbors(){
    //0 = A, 1 = B, 2 = C, 3 = D, 4 = E
    _movies.put(0, "Z Movie 0 | B Movie 1 Movie 2 Movie 7 | C Movie 1 Movie 7 | D Movie 2 Movie 7 | E Movie 2");
    _movies.put(1, "A Movie 1 Movie 2 Movie 7 | C Movie 1 Movie 7 | D Movie 2 Movie 7 | E Movie 2");
    _movies.put(2, "A Movie 1 Movie 7 | B Movie 1 Movie 7 | D Movie 7");
    _movies.put(3, "E Movie 2 | A Movie 2 Movie 7 | B Movie 2 Movie 7 | C Movie 7");
    _movies.put(4, "D Movie 2 | A Movie 2 | B Movie 2 | F Movie 3 | G Movie 3");
}

获取电影。这需要两个参数。一个用于我们从哪里获取电影,另一个用于我们正在寻找的节点。请注意,我将第二个参数转换为一个字母,所以它看起来像你所拥有的

public String getMovies(int s, int v){
    String result = "";
    // just getting corresponding character
    int rem = v % 26;
    char l = (char)((int)'A' + rem);
    //System.out.println("this is char "+l);
    String movie = _movies.get(s);
    String [] tokens = movie.split("\\|");
    for(int i = 0; i < tokens.length; i++){
        String next = tokens[i];
        if(next.contains(String.valueOf(l))){
            result = next;
            break;
        }
    }
    return result;
}

现在是查询部分

String query(int source, int dest){
    List<Integer> nodes = new LinkedList<Integer>();
    int i, element;
    visited[source] = source;
    queue.add(source);
    while(!queue.isEmpty()){
        element = queue.remove();
        i = element;
        if(i == dest) break; // we stop as soon as we reach destination
        nodes.add(element);
        List<Integer> iList = getEdge(i);
        System.out.println(i+" -> "+iList);
        int x = 0; 
        while(x < iList.size()){
            int index = iList.get(x);
            if(visited[index] == -1){
                queue.add(index);
                visited[index] = i;
            }
            x++;
        }
    }
    String result = "";
    for(int x = dest; x >= 0; x= visited[x]){
        if(x == source) break; // we are done
        if(visited[x] != -1){
            result += getMovies(x,visited[x]); // get predecessor of x movies from x
        }
    }

    return result;
}

【讨论】:

  • 感谢您的澄清,这真的很有帮助。我对回溯的概念不太熟悉,我是否应该声明一个在 BFS 运行时存储路径的数据结构?你在我的代码上说的父母是什么意思?
  • 上面的结果应该是这样的 A Movie 2 C Movie 1 Movie 7
  • 我现在肯定更了解你了!非常感谢,现在我将尝试将其应用到我的代码中,谢谢!
  • 没问题。很高兴能提供帮助。
猜你喜欢
  • 1970-01-01
  • 2020-10-29
  • 1970-01-01
  • 1970-01-01
  • 2012-03-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多