2011-10-30 86 views
4

我想刪除使用兩種方法的樣本二叉搜索樹的左子(10)地址:指針 - 傳遞PTR到PTR或路過的PTR

  • 方法一:通過傳遞指針指向當前節點的指針。方法2:通過將指針的地址傳遞給當前節點。這不會刪除節點,但調用delete會破壞指針排列,導致在打印節點時發生崩潰。

的樹是這個樣子,我試圖刪除10,並用5

​​

我有一個指針有一定了解更換。但是,我仍然不清楚指針的這種行爲。

#include <iostream> 
class Node 
{ 
public: 
    Node(int key) : leftChild(0), rightChild(0), m_key (key){} 
    ~Node(){} 

    Node *leftChild; 
    Node *rightChild; 
    int m_key; 
}; 

Node* build1234(int, int, int, int); 
void print(Node *); 
void print1234(Node *); 

void removeLeft(Node **nodePtr) 
{ 
    Node *oldPtr = *nodePtr; 
    if(*nodePtr) 
    { 
     *nodePtr = (*nodePtr)->leftChild; 
     delete oldPtr; 
    } 
} 

int main() 
{ 
    Node *demo1 = build1234(10, 20, 30, 5); 
    Node *demo2 = build1234(10, 20, 30, 5); 
    print1234(demo1); 
    print1234(demo2); 

    //Method1 - 10 is correctly removed with 5 
    Node **nodePtr = &demo1; 
    nodePtr = &(*nodePtr)->leftChild; 
    removeLeft(nodePtr); 
    print1234(demo1); 

    //Method2 - 10 is not removed 
    Node *node = demo2; 
    node = node->leftChild; 
    removeLeft(&node); 
    print1234(demo2);  
    return 0; 
} 

Node* build1234(int B, int A, int C, int D) 
{ 
    Node *root = new Node(A); 
    root->leftChild = new Node(B); 
    root->rightChild = new Node(C); 
    root->leftChild->leftChild = new Node(D); 
    return root; 
} 
void print(Node *node) 
{ 
    if(node) 
    { 
     print(node->leftChild); 
     std::cout << "[" << node->m_key << "]"; 
     print(node->rightChild); 
    } 
} 

void print1234(Node *node) 
{ 
    std::cout << std::endl; 
    print(node); 
} 

注:這個問題是不是BST,但三分球。如果您看到removeLeft(nodePtr)的兩個呼叫和main()功能中的removeLeft(&node)

  1. 這兩個不同?
  2. 爲什麼第二種方法無法達到預期效果?

回答

0

在第一種情況下,您傳遞樹中存在的指針的地址,因此您正在直接修改樹的內容。

在第二種情況下,您傳遞的是main()本地變量的地址。該樹沒有修改,並從地址刪除訪問堆棧內存,這就是爲什麼它崩潰

+0

你能再細說一下嗎? 'removeNode(nodePtr)'vs'removeNode(&node)'。我同意'nodePtr'和'&node'是不同的,但'* nodePtr'和'node'指向同一個位置。 – FiguringLife

+0

經過很多想法:)和筆/紙工作,我已經明白你想說什麼。 – FiguringLife

0

你超越它。所有你需要的是一個功能removeLeft(Node*)是脫鉤的左節點,並刪除它,遞歸:

void removeLeft(Node * p) 
{ 
    removeBoth(p->leftChild); // recurse, OK if null 

    delete p->leftChild; // OK if already null 
    p->leftChild = 0;  // necessary to make recursion terminate 
} 

void removeBoth(Node * p) 
{ 
    if (!p) return; 

    removeLeft(p); 
    removeRight(p); 
} 
+0

如果我刪除給定的二進制搜索樹中的節點(10),它應該替換爲節點(5)。你的代碼正在刪除整個樹。 – FiguringLife

+0

的確如此。你的問題並沒有說你想重組樹。如果'10'有兩個孩子呢? –

+0

對不起,如果我的問題不清楚。這不是關於BST,而是指針。如果在main()函數中看到兩個對'removeLeft()'的調用。其中一個工作正常,第二個沒有。 – FiguringLife

0

如果是壞的指針使用智能指針考慮。
使用智能指針時,使用shared_ptr<Node>而不是Node *make_shared(new Node);而不是new Node,並刪除所有刪除。現在你可以處理指針而不用關心刪除和內存損壞。

相關問題