遍历常规节点类,列出所有节点会导致无限循环

时间:2019-02-04 21:13:27

标签: c++ algorithm tree

我正在练习遍历树/节点,因此遇到了当前问题。我希望能够将一个节点连接到自身。将节点1连接到节点2。可以根据需要将节点连接到尽可能多的节点。这是我编写并正在练习的当前课程。

我的问题是我无法检查是否已遍历过去的节点。我得到的是一个无限循环,该循环为1-> 2-> 3-> 4-> 1-> 2 ...等。

是否可以向正确的方向提示?

我希望nodeN.list_connections()能够打印出nodeN连接到的所有节点。

class Node {
private:
    std::vector<Node*> nodes;
    std::string data;
public:
    Node()
    {
        printf("Status: Created [%d]\n", this);
    }
    void connect(Node& node)
    {
        nodes.push_back(&node);
        printf("Status: Node [%d] Connected To [%d]\n", this, &node);
    }
    void input_data(std::string str_in)
    {
        data = str_in;
    }
    void list_connections()
    {
        printf("List: Start\n");
        printf("Node[this][%d]: %s\n", this, data.c_str());
        for (size_t i = 0; i < nodes.size(); i++)
        {
          printf("Node[i=%d][%d]: %s\n", i, nodes[i], nodes[i]->data.c_str());
          if (this != nodes[i])
             nodes[i]->list_connections();
        }
    }
};

void test_list()
{
    Node one;
    one.input_data("ONE");
    Node two;
    two.input_data("TWO");
    Node three;
    three.input_data("THREE");
    Node four;
    four.input_data("FOUR");

    // one -> two <-> three -> four -> one
    // one -> one
    // two -> two

    one.connect(two);
    one.connect(one);
    two.connect(two);
    two.connect(three);
    three.connect(four);
    four.connect(one);
    three.connect(two);

    one.list_connections();
    //two.list_connections();
    //three.list_connections();
    //four.list_connections();
}

这是我上面的代码。

我的test_list函数测试所有可能的连接方案。

编辑:

我的nodeOne.list_connections()的当前想法是,它将遍历连接到nodeOne的所有节点。仅当当前节点未连接到其他节点时,这些节点才会使用nodeOther.list_connections()。

编辑:

所有节点都以某种方式连接。列出连接时,它将仅列出该节点向下的连接。列表节点将不会返回到根节点/第一个节点。

编辑:

仅使用one.list_connections();输出应该是

 List: Start
 Node[this][7731340]: ONE
 Node[i=0][7731288]: TWO
 Node[i=1][7731340]: ONE
 List: Start
 Node[this][7731288]: TWO
 Node[i=0][7731288]: TWO
 Node[i=1][7731236]: THREE
 List: Start
 Node[this][7731236]: THREE
 Node[i=0][7731184]: FOUR
 Node[i=1][7731288]: TWO
 List: Start
 Node[this][7731184]: FOUR
 Node[i=0][7731340]: ONE

谢谢StephanH指出来。

1 个答案:

答案 0 :(得分:0)

您必须解决图论中的一个常见位置问题(避免循环)。您可以创建一个简单的Path类来跟踪当前递归堆栈中是否已经/或当前正在打印一个节点。因此,您必须检查新节点是否已经在递归堆栈中。让我们使用应用于存储节点ID的整数矢量的标准std :: find()。为了提高可读性和易用性,我将其包装在bool Path::closeCycle(int nid)中。由于路径最多可以包含| N |个元素Path类也可以由n维vector<bool>表示,这将避免使用std::find()。这可以提高性能,但是这可能取决于图形的结构(长路径+少节点vs.短路径+大量节点vs.极值之间的东西)。

在node.h

#include <cstdlib>
#include <string>
#include <vector>
#include <algorithm>


class Path
{
    std::vector<int> vals;
public:
    Path();
    bool closeCycle(int nid)const;
    void add(int nid);
};

class Node {
private:
    int id;
    std::vector<Node*> nodes;
    std::string data;
public:
    Node(int id) : id(id)
    {
        printf("Status: Created [%d]\n", this);
    }
    void connect(Node& node)
    {
        nodes.push_back(&node);
        printf("Status: Node [%d] Connected To [%d]\n", this, &node);
    }
    void input_data(std::string str_in)
    {
        data = str_in;
    }
    void list_connections(const Path& path = Path());
    inline int getId()const { return id; }
};

在node.cpp中

#include "header.h"

void Node::list_connections(const Path& path)
{
    printf("List: Start\n");
    printf("Node[this][%d]: %s\n", this, data.c_str());


    Path npath(path);
    npath.add(id);
    for (size_t i = 0; i < nodes.size(); i++)
    {
        if (!npath.closeCycle(nodes[i]->id))
        {
            printf("Node[i=%d][%d]: %s\n", i, nodes[i], nodes[i]->data.c_str());
            nodes[i]->list_connections(npath);
        }
    }
    printf("List: %s End\n", data.c_str());
}



Path::Path()
{
}

bool Path::closeCycle(int nid) const
{
    return std::find(vals.begin(), vals.end(), nid) != vals.end();
}

void Path::add(int nid)
{
    vals.push_back(nid);
}

您的main.cpp

void main()
{
    Node one(1);
    one.input_data("ONE");
    Node two(2);
    two.input_data("TWO");
    Node three(3);
    three.input_data("THREE");
    Node four(4);
    four.input_data("FOUR");

    one.connect(two);
    one.connect(one);
    two.connect(two);
    two.connect(three);
    three.connect(four);
    four.connect(one);
    three.connect(two);

    one.list_connections();
    std::cout << "\n\n";
    two.list_connections();
    std::cout << "\n\n";
    three.list_connections();
    std::cout << "\n\n";
    four.list_connections();
    std::cout << "\n\n";

    system("pause");
}