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

C++で二分探索木の中順後続ノード(Inorder Successor)を求めるプログラム


二分探索木(BST)とあるノードの値が与えられたとき、そのノードの「中順後続ノード(Inorder Successor)」を求めることを考えます。中順後続ノードとは、ノード p の値よりも大きいキーの中で、最小の値を持つノードのことです。

例として、次のような二分探索木を考えてみましょう。

C++で二分探索木の中順後続ノード(Inorder Successor)を求めるプログラム

このとき p = 1 とすると、1 より大きい値の中で最小のものは 2 なので、出力は 2 になります。

解法のアプローチ

この問題は、二分探索木の性質(左の子 < 親 < 右の子)を利用すると、再帰的に効率よく解けます。手順は以下の通りです。

  • 再帰メソッド inorderSuccessor(root, p) を定義します。
  • root が NULL の場合:
    • NULL を返します。
  • root の値が p の値以下の場合:
    • 答えは必ず右部分木に存在するため、inorderSuccessor(root の右の子, p) の結果を返します。
  • それ以外の場合(root の値が p の値より大きい場合):
    • root 自身が後続候補となり得るため、まず option = inorderSuccessor(root の左の子, p) を求めます。
    • option が NULL なら root を、NULL でなければ option を返します。

実装例(C++)

以下のコードで実際の動作を確認してみましょう。

#include <bits/stdc++.h>
using namespace std;
class TreeNode{
    public:
    int val;
    TreeNode *left, *right;
    TreeNode(int data){
        val = data;
        left = NULL;
        right = NULL;
    }
};
class Solution {
    public:
    TreeNode* inorderSuccessor(TreeNode* root, TreeNode* p) {
        if(!root) return NULL;
        if(root->val <= p->val){
            return inorderSuccessor(root->right, p);
        }else{
            TreeNode* option = inorderSuccessor(root->left, p);
            return !option ? root : option;
        }
    }
};
main(){
    TreeNode *root = new TreeNode(2);
    root->left = new TreeNode(1);
    root->right = new TreeNode(3);
    TreeNode *p = root->left;
    Solution ob;
    cout << (ob.inorderSuccessor(root, p))->val;
}

入力

TreeNode *root = new TreeNode(2);
root->left = new TreeNode(1);
root->right = new TreeNode(3);
1

出力

2

計算量について

このアルゴリズムの時間計算量は O(h) です(h は木の高さ)。各再帰呼び出しで木を1段階ずつ降りていくだけのため、バランスの取れた二分探索木では O(log n)、木が片側に偏っている最悪ケースでは O(n) となります。空間計算量も再帰の深さに依存するため、同様に O(h) です。


  1. C++プログラムにおける二分探索(バイナリサーチ)の基本と実装

    二分探索(バイナリサーチ)とは二分探索は「半区間探索」「対数探索」「バイナリチョップ」とも呼ばれる検索アルゴリズムで、ソート済みの配列の中から目的の値が存在する位置を効率的に見つけ出します。基本的な仕組みは非常にシンプルです。まず、探したい値(ターゲット値)を配列の中央の要素と比較します。一致しなかった場合は、ターゲット値が存在し得ない半分を丸ごと排除し、残りの半分に対して同様の比較を繰り返します。この「中央との比較」と「範囲の絞り込み」を続け、ターゲット値が見つかるか、検索範囲が空になる(=配列にその値が存在しない)かのどちらかで処理が終了します。アイデア自体は簡単ですが、正しく実装するには

  2. C++で二分探索木(AVL木)の左回転を実装するプログラム

    二分探索木とは二分探索木(Binary Search Tree)とは、すべてのノードが次の性質を満たすソート済みの二分木です。ノードの右部分木には、親ノードのキーより大きいキーがすべて格納されるノードの左部分木には、親ノードのキーより小さいキーがすべて格納される各ノードが持てる子ノードは最大2つまで木の回転(Tree Rotation)とは木の回転とは、二分木の要素の順序(ソート順)を崩すことなく木の構造を変更する操作です。回転では、あるノードを1つ上へ、別のノードを1つ下へ移動させます。回転は木の形状を変えるために使われ、小さな部分木を下へ、大きな部分木を上へ移動することで木の高さを抑えられ