[英]Nodes in binary tree are null
void MultiMap::insert(string key, unsigned int value)
{
if(head == nullptr)
head = new Node(key, value);
else
{
Node* tempNode = head;
while(tempNode != nullptr)
{
if(key <= tempNode->m_key)
tempNode = tempNode->m_left;
else if(key > tempNode->m_key)
tempNode = tempNode->m_right;
}
/*line 1*/tempNode = new Node(key, value);
//*line 2*/head->m_left = new Node(key, value);
}
}
对于赋值,我必须创建一个二叉树类,“MultiMap”,其中包含一个包含字符串和int的节点。
以上是将新节点插入树中的代码。 节点按字符串排序。 如果我尝试插入的节点的字符串是>当前节点,程序应该尝试将其插入树的右侧分支,如果它是<=,程序应该尝试将其插入左侧分支这棵树
我通过尝试按顺序插入两个节点来测试它:(Joe,5)和(Bill,1),所以如果程序正常工作,“bill”应该在“joe”的左侧分支上。
第2行已注释掉。
如果我使用第1行,程序将编译并“插入”第二个节点,但是当我尝试使用其他代码查找它时,它只会找到一个nullptr。 如果我用第2行替换第1行,程序将按预期工作。
“tempNode”是我用来跟踪树以找到插入新节点的适当位置。 “head”是指向树中第一个节点的指针。 “m_left”和“m_right”是指向节点的指针,分别代表节点的左右分支。
我不知道为什么这两行不会做同样的事情,即使在那一点上,似乎tempNode和head-> m_left指向内存中的相同位置:第一个节点的左分支。
指针持有地址的变量。 他们没有什么魔力。 第1行执行此操作:
tempNode = new Node(key, value);
这不会在树中插入任何内容。 事实上,它只是泄漏了内存。
在此语句之前指向的tempNode
是无关紧要的。 更重要的是, tempNode
如何保持先前的值已经丢失,因为你已经从树下降了一级。 保持相同地址的两个指针只意味着可以使用两个指针访问该地址。 为指针分配新地址对先前寻址的实体(如果有的话) 没有影响 。
您的任务应该是找到应该用新分配的对象的地址填充的指针 。 你找到了(有点)。 不幸的是,一旦你走进树中进行最后的零检测,你也会丢失它。 一旦这个:
while (tempNode != nullptr)
变得虚假和破碎,你已经是一个节点太远了。 有很多方法可以解决这个问题。 有些人喜欢使用“父”指针,但这只意味着你需要特殊情况下的空映射条件。 请考虑一下:
void MultiMap::insert(string key, unsigned int value)
{
// pp will always point to the pointer we're testing
// i.e. a pointer to pointer.
Node **pp = &head;
while (*pp) // while whatever pp points to is a non-null-pointer
{
if (key < (*pp)->m_key)
pp = &(*pp)->m_left; // put address of left-pointer into pp
else if ((*pp)->m_key < key)
pp = &(*pp)->m_right; // put address of right pointer into pp
else break; // strict weak order match
}
if (*pp)
{
// found matching key. NOTE: unclear if you wanted to just update or not
}
else
{
// allocate new node.
*pp = new Node(key,value);
}
}
除了用头节点指针的地址初始化指针到指针之外,你还会注意到,不会再次引用head。
最后,注意没有特殊情况的头节点测试。 如果映射为空且头指针为NULL,则会自动创建一个新节点并使其成为根节点。
这里发生了什么:
Node* tempNode = head;
while(tempNode != nullptr)
{
if(key <= tempNode->m_key)
tempNode = tempNode->m_left;
else if(key > tempNode->m_key)
tempNode = tempNode->m_right;
}
好的,现在tempNode == nullptr
, 它不指向树的任何节点 。 因为它是堆栈上的变量,所以下一行:
/*line 1*/tempNode = new Node(key, value);
只是初始化这个本地指针, 不会影响树本身。 (这里真的是内存泄漏。)在第二行中,初始化树中的节点:
head->m_left = new Node(key, value);
但仅适用于head-> m_left。 所以你可以写:
if (key <= tempNode->m_key) {
if (tempNode->m_left == nullptr) {
tempNode->m_left = new Node(key, value);
break; // traverse tree loop
} else {
tempNode = tempNode->m_left;
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.