2011-10-30 128 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,并删除所有删除。现在你可以处理指针而不用关心删除和内存损坏。

相关问题