簡體   English   中英

二叉樹中的節點為空

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

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM