2011-08-11 10 views
-4

私はC++初心者ですが、このプログラムの破壊ワークフローをあまり理解していないので、両方のクラスのデストラクタを記述します。しかし、エラーが発生しました...ノードのデストラクタを定義するのは気になりますか?なぜこのプログラムにはエラーがありますか?

#include<iostream> 
using namespace std; 

// in this case, the BST doesn't have duplicates 
class Node 
{ 
public: 
    Node* parent; 
    Node* left; 
    Node* right; 
    Node() : key(-1), parent(NULL), left(NULL), right(NULL) {} 
    virtual ~Node() {cout << "destructor of Node" << endl; delete parent; delete left; delete right;} 
    void setKey(int k) 
    { 
     key = k; 
    } 
    int getKey() {return key;} 
private: 
    int key; 
}; 


class BST 
{ 
public: 
    Node* root; 
    BST() {root = NULL;} 
    virtual ~BST() {freeNode(root);} 
    void addNode(int key) 
{ 
    if (!root) 
    { 
     root = new Node(); 
     root->setKey(key); 
    } 
    else 
     addNode(key, root); 
} 
Node* findNode(int key) 
{ 
    Node* p = root; 
    while (p) 
    { 
     if (p->getKey() == key) 
      return p; 
     else if (p->getKey()<=key) 
     { 
      p = p->right; 
     } 
     else 
      p = p->left; 
    } 
    return p; 
} 
void walk(Node* node) 
{ 
    if (node) 
    { 
     walk(node->left); 
     cout << node->getKey() << " " << flush; 
     walk(node->right); 
    } 
} 
void deleteNode(int key) 
{ 
    Node* p = findNode(key); 
    if (p) 
    { 
     //case 1: p has no children 
     if (!p->right && !p->left) 
      p->parent->right == p ? p->parent->right = NULL : p->parent->left = NULL; 
     //case 2: p has one child 
     else if (!p->left && p->right) 
     { 
      p->parent->right = p->right; 
      freeNode(p); 
     } 
     else if (!p->right && p->left) 
     { 
      p->parent->left = p->left; 
      freeNode(p); 
     } 
     //case 3: p has two children 
     else 
     { 
      Node *suc = successor(key); 
      exchange(suc,p); 
      deleteNode(suc->getKey()); 
     } 

    } 
} 
Node* min(Node* node) 
{ 
    //empty tree 
    if (!node) 
     return NULL; 
    else if (!node->left) 
     return node; 
    else 
     return min(node->left); 
} 
Node* max(Node* node) 
{ 
    //empty tree 
    if(!node) 
     return NULL; 
    else if (!node->right) 
     return node; 
    else 
     return max(node->right); 
} 
Node* successor(int key) 
{ 
    Node *temp = NULL; 
    Node *p = findNode(key); 
    //case 1: has a right child 
    if (p->right) 
     return min(p->right); 
    //case 2: does not have a right child 
    else 
    { 
     temp = p->parent; 
     while(temp->left != p) 
     { 
      p = temp; 
      temp = temp->parent; 
     } 
     return temp; 
    } 
} 

Node* predecessor(int key) 
{ 
    Node *temp = NULL; 
    Node *p = findNode(key); 
    //case1: has a left child 
    if (p->left) 
     return max(p->left); 
    //case2: does not have a left child 
    else 
    { 
     temp = p->parent; 
     while(temp->right != p) 
     { 
      p = temp; 
      temp = temp->parent; 
     } 
     return temp; 
    } 
} 

private: 
void addNode(int key, Node* node) 
{ 
    if (node->getKey() <= key) 
    { 
     if (node->right) 
      addNode(key, node->right); 
     else 
     { 
      Node* leaf = new Node(); 
      leaf->setKey(key); 
      leaf->parent = node; 
      node->right = leaf; 
     } 
    } 
    else 
    { 
     if (node->left) 
      addNode(key, node->left); 
     else 
     { 
      Node* leaf = new Node(); 
      leaf->setKey(key); 
      leaf->parent = node; 
      node->left = leaf; 
     } 
    } 

} 
void freeNode(Node* leaf) 
{ 
    delete leaf; 
} 
void exchange(Node *a, Node *b) 
{ 
    int temp = a->getKey(); 
    a->setKey(b->getKey()); 
    b->setKey(temp); 
} 
}; 

int main(int argc, char** args) 
{ 
int *p = NULL; 
delete p; 

BST tree; 
tree.addNode(8); 
tree.addNode(4); 
tree.addNode(12); 
tree.addNode(2); 
tree.addNode(6); 
tree.addNode(10); 
tree.addNode(14); 
tree.addNode(1); 
tree.addNode(3); 
tree.addNode(5); 
tree.addNode(7); 
tree.addNode(9); 
tree.addNode(11); 
tree.addNode(13); 
tree.addNode(15); 
tree.walk(tree.root); 
return 0; 
} 
+0

デバッガを使用します。 –

+1

少なくともコードは清潔でコメントになっています。 –

+0

なぜ非常に多くの投票が行われますか?誰もがいつか初心者でした... –

答えて

2
delete parent; delete left; delete right; 

オブジェクトを削除すると、そのデストラクタが呼び出されます。ここでは、左と右のノードの両方が、親ノードを削除するときに、現在のノードを削除します。これを修正するには、親の削除を削除するだけです。

+0

ありがとう@Don、私は2つのフォローアップの質問があります:1.私のコードでは、プログラムはノードのデストラクタを出力に従って何度も呼び出します。どうして? (私が考えることができるのは、main()が終了すると、BSTのデストラクタを呼び出すオブジェクトツリーが破棄されますが、Nodeは動的に割り当てられます。なぜNodeクラスのデストラクタが呼び出されるのですか?この場合のNodeとBSTのデストラクタはメモリを解放するのですか? –

+0

動的に割り当てられたオブジェクトも破壊されます。親を削除する必要はありません。 –

+0

@Donに感謝しますが、動的に割り当てられたオブジェクトが破棄されるのはいつですか?私は明示的に "削除"がそれらを破壊することを知っているだけです。 –

関連する問題