2011-10-30 4 views
4

のアドレスを渡す:へのポインタを渡すことによって:ポインタは - PTRにptrを渡すか、私は2つの方法を使用してサンプルのバイナリ検索ツリーの左側の子(10)を削除しようとしていますPTR

  • メソッド1を現在のノードへのポインタ。
  • 方法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)removeLeft(&node)の2つの呼び出しがmain()機能にある場合は、

  1. これら2つの違いは何ですか?
  2. 2番目の方法では目的の結果が得られないのはなぜですか?

答えて

0

最初のケースでは、ツリー内に存在するポインタのアドレスを渡しているため、ツリーの内容を直接変更しています。

2番目のケースでは、代わりにmain()にローカルな変数のアドレスを渡しています。ツリーは変更されておらず、アドレスからの削除はスタックメモリにアクセスしているため、クラッシュします。

+0

少し詳しく説明できますか? 'removeNode(nodePtr)'と 'removeNode(&node)'です。私は 'nodePtr'と'&node'が違うが、 '* nodePtr'と' node'が同じ場所を指していることに同意します。 – FiguringLife

+0

多くの考え:)とペン/ペーパーワークの後、私はあなたが何を言おうとしているのか理解しています。 – FiguringLife

0

あなたはそれを考えすぎています。スマートポインタを使用することを検討してくださいあなたはポインタと悪い場合

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'に2人の子供がいたら? –

+0

申し訳ありませんが、私の質問が明確でない場合。それはBSTについてではなく、ポインタです。 main()関数で 'removeLeft()'を2回呼び出すと、そのうちの1つはうまく動作し、2つ目はうまく動作しません。 – FiguringLife

0

:必要なのは、再帰的に、左ノードをunhooksし、それを削除機能removeLeft(Node*)です。
new Nodeの代わりにNode *make_shared(new Node);の代わりにshared_ptr<Node>を使用し、すべての削除を削除します。今では、削除やメモリ破損を心配することなくポインタを扱うことができます。

関連する問題