简体   繁体   English

深度优先搜索:格式化输出?

[英]Depth First Search: Formatting output?

If I have the following graph: 如果我有以下图表:

  Marisa  Mariah
       \  / 
Mary---Maria---Marian---Maryanne
         |
Marley--Marla

How should be Depth First Search function be implemented such that I get the output if "Mary" is my start point ? 如果“玛丽”是我的起点,我应该如何实现深度优先搜索功能?

Mary
   Maria
       Marisa
       Mariah
       Marian
            Maryanne
       Marla
            Merley

I do realize that the number of spaces equal to depth of the vertex( name ) but I don't how to code that. 我确实知道空格的数量等于顶点(名称)的深度,但我不知道如何编码。 Following is my function: 以下是我的功能:

void DFS(Graph g, Vertex origin)
{
    stack<Vertex> vertexStack;
    vertexStack.push(origin);
    Vertex currentVertex;
    int currentDepth = 0;

    while( ! vertexStack.empty() )
    {
        currentVertex = vertexStack.top();
        vertexStack.pop();

        if(currentVertex.visited == false)
        {
            cout << currentVertex.name << endl;

            currentVertex.visited = true;
            for(int i = 0; i < currentVertex.adjacencyList.size(); i++)
                vertexStack.push(currentVertex.adjacencyList[i]);
        }

    }
}

Thanks for any help ! 谢谢你的帮助 !

Just store the node and its depth your stack: 只需将节点及其深度存储在堆栈中:

std::stack<std::pair<Vertex, int>> vertexStack;
vertexStack.push(std::make_pair(origin, 0));
// ...
std::pair<Vertex, int> current = vertexStack.top();
Vertex currentVertex = current.first;
int     depth        = current.second;

If you want to get fancy, you can extra the two values using std::tie() : 如果你想获得花哨,你可以使用std::tie()来增加两个值:

Vertex currentVertex;
int    depth;
std::tie(currentVertex, depth) = vertexStack.top();

With knowing the depth you'd just indent the output appropriately. 知道depth您只需适当地缩进输出。

The current size of your stack is, BTW, unnecessarily deep! 你的堆栈的当前大小是BTW,不必要地深! I think for a complete graph it may contain O(N * N) elements (more precisely, (N-1) * (N-2)). 我认为对于完整的图,它可能包含O(N * N)个元素(更确切地说,(N-1)*(N-2))。 The problem is that you push many nodes which may get visited. 问题是你推送了许多可能被访问过的节点。

Assuming using an implicit stack (ie, recursion) is out of question (it won't work for large graphs as you may get a stack overflow), the proper way to implement a depth first search would be: 假设使用隐式堆栈(即递归)是不可能的(它不适用于大型图形,因为您可能会出现堆栈溢出),实现深度优先搜索的正确方法是:

  1. push the current node and edge on the stack 推送堆栈上的当前节点和边缘
  2. mark the top node visited and print it, using the stack depth as indentation 标记访问的顶级节点并使用堆栈深度作为缩进打印它
  3. if there is no node 如果没有节点
  4. if the top nodes contains an unvisited node (increment the edge iterator until such a node is found) go to 1. 如果顶部节点包含一个未访问的节点(增加边缘迭代器直到找到这样的节点),请转到1。
  5. otherwise (the edge iterator reached the end) remove the top node and go to 3. 否则(边缘迭代器到达终点)删除顶部节点并转到3。

In code this would look something like this: 在代码中,这看起来像这样:

std::stack<std::pair<Node, int> > stack;

stack.push(std::make_pair(origin, 0));
while (!stack.empty()) {
    std::pair<Node, int>& top = stack.top();
    for (; top.second < top.first.adjacencyList.size(); ++top.second) {
         Node& adjacent = top.first.adjacencyList[top.second];
         if (!adjacent.visited) {
              adjacent.visted = true;
              stack.push(std::make_pair(adjacent, 0));
              print(adjacent, stack.size());
              break;
         }
     }
     if (stack.top().first.adjacencyList.size() == stack.top().second) {
          stack.pop();
     }
 }

Let Rep(Tree) be the representation of the tree Tree . Rep(Tree)成为树Tree的表示。 Then, Rep(Tree) looks like this: 然后, Rep(Tree)看起来像这样:

Root
  <Rep(Subtree rooted at node 1)>
  <Rep(Subtree rooted at node 2)>
               .
               .
               .

So, have your dfs function simply return the representation of the subtree rooted at that node and modify this value accordingly. 因此,让您的dfs函数只返回以该节点为根的子树的表示,并相应地修改该值。 Alternately, just tell every dfs call to print the representation of the tree rooted at that node but pass it the current depth. 或者,只需告诉每个dfs调用打印以该节点为根的树的表示,但将其传递给当前深度。 Here's an example implementation of the latter approach. 这是后一种方法的示例实现。

void PrintRep(const Graph& g, Vertex current, int depth)
{
   cout << std::string(' ', 2*depth) << current.name << endl;
   current.visited = true;
   for(int i = 0; i < current.adjacencyList.size(); i++)
      if(current.adjacencyList[i].visited == false)
         PrintRep(g, current.adjacencyList[i], depth+1);           
}

You would call this function with with your origin and depth 0 like this: 您可以使用您的原点和深度0调用此函数,如下所示:

PrintRep(g, origin, 0);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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