【问题标题】:How to make DFS algorithm continue working on a graph如何使 DFS 算法继续在图上工作
【发布时间】:2021-06-12 00:59:28
【问题描述】:

我正在尝试在 40 x 20 图形上搜索路径(不一定是最短路径)。起点和终点是随机选择的。 DFS 工作正常,直到它击中和边缘。然后,它不会返回并尝试朝不同的方向搜索,而是自行循环。这是我的代码(一小部分,但不再需要理解它,完整代码在这里:

struct Wierzcholek {
    Wierzcholek* next;
    int numerwierzcholka;
};
bool DFS(Wierzcholek**& TablicaList, bool*& visited, int& startowy, int koncowy, int MacierzGrafu[Wymiar40][Wymiar20])

{
        Wierzcholek* p;
        visited[startowy] = true;

            cout << setw(3) << startowy << "->";
            /*
            if (startowy == koncowy)
            {
                cout << koncowy << setw(5) << "Function has ended";
                return true;
            }//*/
                for (p = TablicaList[startowy]; p; p = p->next)
                {
                    MacierzGrafu[startowy / 20][startowy % 20] = 2;
                    if (!visited[p->numerwierzcholka])
                        if(DFS(TablicaList, visited, p->numerwierzcholka, koncowy, MacierzGrafu));
                    return true;
                }
            return false;
}
//Here's the implementation in main function
do {
        DFS(TablicaList, visited, LosowyWierzcholek, KoncowyWierzcholek, MacierzGrafu);
            if (LosowyWierzcholek == KoncowyWierzcholek)
                break;
    } while(true);

编辑:这是完整的程序:https://ideone.com/LGAhw1,这是我制作邻接列表的方法:

void UwtorzSasiada(int MacierzGrafu[Wymiar40][Wymiar20], Wierzcholek **& TablicaList,const char Kierunek, int row, int column) // 68-D(1) 71-G(4) 76-L(9) 80-P(13)
{
    Wierzcholek* p;
    int variable = int(Kierunek) - 67;
    switch (variable)
    {
    case 1: {
        if (MacierzGrafu[row + 1][column] == 1)
        {
            p = new Wierzcholek;
            p->numerwierzcholka = (((row + 1) * Wymiar20) + column);
            p->next = TablicaList[(row * Wymiar20) + column];
            TablicaList[(row * Wymiar20) + column] = p;
        }
    }break;
    case 4: {
        if (MacierzGrafu[row - 1][column] == 1)
        {
            p = new Wierzcholek;
            p->numerwierzcholka = (((row - 1) * Wymiar20) + column);
            p->next = TablicaList[(row * Wymiar20) + column];
            TablicaList[(row * Wymiar20) + column] = p;
        }
    }break;
    case 9: {
        if (MacierzGrafu[row][column - 1] == 1)
        {
            p = new Wierzcholek;
            p->numerwierzcholka = ((row * Wymiar20) + column - 1);
            p->next = TablicaList[(row * Wymiar20) + column];
            TablicaList[(row * Wymiar20) + column] = p;
        }
    }break;
    case 13: {
        if (MacierzGrafu[row][column + 1] == 1)
        {
            p = new Wierzcholek;
            p->numerwierzcholka = ((row * Wymiar20) + column + 1);
            p->next = TablicaList[(row * Wymiar20) + column];
            TablicaList[(row * Wymiar20) + column] = p;
        }
    }break;
    }
}

【问题讨论】:

  • 我如何让 dfs 继续搜索而不是无限循环? -- 在你首先在纸上解决问题之前,你不应该写一行代码。然后将该解决方案转换为代码。
  • 变量名在尝试阅读您的代码时可能会有很大帮助。但当它们使用其他语言时则不然。下次请翻译(或直接用英文写)

标签: c++ algorithm graph depth-first-search


【解决方案1】:

几个问题:

  1. 您将递归的基本情况放在 cmets 中,但需要以积极的结果结束递归:

    if (startowy == koncowy) {
        cout << koncowy << setw(5) << "target found";
        return true;
    }
    
  2. 递归DFS 调用的结果被忽略,而true 被无条件返回——同样当节点的邻居已经被访问时也是如此。发生这种情况是因为内部 if 语句没有正文:

    if (!visited[p->numerwierzcholka])
        if(DFS(TablicaList, visited, p->numerwierzcholka, koncowy, MacierzGrafu));
    return true;
    

    if 右侧的分号破坏了算法。这应该是:

    if (!visited[p->numerwierzcholka] && 
            DFS(TablicaList, visited, p->numerwierzcholka, koncowy, MacierzGrafu))
        return true;
    
  3. startowy 参数在调用DFS 期间永远不会更改,但在您的主代码中,您似乎期望调用将更改LosowyWierzcholek,直到它最终匹配KoncowyWierzcholek。这不是真的。 LosowyWierzcholek 不会改变。所以主程序中的while循环是一个无限循环。

  4. 主程序根本不需要循环:遍历是通过递归发生的,而不是通过迭代发生的。再次重复相同的DFS 搜索也无济于事。

    相反,您的主程序应该只调用 DFS 并使用布尔返回值:

    bool result = DFS(TablicaList, visited, LosowyWierzcholek, KoncowyWierzcholek, MacierzGrafu);
    cout << "result: " << result;
    

【讨论】:

  • 我非常感谢您的回答,您在第 3 段中讨论的算法是这样设计的,因此当图形的当前顶点最终遇到它正在搜索的顶点时,该函数将停止。它不会更改LosowyWierzcholek,但是当(最终)使用与KoncowyWierzcholek 相同的参数调用dfs 时,它应该停止递归。我理解正确吗?
  • 我已经应用了更改,但是程序在遇到边缘时仍然刚刚结束,所以很遗憾我最初的问题仍未解决。
  • 您能否编辑您的问题并添加构建图表的代码,以便我们运行它并查看会发生什么?我刚刚发现了一些导致您的代码挂起的问题,但显然我无法运行它,因为它不完整。
  • 我已经编辑了这个问题,把我如何创建我的列表放在最后,如果你想运行这个程序,还放了一个指向 ideone 的链接,因为它已经被分割成函数和一点点很长时间才能提出问题。
猜你喜欢
  • 2014-09-19
  • 2019-03-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-02-17
  • 1970-01-01
相关资源
最近更新 更多