我正在练习遍历树/节点,因此遇到了当前问题。我希望能够将一个节点连接到自身。将节点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指出来。
答案 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");
}