Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/149.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在有向图中通过bfs搜索显示最短路径_C++_Algorithm_Graph Theory - Fatal编程技术网

C++ 在有向图中通过bfs搜索显示最短路径

C++ 在有向图中通过bfs搜索显示最短路径,c++,algorithm,graph-theory,C++,Algorithm,Graph Theory,我一直在为大学做一个项目,遇到了一个相当大的问题。我要做一个函数,通过一个有向图,从点a到点B,得到最短路径,并按顺序显示路径 例如,如果节点拥有一个州名,并且我们想要找到加利福尼亚州和犹他州之间的最短路径,那么输出将显示California->nevada->Utah 目前,我的遍历显示了使用bfs搜索的所有节点,而不是从A点到B点的节点列表 以下是我执行任务的情况。我唯一真正的问题是,我如何跟踪我实际遍历的节点,而不是搜索的所有节点 bool DirectedGraph::GetShorte

我一直在为大学做一个项目,遇到了一个相当大的问题。我要做一个函数,通过一个有向图,从点a到点B,得到最短路径,并按顺序显示路径

例如,如果节点拥有一个州名,并且我们想要找到加利福尼亚州和犹他州之间的最短路径,那么输出将显示California->nevada->Utah

目前,我的遍历显示了使用bfs搜索的所有节点,而不是从A点到B点的节点列表

以下是我执行任务的情况。我唯一真正的问题是,我如何跟踪我实际遍历的节点,而不是搜索的所有节点

bool DirectedGraph::GetShortestPath(
const string& startNode, const string& endNode, 
bool nodeDataInsteadOfName, vector<string>& traversalList) const
{

//Nodes are the same
if (startNode.compare(endNode) == 0)
    return false;

//Stores the location of our nodes in the node list
vector<int> path;

//Queue to hold the index of the node traversed 
queue<int> q;

//Create our boolean table to handle visited nodes
bool *visited = new bool[m_nodes.size()];
//initialize bool table
memset(visited, false, sizeof(bool) * m_nodes.size());

//Label the start node as visited
visited[GetNodeIndex(startNode)] = true;
//Push the node onto our queue
q.push(GetNodeIndex(startNode));



while (!q.empty())
{
    //Store the nodes index
    int index = q.front();
    path.push_back(q.front());
    q.pop();

    int i = 0;
    for (i = 0; i < m_nodes[index]->Out.size(); i++)
    {
        //If this node matches what we are looking for break/return values
        if (m_nodes[index]->Out[i]->targetI == GetNodeIndex(endNode))
        {
            path.push_back(m_nodes[index]->Out[i]->targetI);
            if (nodeDataInsteadOfName)
            {
                path.push_back(m_nodes[index]->Out[i]->targetI);
                for (int x = 0; x < path.size(); x++)
                {
                    traversalList.push_back(m_nodes[path[x]]->Data);
                }
            }
            else
            {
                for (int x = 0; x < path.size(); x++)
                {
                    traversalList.push_back( m_nodes[path[x]]->Name);
                }
            }

            return true;
        }


        //Continue through the data
        if (!visited[m_nodes[index]->Out[i]->targetI])
        {
            visited[m_nodes[index]->Out[i]->targetI] = true;
            q.push(m_nodes[index]->Out[i]->targetI);
        }
    }

}
// You must implement this function
return false;
}
bool DirectedGraph::GetShortestPath(
常量字符串和起始节点,常量字符串和结束节点,
bool nodedaintosteofname、vector和traversalList)const
{
//节点是相同的
if(startNode.compare(endNode)==0)
返回false;
//在节点列表中存储节点的位置
向量路径;
//用于保存所遍历节点的索引的队列
队列q;
//创建布尔表以处理访问的节点
bool*visted=新bool[m_nodes.size()];
//初始化布尔表
memset(已访问,false,sizeof(bool)*m_nodes.size());
//将开始节点标记为已访问
已访问[GetNodeIndex(startNode)]=true;
//将节点推到我们的队列中
q、 推送(GetNodeIndex(startNode));
而(!q.empty())
{
//存储节点索引
int index=q.front();
路径。向后推(q.front());
q、 pop();
int i=0;
对于(i=0;iOut.size();i++)
{
//如果此节点与我们要查找的中断/返回值匹配
if(m_节点[index]->Out[i]->targetI==GetNodeIndex(endNode))
{
path.push_back(m_节点[index]->Out[i]->targetI);
if(nodedaintainsteadofname)
{
path.push_back(m_节点[index]->Out[i]->targetI);
对于(int x=0;x数据);
}
}
其他的
{
对于(int x=0;xName);
}
}
返回true;
}
//继续浏览数据
如果(!访问了[m_节点[index]->Out[i]->targetI])
{
已访问的[m_节点[index]->Out[i]->targetI]=true;
q、 推送(m_节点[index]->Out[i]->targetI);
}
}
}
//您必须实现此功能
返回false;
}
//图私有成员的定义

struct Edge
{
    int srcI; // Index of source node
    int targetI; // Index of target node
    Edge(int sourceNodeIndex, int targetNodeIndex)
    {
        srcI = sourceNodeIndex;
        targetI = targetNodeIndex;
    }
};

struct Node
{
    string Name;
    string Data;
    Node(const string& nodeName, const string& nodeData)
    {
        Name = nodeName;
        Data = nodeData;
    }

    // List of incoming edges to this node
    vector<Edge*> In;

    // List of edges going out from this node
    vector<Edge*> Out;
};

// We need a list of nodes and edges
vector<Node*> m_nodes;
vector<Edge*> m_edges;

// Used for efficiency purposes so that quick node lookups can be 
// done based on node names. Maps a node name string to the index 
// of the node within the nodes list (m_nodes).
unordered_map<string, int> m_nodeMap;
struct-Edge
{
int srcI;//源节点的索引
int targetI;//目标节点的索引
边缘(int sourceNodeIndex、int targetNodeIndex)
{
srcI=源节点索引;
targetI=targetNodeIndex;
}
};
结构体类型
{
字符串名;
字符串数据;
节点(常量字符串和节点名、常量字符串和节点数据)
{
名称=节点名称;
数据=节点数据;
}
//此节点的传入边列表
矢量输入;
//从此节点引出的边的列表
矢量输出;
};
//我们需要一个节点和边的列表
向量m_节点;
向量m_边;
//用于提高效率,以便可以进行快速节点查找
//根据节点名称完成。将节点名称字符串映射到索引
//节点列表中节点的名称(m_节点)。
无序地图m_节点地图;

第一个问题是for循环中的if问题。路径变量只能包含两项:开始节点和结束节点。我建议您不要使用for循环跟踪路径。而是为每个节点指定一个距离

struct Node
{
    string Name;
    string Data;
    int Distance;
    Node(const string& nodeName, const string& nodeData)
    {
        Name = nodeName;
        Data = nodeData;
        Distance = INT_MAX;
    }

    // List of incoming edges to this node
    vector<Edge*> In;

    // List of edges going out from this node
    vector<Edge*> Out;
};
在每次迭代中,从队列中选择一个节点(称之为索引),循环遍历其邻接列表(传出弧),并测试是否访问了相邻节点。如果访问了该节点,请跳过它。如果未访问该节点,请将其距离设置为

m_nodes[index]->Distance + 1
更新每个节点的距离后,检查它是否是最终节点,如果是,则断开循环


此时,距离已正确更新。从结束节点向后移动,每次使用(距离=当前节点的距离-1)从邻接列表中选择节点时。您可以使用m_边向量来执行此操作,每次您实际知道targetI,因此您可以使用上面提到的距离值检查其对应的scrI

如果在遍历图形时,您记得到达所遍历的每个节点所需的步数,然后在最后,你可以反向工作,以获得最短的路径。如果你发现你的目标节点距离为n,那么它与距离为n-1的节点相邻,与距离为n-2的节点相邻,等等,一直到距离为0的起始节点。你的意思是像Dijkstra的算法一样?我已经试着修改上面的代码来做你所说的,我似乎想不出一种方法来正确地存储n值。我肯定我一定错过了什么,因为这似乎应该是一个相当简单的修复。
m_nodes[index]->Distance + 1