我正在尝试将摩尔斯电码插入二叉树,但我的Insert()
正在执行。我很难过为什么会失败。
二叉树类:
class BST
{
private:
struct Node
{
string letter;
string code;
Node *left;
Node *right;
};
Node *root;
public:
BST()
{
root = NULL;
}
void Insert(Node *&r, string letter, string code)
{
if(r == NULL)
{
r = new Node;
r->letter = letter;
r->code = code;
r->left = r->right = NULL;
}
}
void Insert(string letter, string code)
{
Node *r = root;
if(r != NULL)
{
for(int i = 0; i < code.length(); i++)
{
if(code[i] == '.') r = r->left;
else if(code[i] == '-') r = r->right;
else break;
}
Insert(r, letter, code);
}
else Insert(root, letter, code);
}
};
主:
struct alphaTree
{
string letter;
string code;
};
alphaTree tree[] = {
{"ROOT", ""}, {"E", "."}, {"T", "-"}, {"I", ".."}, {"A", ".-"}, {"N", "-."},
{"M", "--"}, {"S", "..."}, {"U", "..-"}, {"R", ".-."}, {"W", ".--"}, {"D", "-.."},
{"K", "-.-"}, {"G", "--."}, {"O", "---"}, {"H", "...."}, {"V", "...-"}, {"F", "..-."},
{"L", ".-.."}, {"P", ".--."}, {"J", ".---"}, {"B", "-..."}, {"X", "-..-"}, {"C", "-.-."},
{"Y", "-.--"}, {"Z", "--.."}, {"Q", "--.-"}
};
for(int i = 0; i < 27; i++)
{
t.Insert(tree[i].letter, tree[i].code);
}
我的tree[]
数组的前3个元素已插入但尝试插入"I"
时程序崩溃。
答案 0 :(得分:1)
插入新节点时,父节点左右不会更新。
您可能认为父母已更新,因为您通过引用传递指针,但您传递的是r
而不是r->left
或r->root
。
一种可能的解决方案是使用**r
代替*r
中的void Insert(string letter, string code)
您可以更改以下内容:(Working example here)
void Insert(string letter, string code)
{
Node **r = &root;
if(*r != NULL)
{
for(int i = 0; i < code.length(); i++)
{
assert(*r);
if(code[i] == '.') r = &((*r)->left);
else if(code[i] == '-') r = &((*r)->right);
else break;
}
Insert(*r, letter, code);
}
else Insert(root, letter, code);
}
与您的问题无关,但作为旁注:
for(int i = 0; i < code.length(); i++)
你正在比较一个
带有singed int的unsigned(length)。您应该将i
更改为
的std :: string :: size_type的。void Insert(string letter, string code)
中,您应该添加
在访问*r
个孩子之前断言(* r)。答案 1 :(得分:1)
你的问题在这里:
for(int i = 0; i < code.length(); i++)
{
if(code[i] == '.') r = r->left;
else if(code[i] == '-') r = r->right;
else break;
}
此循环开始时,请确保r
永远不会NULL
。然而,由于树中只有一个元素,当您将其设置为NULL
或r = r->left
时,它将立即变为r = r->right
以进行下一次迭代,因为在该树中只有一个节点树及其left
和right
都是NULL
。
循环时,您不会检查r
是否变为NULL
。
越早到达摩尔斯电码中包含两个或更多符号的元素,当r
指针成为NULL
时,您的应用程序就会尝试从for(int i = 0; i < code.length(); i++)
{
if (code[i] == '.')
{
if (r->left)
r = r->left;
else
{
// todo: code to bind a new node to r->left
break;
}
}
else // its always either '.' or '-' so there is no need to double check the symbol here
{
if (r->right)
r = r->right;
else
{
// todo: code to bind a new node to r->right
break;
}
}
}
读取。
您可能希望将代码扩展为更像这样的代码:
r
现在,您确保循环停止,而left
仍然是有效指针。降序树中的最后一个有效指针。
当然,您仍然必须决定在此节点的right
或{{1}}侧创建新节点。