なぜC ++のコードでは、私のBST内のすべてのノードを削除するには失敗していますか?
-
19-09-2019 - |
質問
これは、ルートノードを含む、BSTを横断し、すべてのノードを削除することになっています。しかし、最後に、私はメッセージ「ルートはまだ左のノードを持っている。」取得しますなぜ、すべてのノードが削除されていない?
void deleteTree()
{
deleteNode(root);
if(root->right)
cout << "root still has a right node" << endl;
if(root->left)
cout << "root still has a left node" << endl;
root = 0;
}
void deleteNode(node *p)
{
if(p->left)
{
deleteNode(p->left);
p->left = 0;
}
if(p->right)
{
deleteNode(p->right);
p->right = 0;
}
cout << "Deleting node containing " << p->data << endl;
delete p;
}
解決
あなたはp
、割り当てられたメモリへのroot
もはやポイントで、その内容にアクセスしようとし、その後エンド(deleteTree()
)でroot
を削除しています。結果は未定義されようとしている。
他のヒント
あなたはroot
を削除しています。そして、あなたのコードは、それがあった場所のメモリにアクセスしようとしてます。
あなたが未定義の行動の地にもしている。
あなたはroot
でそれを削除した後間接参照deleteNode
べきではありません。 root->left
が非nullである理由を検査するデバッガを使用します。
あなたはすでに新しい割り当てられたブロックで使用できるようになり、ルートを削除した後にあなたがroot->left
を見ている。
私は単にツリー自体を変更するだろう、それに対処しやすくなります:
struct Node
{
Node(data_type data): mLeft(), mRight(), mData(data) {}
Node(const Node& rhs): mLeft(), mRight(), mData(rhs.mData)
{
if (rhs.mLeft.get()) mLeft.reset(new Node(*rhs.mLeft));
if (rhs.right.get()) mRight.reset(new Node(*rhs.mRight));
}
Node& operator=(Node rhs)
{
this->swap(rhs);
return *this;
}
~Node() { }
void swap(Node& rhs)
{
using std::swap;
swap(mLeft, rhs.mLeft);
swap(mRight, rhs.mRight);
swap(mData, rhs.mData);
}
Node* left() const { return mLeft.get(); }
void left(std::auto_ptr<Node> node) { mLeft= node; }
Node* right() const { return mRight.get(); }
void right(std::auto_ptr<Node> node) { mRight = node; }
data_type& data() { return mData; }
const data_type& data() const { return mData; }
private:
std::auto_ptr<Node> mLeft;
std::auto_ptr<Node> mRight;
data_type mData;
};
オブジェクト指向であることによって、各ノードは、今、それが扱うメモリの責任です。また、インタフェースのstd::auto_ptr
を使用すると、それが明確にそれが所有権を取得することになります。
それは、ディープコピーのためboost::shared_ptr
または同等を必要とする他のアプローチを調整されていますので注意してください。そして、そうstd::auto_ptr
は、あなたが自分でコピーを扱う残し、そこにはマジックます。
このデザインは、誰もがリソースを操作することができることで、プレーンC-struct
を使用するよりもはるかクリーナーです。あなたはまだ、アクセサを経由して、基礎となるデータへのフルアクセスを持っている...しかし、彼らは未定義の動作を起動しないように注意してください...
もちろん、あなたはまだそれをダウンクラッシュすることがあります:
Node& node = ...
delete node.left(); // haha
しかし、C ++が意図しない問題に対して保護することができるならば、それは邪悪なコードへのオープンドアを残しています。