简体   繁体   中英

Algorithm finding path in an undirected tree

Suppose I am given a undirected tree and I need to find a path(the only path) between two nodes.

What is the best algorithm to do it.I probably could use a Dijkstra's algorithm but there a probably something better for trees.

C++ example would be helpful but not necessary

Thank you

Assuming each node has a pointer to its parent, then simply back-track up the tree towards the root from each start node. Eventually, the two paths must intersect. Testing for intersection could be as simple as maintaining a std::map of node addresses.

UPDATE

As you've updated your question to specify undirected trees, then the above isn't valid. A simple approach is simply to perform a depth-first traversal starting at Node #1, eventually you'll hit Node #2. This is O(n) in the size of the tree. I'm not sure there's going to be a faster approach than that, assuming a completely general tree.

Supposing you have

struct Node
{
    std::vector<Node *> children;
};

then what could be done is traversing the whole tree starting at root keeping the whole chain during the traversal. If you find eg node1 then you save the current chain, if you find node2 then you check for the intersection... in code ( UNTESTED ):

bool findPath(std::vector<Node *>& current_path, // back() is node being visited
              Node *n1, Node *n2,                // interesting nodes
              std::vector<Node *>& match,        // if not empty back() is n1/n2
              std::vector<Node *>& result)       // where to store the result
{
    if (current_path.back() == n1 || current_path.back() == n2)
    {
        // This is an interesting node...
        if (match.size())
        {
            // Now is easy: current_path/match are paths from root to n1/n2
            ...
            return true;
        }
        else
        {
            // This is the first interesting node found
            match = current_path;
        }
    }
    for (std::vector<Node *>::iterator i=current_path.back().children.begin(),
                                       e=current_path.back().children.end();
         i != e; ++i)
    {
        current_path.push_back(*i);
        if (findPath(current_path, n1, n2, match, result))
          return true;
        current_path.pop_back(); // *i
    }
    return false;
}

广度优先搜索和深度优先搜索比Dijkstra算法更有效。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM