C++
 Computer >> コンピューター >  >> プログラミング >> C++

二分木がBST(二分探索木)であるかどうかを判定するC++プログラム

二分探索木(Binary Search Tree:BST)とは、次の3つの性質を満たす二分木データ構造のことです。

  • あるノードの左部分木には、そのノードのキーよりも小さいキーを持つノードのみが含まれる。
  • あるノードの右部分木には、そのノードのキーよりも大きいキーを持つノードのみが含まれる。
  • 左部分木と右部分木のそれぞれも、必ず二分探索木でなければならない。

アルゴリズム

BST判定は、各ノードに「取り得る値の範囲(最小値・最大値)」を渡しながら再帰的に木をたどることで実現できます。手順は以下の通りです。

Begin
    function BSTUtill()
        ノードがNULLと等しい場合
            1 を返す。
        ノードのデータが最小値未満または最大値より大きい場合
            0 を返す。
        左部分木と右部分木を再帰的にたどる。
End.

この方法では、単に親子関係だけを見るのではなく、ルートから各ノードまでの経路全体で妥当な値の範囲を更新していくため、正確にBSTかどうかを判定できます。

サンプルコード

以下は、C++で二分木がBSTであるかどうかを判定するプログラムの例です。INT_MIN と INT_MAX を初期範囲として利用しています。

#include <iostream>
#include <cstdlib>
#include <climits>
using namespace std;
struct n {
    int d;
    n* l;
    n* r;
};
int BSTUtil(n* node, int min, int max);
int isBST(n* node) {
    return(BSTUtil(node, INT_MIN, INT_MAX));
}
int BSTUtil(struct n* node, int min, int max) {
    if (node==NULL)
        return 1;
    if (node->d < min || node->d > max)
        return 0;
        return BSTUtil(node->l, min, node->d - 1) && BSTUtil(node->r, node->d + 1, max);
}
n* newN(int d) {
    n* nod = new n;
    nod->d = d;
    nod->l = NULL;
    nod->r = NULL;
    return nod;
}
int main() {
    n *root = newN(7);
    root->l = newN(6);
    root->r = newN(10);
    root->l->l = newN(2);
    root->l->r = newN(4);
    if (isBST(root))
        cout<<"The Given Binary Tree is a BST"<<endl;
    else
        cout<<"The Given Binary Tree is not a BST"<<endl;
        n *root1 = newN(10);
        root1->l = newN(6);
        root1->r = newN(11);
        root1->l->l = newN(2);
        root1->l->r = newN(7);
        if (isBST(root1))
            cout<<"The Given Binary Tree is a BST"<<endl;
        else
            cout<<"The Given Binary Tree is not a BST"<<endl;
        return 0;
}

出力結果

The Given Binary Tree is not a BST
The Given Binary Tree is a BST

解説

最初の例では、ルート7に対して左の子6、さらにその下に4というノードがあります。4は6より小さいため一見問題ないように見えますが、ルート7の左部分木内にあるべき値の範囲(7未満)の中でも、6の右側に配置できるのは6以上7未満の値のみです。この制約により、この木はBSTではないと判定されます。

一方、2番目の例では、すべてのノードが「左の子 < 親 < 右の子」という条件と、各部分木における値の範囲制約を満たしているため、BSTであると判定されます。

このアルゴリズムの計算量は、木の各ノードを一度ずつ訪問するため O(n)、再帰呼び出しによるスタックの深さは木の高さに依存し、最悪の場合(偏った木)で O(n) の空間計算量となります。

  1. C++で二分木が別の二分木の部分木(サブツリー)であるかを判定する方法

    はじめに二つの二分木が与えられたとき、小さい方の木がもう一方の二分木の部分木(サブツリー)として含まれているかどうかを判定する方法を解説します。例として、以下のような二つの木を考えてみましょう。この場合、2番目の木は1番目の木の部分木となっています。判定アルゴリズムの考え方この性質を確認するためには、大きい方の木を後順走査(post-order traversal)でたどり、各ノードを根とする部分木が2番目の木と完全に一致するかどうかを順番に調べます。一致する部分木が一つでも見つかれば、2番目の木は1番目の木の部分木であると判定できます。判定の流れは以下の通りです。1. 部分木側がNULLであ

  2. Pythonで二分木が二分探索木(BST)かどうかを判定する方法

    はじめに:BSTとは何か二分木が与えられたとき、それが二分探索木(Binary Search Tree:BST)であるかどうかを判定することは、データ構造の学習やコーディング面接でよく出題される定番の問題です。BSTには以下のような重要な性質があります。左部分木に含まれるすべてのノードの値は、現在のノードの値より小さい右部分木に含まれるすべてのノードの値は、現在のノードの値より大きいこれらの性質は、木の中のすべてのノードに対して再帰的に成り立つたとえば、次のような二分木を考えてみましょう。ルート:5左の子:1右の子:9(その左の子:7、さらに左の子:6・右の子:8/右の子:10)この場合、すべ