[英]Insert into n-ary tree using Queue
I have a simple n-ary (3 child nodes maximum) whereby the first node inserted will be the root. 我有一个简单的n元(最多3个子节点),由此插入的第一个节点将是根节点。 Before, I add any other node, I have to search the tree and insert as a child node from a previously inserted node, if a condition is meet.
在添加任何其他节点之前,如果满足条件,我必须搜索树并从先前插入的节点作为子节点插入。 My insertion methods is overloaded for first insertion and subsequent insertions.
我的插入方法在第一次插入和随后的插入时过载。
I was able to insert the first node using this method: 我能够使用此方法插入第一个节点:
void Tree::AddSkill(char* name, char* desc, int level)
{
Skill s(name, desc, level);
Node * newNode = new Node(s);
//newNode->aSkill = Skill(name, desc, level);
newNode->parent = NULL;
for (int i = 0; i<CHILD_MAX; i++)
{
newNode->children[i] = NULL;
}
if (this->root == NULL)
{
this->root = newNode;
}
else
{
this->root->parent = newNode;
newNode->children[0] = this->root;
this->root = newNode;
}
}
I'm having a few issues with subsequent insertion into the tree, Here is the code I have so far: 我在随后插入树中遇到一些问题,这是到目前为止的代码:
void Tree::AddSkill(char* name, char* desc, int level, char* parentName)
{
if (this->root == NULL)
{
cout << "Error: no nodes in tree.\n";
return;
}
Node* node = NULL;
Skill s(name, desc, level);
Node * child = new Node(s);
while (root != NULL)
{
if (strcmp(child->aSkill.GetName(), parentName) == 0)
{
for (int i = 0; i < CHILD_MAX; i++)
{
if (node->children[i] == NULL)
{
child->aSkill = s;
child->parent = node;
node->children[i] = child;
return;
}
}
}
}
}
When I run the code through VS Debugger, the while loop in the second AddSkill
method repeats endlessly. 当我通过VS Debugger运行代码时,第二个
AddSkill
方法中的while循环不断重复。 I'm not so sure what I'm doing wrong or what concept I need to implement, any help will be appreciated. 我不确定自己在做什么错或需要实现什么概念,我们将不胜感激。
PS This is an Homework (Not sure what the appropriate tag is). PS这是一项作业(不确定适当的标签是什么)。
Update: I have tried to implement the overloaded AddSkill()
using Queue. 更新:我尝试使用Queue实现重载的
AddSkill()
。 This is what I've tried with it. 这就是我尝试过的。
void SkillTree::AddSkill(char* name, char* desc, int level, char* parentName)
{
if (this->root == NULL)
{
cout << "Error: no nodes in tree.\n";
return;
}
queue<Node*> q;
q.push(this->root);
while (!q.empty())
{
Node * n = q.front();
q.pop();
if (strcmp(n->aSkill.GetName(), parentName) == 0)
{
for (int i = 0; i<CHILD_MAX; i++)
{
if (n->children[i] == NULL)
{
Skill s(name, desc, level);
Node * child = new Node(s);
//When I comment out the next 3 lines, program does not crash. Not sure what the problem is here.
child->aSkill = s;
child->parent = n;
n->children[i] = child;
return;
}
}
return;
}
for (int i = 0; i<CHILD_MAX; i++)
{
if (n->children[i] != NULL)
{
q.push(n->children[i]);
}
}
}
}
Skill Class 技能课
#include <iostream>
#include "Skill.h"
Skill::Skill()
{
name = NULL;
desc = NULL;
level = 0;
}
Skill::Skill(char* name, char* desc, int level) : level(level), name(new char[strlen(name) + 1]), desc(new char[strlen(desc) + 1])
{
strcpy_s(this->name, (strlen(name) + 1), name);
strcpy_s(this->desc, (strlen(desc) + 1), desc);
}
Skill::Skill(const Skill& aSkill)
{
this->name = new char[strlen(aSkill.name) + 1];
strcpy_s(this->name, (strlen(aSkill.name) + 1), aSkill.name);
this->level = aSkill.level;
this->desc = new char[strlen(aSkill.desc) + 1];
strcpy_s(this->desc, (strlen(aSkill.desc) + 1), aSkill.desc);
}
Skill& Skill::operator=(const Skill& aSkill)
{
if (this == &aSkill)
return *this;
else
{
delete[] name;
delete[] desc;
name = new char[strlen(aSkill.name) + 1];
strcpy_s(name, (strlen(aSkill.name) + 1), aSkill.name);
desc = new char[strlen(aSkill.desc) + 1];
strcpy_s(name, (strlen(aSkill.desc) + 1), aSkill.desc);
level = aSkill.level;
return *this;
}
}
Skill::~Skill()
{
delete[] name;
delete[] desc;
}
char* Skill::GetName() const
{
return name;
}
char* Skill::GetDesc() const
{
return desc;
}
int Skill::GetLevel() const
{
return level;
}
void Skill::Display(ostream& out)
{
out << "- " << GetName() << " -- " << GetDesc() << " [Lvl: " << GetLevel() << "]\n";
}
Node: 节点:
Skill aSkill;
Node* parent;
Node* children[CHILD_MAX];
Node() : parent(NULL)
{
for (int i = 0; i < CHILD_MAX; i++)
{
children[i] = NULL;
}
};
Node(const Skill& n) : aSkill(n), parent(NULL)
{
for (int i = 0; i < CHILD_MAX; i++)
{
children[i] = NULL;
}
};
Here is an extract from main()
这是
main()
的摘录
SkillTree student("Student");
student.Display(cout);
student.AddSkill("Alphabet","Mastery of letters and sounds",0);
student.Display(cout);
student.AddSkill("Reading","The ability to read all manner of written material",1,"Alphabet");
student.AddSkill("Writing","The ability to put your thoughts on paper",1,"Alphabet");
student.Display(cout);
student.AddSkill("Speed Reading Level 1","Read any text twice as fast as normal",5,"Reading");
student.AddSkill("Speed Reading Level 2","Read any text four times as fast as normal",10,"Speed Reading Level 1");
student.AddSkill("Memorization","Memorize average sized texts",10,"Reading");
student.AddSkill("Massive Memorization","Memorize large sized texts",20,"Memorization");
student.AddSkill("Spell Writing","The ability to write spells",5,"Writing");
student.AddSkill("History","The ability to write (and rewrite) history",10,"Writing");
student.AddSkill("Written Creation","The ability to write things into reality",20,"History");
student.Display(cout);
The two functions that student.Display(cout);
学生的两个函数
student.Display(cout);
calls are as follow 电话如下
void Tree::Display(ostream& out)
{
out << "Skill Tree: " << title << "\n";
if (this->root == NULL)
{
cout << "Empty\n";
return;
}
else
Display_r(out, this->root, 1);
}
void Tree::Display_r(ostream& out, Node* n, int depth)
{
for (int i = 0; i<depth; i++)
{
out << " ";
}
n->aSkill.Display(out);
for (int i = 0; i<CHILD_MAX; i++)
{
if (n->children[i] != NULL)
{
Display_r(out, n->children[i], depth + 1);
}
}
}
If I comment out a section of code in the Queue implementation of AddSkill()
, I get no error. 如果我注释掉
AddSkill()
的Queue实现中的一段代码,则不会出错。
In the first AddSkill()
you insert the new node on the top of the tree, making it the new root. 在第一个
AddSkill()
,将新节点插入树的顶部,使其成为新的根。
In the second AddSkill()
you intend to insert the new node as child of a parent skill. 在第二个
AddSkill()
您打算将新节点作为父级技能的子级插入。 The approach seems to be: 该方法似乎是:
while
loop ) while
循环) for
loop) for
循环) What are the problems ? 有什么问题?
THere are several flaws in your algorithm: 这是您算法中的几个缺陷:
root
not null. root
循环不为null。 As the tree is not empty here, and as you don't delete any node, this condition will remain true, allowing for an endless loop. node
is the current node, and you insert the new child
into node
's children. node
是当前节点,然后将新的child
node
插入到该node
的child
node
。 This code is not exectuted. node
to NULL
and never changed this value. node
设置为NULL
并且从未更改过该值。 How to solve it ? 怎么解决呢?
To do this right, you'd have to start with node
at root
, then check if the node's name matches parentname
, and if yes, insert the child as you did. 为此,您必须从
root
node
开始,然后检查节点名称是否与parentname
相匹配,如果是,请像您一样插入子节点。
There's a last problem however. 但是,还有最后一个问题。 A rather important one.
一个相当重要的。 The structure of your algorithm works for a linked list traversal, but not a tree traversal .
算法的结构适用于链表遍历,而不适用于树遍历 。 The tree traversal algorithm requires either a stack/list to keep track of all the branches to explore, or a recursive approach.
树遍历算法需要堆栈/列表来跟踪要探索的所有分支,或者需要递归方法。
Here some code ( sorry, I've replaced char*
with string
and used vector<Node*>
instead of Node*[]
), using an auxiliary overload of AddSkill()
, to perform the recursive search: 这是一些代码( 对不起,我已经用
string
替换了char*
,并使用了vector<Node*>
而不是Node*[]
),并使用了AddSkill()
的辅助重载来执行递归搜索:
// replaces the former one that you had
void Tree::AddSkill(string name, string desc, int level, string parentName)
{
if (root == NULL)
{
cout << "Error: no nodes in tree.\n";
return;
}
Skill s(name, desc, level);
AddSkill(root, s, parentName);
}
// auxiliary helper
void Tree::AddSkill(Node*node, Skill& s, string& parentName)
{
if (node->sk.name == parentName) { // if found, add the new node as childen
Node * child = new Node(s);
child->parent = node;
node->children.push_back(child);
}
else {
for (auto &x : node->children) // for all the children
AddSkill(x, s, parentName); // search recursively
}
}
And here an online demo using shared pointers instead of raw pointers. 这里是使用共享指针而不是原始指针的在线演示 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.