質問
私はAVL木を実装するために私を頼む割り当てに取り組んでいます。私は回転方法が正しい持っているかなり確信しているが、私はそれらを使用する際に考え出すトラブルを抱えています。
たとえば、本の中の説明は、私はノード/要素を挿入するためにダウンした同じ道を登る必要があることを述べています。しかし、私は、任意の親ポインタを持っていないことができます。
最新のコード:
public BinaryNode<T> insert(BinaryNode<T> node) {
if (this.getElement().compareTo(node.getElement()) > 0) {
if (this.getLeftChild() != null) {
BinaryNode<T> b = this.getLeftChild().insert(node);
if(!this.isBalanced()) {
this.balance();
}
return b;
} else {
this.setLeftChild(node);
}
} else if (this.getElement().compareTo(node.getElement()) < 0) {
if (this.getRightChild() != null) {
return this.getRightChild().insert(node);
} else {
this.setRightChild(node);
}
}
return this;
}
私はここでやりたいことは戻って木登りですが、それはノードを挿入した後では、唯一のバランスを確認することができます。 else節にあるため、これます。
私はまた、RサミュエルKlatchkoが提案バランスのコードを入れてみましたが、各挿入のバランスをチェックします。たとえば、次のいずれかが連続的に7,9、5,3、及び1を挿入した場合、私は1を挿入しようとNULLポインタ例外を取得
。編集:上記の理由の一つは、私は高さをやっていた方法とは何かを持っていることがあります。私は、高さと高さを毎回計算する場合は、単一の右回転で正常に動作します()それはAVL木の(ログ(N))時間Oを破ります。
これを実現する方法上の任意の考え?
解決
あなたのコードは、あなたがダウンした同じ道を登っています。このコードを考えてみます:
if (this.getLeftChild() != null) {
return this.getLeftChild().insert(node);
}
と少しそれを変更します:
if (this.getLeftChild() != null) {
boolean b = this.getLeftChild().insert(node);
// do something here
return b;
}
再帰呼び出しからコードが戻るように、各リターンが戻って親にあなたをもたらします。すぐに再帰呼び出しの値を返さないことで、あなたのリバランスを行う機会を持っています。
最新のコードのための更新の
あなたが右に挿入したとき、リバランスすることを忘れないでください。
他のヒント
あなたはinsert
メソッドに親のポインタを渡してみてください、またはあなたが反復法にinsert
を変換して、ツリーの下のパスを記録した上で明示的なスタックを保つことができます。
ところで、使用する回転を選択するためには、あなただけのノードがアンバランスであることを知ることができる、あなたはより深いサブツリーが右または左にあるかどうかを知っている必要があります。これは、単純なisBalanced
方法は非常に十分ではないことを意味します。また、非効率的だし、AVL木ののO(ログn)を爆破するの複雑さ、あなたがするたびに高さを計算するためます。