[英]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.