簡體   English   中英

通過有向圖中的bfs搜索顯示最短路徑

[英]Displaying shortest path via bfs search in directed graph

我一直在為一個大學項目工作,遇到了一個很大的問題。 我應該做一個函數,以通過有向圖從A點到B點獲得最短路徑,並按順序顯示路徑。

EX。 如果該節點擁有州名,並且我們想查找加利福尼亞和猶他州之間的最短路徑,則輸出將顯示加利福尼亞->內華達州->猶他州

當前,我的遍歷顯示所有使用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;
}

//定義圖私有成員

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;

第一個問題是for循環中的if 您的path變量只能包含兩項:開始節點和結束節點。 我建議您不要使用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[GetNodeIndex(startNode)]->Distance = 0;

在每次迭代中,從隊列中選擇一個節點(您稱為index ),遍歷其鄰接表(外向弧),並測試是否訪問了相鄰節點。 如果訪問了該節點,請跳過它。 如果未訪問該節點,則將其距離設置為

m_nodes[index]->Distance + 1

更新每個節點的距離后,檢查它是否是最后一個節點,如果是這樣,請跳出循環。

此時,您的距離已正確更新。 每次從鄰接節點向后移動,每次從(距離=當前節點的距離-1)從鄰接列表中選擇該節點。 每次您真正知道targetI時 ,都可以使用m_edges向量進行此操作,因此可以使用上述距離值檢查其對應的scrI

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM