バイナリツリーが検索ツリーであるかどうかをテストし、完全なブランチをカウントするアルゴリズム


10

再帰的アルゴリズムを作成して、バイナリツリーがバイナリ検索ツリーであるかどうかを確認し、想定されるグローバルカウント変数を使用して、そこに完全なブランチがいくつあるか(左と右の両方の子ノードを持つ親ノード)を数える必要があります。これは私のデータ構造クラスの割り当てです。

これまでのところ

void BST(tree T) {
   if (T == null) return
   if ( T.left and T.right) {
      if (T.left.data < T.data or T.right.data > T.data) {
        count = count + 1
        BST(T.left)
        BST(T.right)
      }
   }
}

しかし、これを実際に理解することはできません。2番目のifステートメントがtrueでない場合、カウントはゼロになるため、このアルゴリズムは問題を解決しないことを知っています。

誰かがこれを手伝ってくれる?


<ノードで比較演算子はどのように定義されますか?
Joe

バイナリ検索ツリーでなくてもカウントを計算しますか?
Joe

1
あなたのアルゴリズムは、trueまたはなどの何かを返すことになっていますかfalse
Joe

2
おそらく、最初に2つの別々の関数を定義する必要があります。1つはBSTかどうかを確認するための関数で、もう1つは完全なブランチをカウントするための関数です。それはもっと扱いやすいはずです。
sepp2k 2012年

1
@OghmaOsiris質問は基本的に「これが私のコードです。どうやって機能させるのですか?」コードが疑似(ish)の種類ではなかった場合、それは間違いなくSOの質問になります。
sepp2k 2012年

回答:


10

他の人がすでにコメントで示しているように、ここには実際には2つの無関係な関数があります。ツリーが検索ツリーであるかどうかのテストと完全なブランチのカウントです。割り当てが特にそれを必要としない限り、私は2つの別個の関数を作成します。

最初に完全なブランチを数えるabountを見てみましょう。つまり、左の子と右の子の両方を持つノードをカウントします。次にcount = count + 1T.leftとの両方T.rightがnullでない場合(T.left.dataおよびnot T.right.data:データはこのタスクには関係ありません)、カウンター()をインクリメントする必要があります。

if (T.left and T.right) {
    count = count + 1

さらに、右側のサブツリーが空の場合でも左側のサブツリーを探索する必要があり、左側のサブツリーが空の場合でも右側のサブツリーを探索する必要があります。したがって、再帰呼び出しを行う場所に注意してください。

ツリーが検索ツリーであるかどうかをテストするには、データ値を検査する必要があります。あなたはすでに正しい比較に近いものを持っています。不正解です。さまざまな形状のツリーの例をいくつか(あまり大きくない、2〜5ノード)作成し、それらに対してアルゴリズムを実行して何が起こるかを確認します。

妥当性チェックの結果を置く場所を見つける必要があります。繰り返しますが、再帰呼び出しを行う場所に注意してください(この部分だけを行う場合、いくつかの解決策がありますが、この段階では1つしか表示されなくてもかまいません)。

最後に、両方の関数を別々に作成し、いくつかの例でそれらをテストした後、慎重に組み合わせます(割り当てで必要な場合)。


おかげで、私は質問を再読しました、そしてそれは別々の方法であるはずでした。
OghmaOsiris 2012年

7

このような場合、多くの場合、後向きに考える方が簡単なので、まず必要なものを検討します。あなたの説明から、それらをリストしましょう:

  • 再帰
  • 有効
  • 完全なノードの数

OK、これはかなり短いリストですが、これは扱いやすいはずです。空のメソッドから始めましょう。何が発生するのかについての説明を追加します。

valid_bst () {
}

今妥当性。どのように有効性をチェックしますか?チャットで、ツリーは有効であると言いました。「...左のすべての子が親よりも小さく、右の子が親よりも大きい場合」あなたも平等を認めるつもりだったと思います。それはでしょうt.left.value <= t.value <= t.right.value

valid_bst () {
    This node is valid if t.left.value <= t.value <= t.right.value
}

しかし、子どもの一人が行方不明になった場合はどうなりますか?あなたが言ったことから、一方が欠落している(または両方が欠落している)場合でも、ノードはまだ有効であることがわかります。これを追加して、少し再構成します。

valid_bst () {
    This node is valid to the left if 
        there is no left child or 
        it is no greater than the current node.
    This node is valid to the right if 
        there is no right child or 
        it is no less than the current node.
    This node is valid overall if it is valid to the left and right.
}

これで、このノードが有効かどうかがわかりました。ツリー全体が有効かどうかを確認するにはどうすればよいですか?それは配列にないので、線形にループすることはおそらくできません。あなたの割り当ては答えを与えます:再帰。しかし、再帰を使用してどのように答えを蓄積するのでしょうか?このノードが有効かどうか、および左右のノードが有効かどうかを尋ねる呼び出しの結果の3つの情報にアクセスできます。明らかに、ツリーはこれら3つすべてが真である場合にのみ有効です。

valid_bst () {
    This node is valid to the left if 
        there is no left child or 
        it is no greater than the current node.
    This node is valid to the right if 
        there is no right child or 
        it is no less than the current node.
    This node is valid overall if it is valid to the left and right.
    Is the left child valid?
    Is the right child valid?
    This tree is only valid if this node and both its children are.
}

あなたが注意を払っているなら、それは私たちの関数が返す必要があるものを教えてくれます。

では、どのようにカウントを統合しますか?あなたは何が重要であるか(「左と右の両方の子ノードを持つ親ノード」)を言います、そしてそれは実際のコードに変換することは難しくありません。その条件が満たされているかどうかを確認し、カウンターを適切に増分します。これが本当であるたびに到達するどこかにある必要があることを覚えておいてください。

そしてもちろん、再帰の停止条件やnullのチェックなど、いくつかの詳細は省略しました。


6

上記の3つのコメントは、コードの問題に対する3つのヒントです。

  1. 比較演算子がノードのデータ型をどのように処理するかを明確に定義していない限り、2つのノードを直接比較しても期待どおりの結果が得られない可能性があります。あなたがおそらく意味したことは、ノードに保存されたフィールドを比較することでした、例えばnode1.value < node2.value
  2. 現時点でifは、3番目がtrueの場合にのみカウントに追加されますが、それが意図したことですか?ちなみに、ifステートメントが意図したとおりに機能することを再確認してください。
  3. ツリーが有効なBSTの場合はtrueを返し、それ以外の場合はfalseを返すことを想定しています。つまり、基本ケースでは常にtrueまたはfalseを返す必要があり、再帰呼び出しの結果も返す必要があります。

ポイント1について:これは疑似コードですよね?したがって、意図が読者に伝えられている限り、そのようなものを定義する理由はありません。
sepp2k 2012年

@ sepp2kは本当です、そして私のコメントはおそらく疑似コードには少しあまりにもきついです。私のポイントは、2つのノードを比較することの意味を理解する必要があることだと思います。あなたのポイントは、私たちはすでにそれを暗黙のうちに理解しているべきだということです。
Joe

そうです。
sepp2k 2012年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.