从未知结构C++构造一个树(非二进制)结构
Construct a tree(non-binary) structure from an unknown struct C++
我需要根据传递给我的结构,向树的特定分支动态添加子节点。例如,我有一个这样的结构:
struct my_struct
{
int a;
int b;
char c;
}
在我的功能中,在移动到所需的节点后,我应该能够将子节点添加到特定节点,类似于以下内容:
root
|
son------daughter----another_son
|
a---b--c
我的树节点结构如下:
struct tree{
string name;
int child_count;
int value;
vector< tree* > child;
};
由于我想稍后更新这些变量中的每一个,所以我想为结构中的每个变量分离出节点。由于结构可以在我不知情的情况下更新,我希望逻辑与结构无关。
好吧,我可以建议一种方法,而不需要太深入的细节。我会设置类似于下面代码的东西。基本上,有一个通用结构允许某种简化的内省,通过重新定义子结构中的两个纯虚拟方法,该算法将能够将结构"树化"为子节点。最后你会发现一个树"导航"的例子。好吧,这只是一个非常快速的例子,决不能认为它是详尽的,你会注意到它没有为更复杂的结构实现任何类型的树递归。无论如何,我不知道为什么选择structs而不是class来处理所有这些。想想看!
#include <vector>
#include <string>
#include <iostream>
// Allowed data types
enum MyTypes {
INT,
DOUBLE,
NODATA
};
// Base source struct
struct MyBaseStruct {
std::vector <std::string> ids;
virtual MyTypes getType(std::string id) = 0;
virtual void *getPointer(std::string id) = 0;
};
// Example of used struct
struct MyStructA: MyBaseStruct {
int a;
double b;
MyStructA();
MyTypes getType(std::string id);
void *getPointer(std::string id);
};
MyStructA::MyStructA()
{
ids.push_back("a");
ids.push_back("b");
}
MyTypes MyStructA::getType(std::string id)
{
if (id == "a")
return INT;
else if (id == "b")
return DOUBLE;
return NODATA;
}
void *MyStructA::getPointer(std::string id)
{
if (id == "a")
return static_cast <void *> (&a);
else if (id == "b")
return static_cast <void *> (&b);
return 0;
}
struct MyTreeNode {
std::string id;
MyTypes type;
void *pointer;
std::vector <MyTreeNode *> children;
void addChildren(MyBaseStruct &data);
};
void MyTreeNode::addChildren(MyBaseStruct &data)
{
std::vector <std::string>::const_iterator i(data.ids.cbegin());
while (i != data.ids.cend()) {
MyTreeNode *newNode= new MyTreeNode;
newNode->id= (*i);
newNode->type= data.getType(*i);
newNode->pointer= data.getPointer(*i);
children.push_back(newNode);
i++;
}
}
int main(int /*argc*/, char * /*argv[]*/)
{
MyStructA a;
a.a= 1;
a.b= 12.34;
MyTreeNode treeRoot;
treeRoot.id= "root of my tree";
treeRoot.type= NODATA;
treeRoot.pointer= 0;
treeRoot.addChildren(a);
// Example of tree navigation
std::vector <MyTreeNode *>::const_iterator i(treeRoot.children.cbegin());
while (i != treeRoot.children.cend()) {
std::cout << (*i)->id << ": ";
if ((*i)->pointer) {
if ((*i)->type == INT) {
std::cout << *(static_cast <int *> ((*i)->pointer)) << "n";
}
if ((*i)->type == DOUBLE) {
std::cout << *(static_cast <double *> ((*i)->pointer)) << "n";
}
}
i++;
}
}
如果有时间,还可以考虑编写一种变体类来处理不同类型的数据类型,从而避免在多个位置强制转换值的需要。
struct tree{
string name;
my_struct structure;
int sonc;
vector< tree* > child;
};
我建议您使用Node作为树节点的结构名称(那些可组装树的节点)并使用诸如"父"answers"子"之类的术语来表示树中不同深度的节点。
顺便说一句,如果您想向上遍历树,我建议添加另一个指向节点父节点的指针。
然后编写一个函数,其中有一个Node(树)作为参数醚,向其中添加子项。。。
像这样:
addToTree(tree node, other parameters, like struct...)
{
tree newNode = new tree();
//do what you want with the new node...
node.children.add(newNode);
node.sonc++;
newNode.Parent = node;
}
使用数据类型
struct data {
string name;
my_struct structure;
int sonc;
};
并定义您的树一般。
现在我建议使用Boost Containers,这样你就可以创建一个不完整类型的向量/list/deque:
template <typename Data>
struct node
{
Data _data;
boost::deque<node> _children;
};
或者,如果你赞成继承,这也可能有效:
template <typename Data>
struct node : public Data
{
boost::deque<node> _children;
};
这样可以省去手动分配管理的所有麻烦
或者,您可以使用std::unique_ptr<node>
来避免手动进行内存管理(提示:这很难。想想异常安全、自分配、循环)
甚至,使用boost::variation:
typedef boost::make_recursive_variant<data, std::vector<boost::recursive_variant_> >::type tree;
什么最适合你取决于申请。
- 预处理器:插入结构名称中的前一个行号
- 为什么在没有显式默认构造函数的情况下,将另一个结构封装在联合中作为成员的结构不能编译
- 我不明白为什么我声明一个空的内部结构并将其传递给构造函数
- 静态结构和一个定义规则
- 为什么将一个结构的引用设置为等于另一个结构只会更改一个数据成员?
- C++ - 如何在结构向量中找到结构体一个成员的最大值?
- 如何在 C++11 中查找和更新向量中的一个嵌套结构
- 在学习数据结构之前对STL有一个了解是好的吗?
- 给定一个C++嵌套的私有结构类型,是否有从文件范围静态函数访问它的策略
- 从另一个 cpp 文件更改结构内、映射键内的变量
- 如何将一个结构的字符数组复制到结构的另一个字符数组中?
- 使用完数据结构后清空数据结构是一个好习惯吗?
- 如何制作一个地图,其中的值是C++中的结构数组
- 如何将数据从一个结构链接到另一个结构
- 是否可以使用智能指针成员设置具有另一个结构的结构?
- error dllimport 函数的定义不允许在一个特定的联合中,而其他类、结构和联合将按预期导出
- std::transform 将一个结构数组复制到另一个结构数组
- C++:如何做一个链表,结构作为参数传递?
- 输入 ctrl + x 后如何再次 cin (cin<<x) 循环(cin 一个结构)
- 两个附带的类层次结构-一个好的设计模式