簡體   English   中英

頭指針不包含二叉樹中的子節點

[英]Head pointer doesn't contain child nodes in Binary Tree

我正在復制一棵二叉樹,但我遇到了一個問題,即新樹的根指針最終只包含要復制的第一個節點,而沒有其他節點。 我相信這個問題與這樣一個事實有關,即當我在輔助函數的遞歸中傳遞指針時,由於某種原因,它們沒有被重新分配給新節點的內存地址。 就像在helper(t1->left, t2->left) t2->left 中一樣,實際上並沒有最終成為我想要的值,它保持為空。

   bool first_time = true;
   TreeNode* ref = NULL;
    void helper(TreeNode* t1, TreeNode* t2) {
        if(t1) {
            t2 = new TreeNode(t1->val);
            if(first_time) {
                ref = t2;
                first_time = false;
            }
            helper(t1->left, t2->left);
            helper(t1->right, t2->right);
        }
        
    }
    TreeNode* mergeTrees(TreeNode* t1, TreeNode* t2) {
        TreeNode* tree1 = new TreeNode(1);
        tree1->left = new TreeNode(2);
        tree1->right = new TreeNode(3);
        helper(tree1, NULL);
        return ref;
    }

檢查您的全局變量first_timeref

if (first_time) {
  ref = t2;           // global
  first_time = false; // global set to never go here again
}

它實際上是您問題的根源 - 一旦您將第一個節點傳遞給您的函數,您就更改了其他全局變量ref並且此后永遠不會在任何地方更改它。 因此,基本上,在每次遞歸調用中,您都會使用懸空指針泄漏內存。 可能,您應該將參數first_time傳遞給您的函數,並且可能將ref作為參數傳遞為可分配的

你在這里有幾個問題。

首先, reffirst_time是嚴重的缺陷,您應該避免編寫具有這種全局狀態的代碼。 它不是可重入的,也不是線程安全的。

其次,您嘗試寫入 t2 指針並將調用者的指針更改為該值。 但是,您傳入的是 t2 的副本,因此寫入的內容將丟失。

清理它不需要太多,只需更改您的函數以獲取對指針引用,並且對 t2 的寫入將持續返回給調用者。 請注意,t2 是一個“out”參數,因此初始調用者將通過此指針獲取返回的樹副本。

這是一個固定版本:

void helper(TreeNode* t1, TreeNode*& t2) {
    if(t1) {
        t2 = new TreeNode(t1->val);
        helper(t1->left, t2->left);
        helper(t1->right, t2->right);
    }  
}

這是您的測試函數的樣子:

TreeNode* copyTest() {
    TreeNode* tree1 = new TreeNode(1);
    tree1->left = new TreeNode(2);
    tree1->right = new TreeNode(3);
    
    TreeNode* tree2 = nullptr;
    helper(tree1, tree2);  // tree2 is written to as new root.
    return tree2;
}

但是如果不需要 out 參數,通常不鼓勵使用。

為什么不編寫 copyTree 函數來返回指向復制樹的指針? 基本上去掉in的第二個參數,並分配當前樹的副本,向下遞歸,將每個子副本附加到當前節點的父副本,並返回父節點:

TreeNode* copyTree(TreeNode* tree) {
    TreeNode* ret = nullptr;
    if (tree) {
        ret = new TreeNode(tree->val);
        ret->left = copyTree(tree->left);
        ret->right = copyTree(tree->right);
    }
    return ret;
}

除非您非常小心,否則這不是防止泄漏的好方法,但它有助於理解遞歸和樹結構。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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