【问题标题】:Infinite loop when trying to find the shortest path in a graph尝试在图中找到最短路径时的无限循环
【发布时间】:2017-08-06 14:52:39
【问题描述】:

我已经修改了以下代码以满足我在图中查找路径的需要

//H-File
#include<iostream>
#include <list>
using namespace std;
#ifndef _Graph__
#define _Graph__


class Graph
{
    int V; // No. of vertices in graph
    list<int> *adj; // Pointer to an array containing adjacency lists

    // A recursive function used by printAllPaths()
    void printAllPathsUtil(int , int , bool [], int [], int &);

public:
    Graph(int V); // Constructor
    void addEdge(int u, int v);
    void printAllPaths(int s, int d);
};

void solveMaze(string name, int start, int end);



#endif /* defined(__Graph__) */

    //CPP FILE
Graph::Graph(int V)
{
    this->V = V;
    adj = new list<int>[V];
}

void Graph::addEdge(int u, int v)
{
    adj[u].push_back(v); // Add v to u’s list.
}

// Prints all paths from 's' to 'd'
void Graph::printAllPaths(int s, int d)
{
    // Mark all the vertices as not visited
    bool *visited = new bool[V];

    // Create an array to store paths
    int *path = new int[V];
    int path_index = 0; // Initialize path[] as empty

    // Initialize all vertices as not visited
    for (int i = 0; i < V; i++)
        visited[i] = false;

    // Call the recursive helper function to print all paths
    printAllPathsUtil(s, d, visited, path, path_index);
}


void Graph::printAllPathsUtil(int u, int d, bool visited[], int path[], int &path_index){
    // Mark the current node and store it in path[]
    visited[u] = true;
    path[path_index] = u;
    path_index++;

    // If current vertex is same as destination, then print
    // current path[]
    if (u == d)
    {
        int steps;
        for (int i = 0; i<path_index; i++){
            cout << path[i] << " ";
            steps = i;
        }

        cout << endl;
        cout << "Length of path is " << steps << endl;
    }
    else // If current vertex is not destination
    {
        // Recur for all the vertices adjacent to current vertex
        list<int>::iterator i;
        for (i = adj[u].begin(); i != adj[u].end(); ++i)
            if (!visited[*i])
                printAllPathsUtil(*i, d, visited, path, path_index);
    }

    // Remove current vertex from path[] and mark it as unvisited
    path_index--;
    visited[u] = false;
}

void solveMaze(string name, int start, int end){
    vector<int> graphData;
    ifstream f(name);
    if (f.is_open()) {
        string line;
        getline(f, line);
        char c;
        while (f >> c) {
            if (c == '1') {
                graphData.push_back(1);
            }
            else if (c =='0') {
                graphData.push_back(0);
            }
        }
        f.close();
    }


    int numRooms = int(graphData.size()/4);
    int numCols = sqrt(graphData.size()/4);
    cout << "numCols: " << numCols << endl;
    cout << "rooms: "<< numRooms << endl;
    cout << endl;
    cout << endl;

    Graph maze(numRooms);
    for(int room = 0; room < numRooms; ++room){
        //if room is on top row and left corner
        if(room == 0){

            if(graphData[(room*4+1)] == 1){//You are at room 0, checking room 1
                maze.addEdge(room, room+1);
                cout << "a ";
                cout << "room " << room << " to " << room+1 << endl;
            }
            if(graphData[(room*4+2)] == 1){//Checking below room zero
               maze.addEdge(room, room+numCols);
                cout << "b ";
                cout << "room " << room << " to " << room+numCols << endl;
            }
        }

        //if room is on top row
        if(room < numCols && room !=0){
            if(graphData[(room*4+1)] == 1){//Check to east
                maze.addEdge(room, room+1);
                cout << "c ";
                cout << "room " << room << " to " << room+1 << endl;
            }
            if(graphData[(room*4+2)] == 1){//Checking to south
                maze.addEdge(room, room+numCols);
                cout << "d ";
                cout << "room " << room << " to " << room+numCols << endl;
            }

        }

        //if room is on top row and right corner
        if(room == numCols-1){
            if(graphData[(room*4+2)] == 1){//Checking to south
                maze.addEdge(room, room+numCols);
                cout << "e ";
                cout << "room " << room << " to " << room+numCols << endl;
            }

        }
        //if room is on middle row and left room
        if((room >= numCols) && (room%numCols == 0)){
            if(graphData[(room*4+1)] == 1){//Check to east
                maze.addEdge(room, room+1);
                cout << "f ";
                cout << "room " << room << " to " << room+1 << endl;
            }
            if(graphData[(room*4+2)] == 1){//Checking to south
                maze.addEdge(room, room+numCols);
                cout << "g ";
                cout << "room " << room << " to " << room+numCols << endl;
            }

        }

        //if room is on middle row and right room
        if((room > numCols) && (room%numCols == numCols-1)){
            if(graphData[(room*4+2)] == 1){//Checking to south
                maze.addEdge(room, room+numCols);
                cout << "h ";
                cout << "room " << room << " to " << room+numCols << endl;
            }

        }

        //if room is on bottom row but not the room on the right corner
        if(room > numCols && (room == numRooms-numCols)){
            if(graphData[(room*4+1)] == 1){//Check to east
                maze.addEdge(room, room+1);
                cout << "i ";
                cout << "room " << room << " to " << room+1 << endl;
            }

        }
        //else room is just in middle rows
        if((room > numCols) && (room%numCols != numCols-1) && (room%numCols != 0)){
            if(graphData[(room*4+1)] == 1){//Check to east
                maze.addEdge(room, room+1);
                cout << "j ";
                cout << "room " << room << " to " << room+1 << endl;
            }
            if(graphData[(room*4+2)] == 1){//Checking to south
                maze.addEdge(room, room+numCols);
                cout << "k ";
                cout << "room " << room << " to " << room+numCols << endl;
            }

        }
    }
    cout << endl;
    cout << endl;
    cout << "Finding all paths from " << start << " to " << end << "..." << endl;

    maze.printAllPaths(start, end);
}

它工作得很好,除了当我在图表中遇到死胡同并且不得不绕回的情况。它继续采用相同的路径,因此陷入无限循环。我不确定如何解决这个问题。只是要明确一点:如果我有这样的连接

A--B--C--D--E
   |
   F

它会从 A 到 B 到 F 再回到 B 再到 F 反复。我希望它从 A 到 B 到 F 然后回到 B 然后到 C。有什么想法吗?

【问题讨论】:

  • 题外话:包含保护应该围绕整个头文件。在#ifndef _Graph__ 上方放置有可能让您感到悲伤的东西。 _Graph__ 是非法标识符,因为有双下划线。 More on that linked here。将using namespace std 放在标题中会给其他编码人员带来特别令人讨厌的惊喜。
  • 这段代码缺少一堆标题和一个重复报告问题的main函数。
  • 好的...乍一看,您至少缺少几个编译器指令:#include 和 #include...如果我是您的编译器,我会争论你也是。你似乎以一种我以前从未见过的方式滥用“getline”,我有点喜欢那样,因为它是新的和令人耳目一新的,但它不会起作用。阅读使用“getline”或以其他方式完成业务。
  • 现在我看到您还需要#include...您还遇到了一大堆类型转换问题...什么编译器允许您编译和运行这个烂摊子? ??

标签: c++ graph path infinite-loop


【解决方案1】:

printAllPathsUtil:

// Recur for all the vertices adjacent to current vertex
list<int>::iterator i;
  for (i = adj[u].begin(); i != adj[u].end(); ++i)
    if (!visited[*i])
      printAllPathsUtil(*i, d, visited, path, path_index);

// Remove current vertex from path[] and mark it as unvisited
visited[u] = false;

因此,直到您完成探索 F 之后,您才将 B 标记为已访问。并且直到 您完成探索之后,您才将 F 标记为已访问探索 B. 所以你在这两个房间之间来回穿梭,就像在无尽的走廊里冲锋一样。

在您探索相邻房间之前将 B 标记为已访问。

【讨论】:

  • 这得到了我想要的!非常感谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-08-17
  • 1970-01-01
  • 2013-12-06
  • 2014-09-14
  • 2016-06-25
  • 2014-04-14
  • 2019-10-20
相关资源
最近更新 更多