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

C言語で二分木の右側ビュー(Right View)を出力する方法


この記事では、与えられた二分木の「右側ビュー(Right View)」――すなわち、木を右側から見たときに見えるノード――を出力するC言語プログラムについて解説します。まずデータを挿入して二分木を構築し、その後、完成した木の右側ビューを画面に表示します。

C言語で二分木の右側ビュー(Right View)を出力する方法

上の図は、ノード10・42・93・14・35・96・57・88から構成される二分木を表しています。この中で木の右側に位置するノードが選ばれ、画面に表示されます。たとえば、10・93・57・88がこの二分木における最も右側のノードに該当します。

実行例

入力:10 42 93 14 35 96 57 88
出力:10 93 57 88

二分木の各ノードには「left」と「right」という2つのポインタが用意されています。本問題では右側のノードのみを走査すればよいため、ノードの左の子を意識する必要はありません。

右側ビューには、各レベル(階層)の末尾にあたるノード、つまりそのレベルで最も右にあるノードがすべて含まれます。そこで、「右部分木を先に、左部分木を後に」走査する再帰的なアプローチを採用することで、目的のノードを簡単に抽出できます。プログラムは、それまでに到達した最大レベルより深いレベルのノードを見つけるたびに、そのノードを出力します。右部分木から先に探索するため、その時点で訪問したノードは必ずそのレベルの最も右側のノードになるからです。

以下のコードは、このアルゴリズムをC言語で実装したものです。

アルゴリズム

START
    Step 1 -> 構造体型のノード変数を作成
        int data を宣言
        ノード型ポインタ *left, *right を宣言
    Step 2 -> 引数 item を持つノード挿入用関数を作成
        malloc を使ってノード型の一時変数 temp を確保
        temp->data = item を設定
        temp->left = temp->right = NULL を設定
        temp を返す
    Step 3 -> 関数 void right_view(struct node *root, int level, int *end_level) を定義
        IF root == NULL ならば
            Return
        IF *end_level < level ならば
            root->data を出力
            *end_level = level を設定
            right_view(root->right, level+1, end_level) を呼び出す
            right_view(root->left, level+1, end_level) を呼び出す
    Step 4 -> 関数 void right(struct node *root) を定義
        int level = 0 を設定
        right_view(root, 1, &level) を呼び出す
    Step 5 -> main() 内で
        struct node *root = New(10) として木のノード値を設定
        right(root) を呼び出す
STOP

C言語での実装例

#include<stdio.h>
#include<stdlib.h>

/* 二分木のノードを表す構造体 */
struct node {
    int data;
    struct node *left, *right;
};

/* 新しいノードを生成する関数 */
struct node *New(int item) {
    struct node *temp = (struct node *)malloc(sizeof(struct node));
    temp->data = item;
    temp->left = temp->right = NULL;
    return temp;
}

/* 右側ビューを再帰的に出力する関数 */
void right_view(struct node *root, int level, int *end_level) {
    if (root == NULL) return;
    if (*end_level < level) {
        printf("%d\t", root->data);
        *end_level = level;
    }
    right_view(root->right, level+1, end_level);
    right_view(root->left, level+1, end_level);
}

/* 右側ビューの出力を開始する関数 */
void right(struct node *root) {
    int level = 0;
    right_view(root, 1, &level);
}

int main() {
    printf("right view of a binary tree is : ");
    struct node *root = New(10);
    root->left = New(42);
    root->right = New(93);
    root->left->left = New(14);
    root->left->right = New(35);
    root->right->left = New(96);
    root->right->right = New(57);
    root->right->left->right = New(88);
    right(root);
    return 0;
}

出力結果

上記のプログラムを実行すると、以下の出力が得られます。

right view of a binary tree is : 10 93 57 88

計算量について

このアルゴリズムは各ノードを一度だけ訪問するため、時間計算量はノード数を n として O(n) となります。また、再帰呼び出しに必要なスタック領域は木の高さ h に比例し、空間計算量は O(h) です。平衡な二分木であれば O(log n)、最悪ケース(線形に偏った木)では O(n) になります。

  1. Pythonで二分木の指定ノードの右隣ノードを見つけるプログラム

    二分木が与えられ、さらに特定のノード「u」へのポインタも渡されたとします。このとき、u のすぐ右側に位置するノード(必ず同じ階層に存在する)を見つける必要があります。対象のノードは葉ノードの場合もあれば、内部ノードの場合もあります。 例として、次のような二分木が入力されたとしましょう。 ここで u = 6 とすると、出力は 8 になります。ノード 6 の右隣にはノード 8 が存在するため、値 8 が返されるというわけです。 解決のためのアプローチ この問題は、両端キュー(deque)を使った幅優先探索(BFS)、いわゆるレベル順走査によって解くことができます。手順は以下の通りです。 ルー

  2. Pythonで二分木の2番目に深い葉ノードの深さを求めるプログラム

    問題の概要二分木が与えられたとき、2番目に深い葉ノードの深さを求めることを考えます。最も深い葉が複数存在する場合は、その次に高い位置にある葉ノードが「2番目に深い葉」とみなされます。なお、根(ルート)の深さは0であるとします。入力例と出力例えば、次のような二分木が与えられた場合を考えてみましょう。この木では、最も深い葉はノード7とノード8(深さ3)であり、その次に深い葉はノード3(深さ1)です。したがって、出力は 1 となります。解法のアプローチこの問題は、木をレベル(深さ)ごとに順番に辿っていく幅優先探索(BFS)の考え方を使うと、シンプルに解くことができます。各レベルで最初に見つかった葉ノ