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

C++でスタックを1つだけ使って二分木の葉ノードを左から右へ出力する方法

本記事では、二分木の葉ノードを左から右の順で出力するプログラムを紹介します。ここでのポイントは、スタックを1つだけしか使えないという制約です。

push() 操作で二分木のノードをスタックに挿入し、pop() 操作で葉ノードを取り出して表示します。

葉ノードとは?

葉ノード(リーフノード)とは、左ポインタと右ポインタがどちらも NULL になっている、木の末端にあるノードのことです。つまり、そのノードは親ノードではないことを意味します。

実行例

入力 : 12 21 32 41 59 33 70
出力 : 41 59 33 70

上記の例では、値が 41、59、33、70 のノードが葉ノードに該当します。

スタックは LIFO(Last In First Out:後入れ先出し)方式のデータ構造で、トップポインタは最後に挿入された要素を指します。この性質により、最後に挿入された葉ノードが他のノードよりも先にスタックから取り出されることになります。

以下のコードは、STL を使用した C++ 実装の例です。

アルゴリズム

START
    Step 1 -> ノード構造体を作成
        int 型の data を宣言
        ノード型のポインタ *left, *right を宣言
    Step 2 -> 値 val を引数に持つノード挿入用関数を作成
        malloc でノード変数を確保
        node->data = val を設定
        node->left = node->right = NULL を設定
        node を返す
    Step 3 -> 関数 void leaf(Node *ptr) を宣言
        vector stackstck を作成
        無限ループ While 1
        IF ptr が有効なら
            stck.push(ptr)
            ptr = ptr->left
        Else
            IF (stck.empty())
                Break
            Else
                IF (stck.top()->right == NULL)
                    ptr = stck.top()
                    stck.pop()
                    IF ptr->left == NULL
                        ptr->data を表示
                End
                While ptr == stck.top()->right
                    ptr = stck.top()
                    stck.pop()
                    IF stck.empty()
                        Break
                    End
                IF !stck.empty()
                    ptr = stck.top()->right
                Else
                    ptr = NULL
                EndIF
            End
        End
    Step 4 -> main() 内で
        Node* root = New(12) のように値を渡して New を呼び出す
        leaf(root) を呼び出す
STOP

C++ 実装コード

#include <bits/stdc++.h>
using namespace std;
// ノードの構造体定義
struct Node {
    Node* left;
    Node* right;
    int data;
};
// 新しいノードを作成する関数
Node* New(int val) {
    Node* node = new Node();
    node->left = node->right = NULL;
    node->data = val;
    return node;
}
// スタックを使って葉ノードを出力する関数
void leaf(Node* ptr) {
    // ノードを格納するスタック
    stack<Node*> stck;
    while (1) {
        if (ptr) {
            stck.push(ptr);
            ptr = ptr->left;
        } else {
            if (stck.empty())
                break;
            else {
                if (stck.top()->right == NULL) {
                    ptr = stck.top();
                    stck.pop();
                    // 葉ノードを表示
                    if (ptr->left == NULL)
                        printf("%d ", ptr->data);
                }
                while (ptr == stck.top()->right) {
                    ptr = stck.top();
                    stck.pop();
                    if (stck.empty())
                        break;
                }
                if (!stck.empty())
                    ptr = stck.top()->right;
                else
                    ptr = NULL;
            }
        }
    }
}
int main() {
    printf("leaf nodes at end level are : ");
    Node* root = New(12);
    root->left = New(21);
    root->right = New(32);
    root->left->left = New(41);
    root->left->right = New(59);
    root->right->left = New(33);
    root->right->right = New(70);
    leaf(root);
    return 0;
}

処理の流れの解説

このアルゴリズムは、反復的な中順走査(インオーダー走査)の考え方を応用しています。

  • まず、現在のノードが存在する限り、スタックに push しながら左の子へ移動していきます。
  • 左端まで到達したら、スタックのトップにあるノードを調べます。そのノードの右の子が NULL であり、かつ左の子も NULL であれば、それは葉ノードなので値を出力します。
  • 右側の部分木の走査が完了したノードは、スタックから pop しながら親へ戻ります。
  • スタックが空になるまでこの処理を繰り返すことで、すべての葉ノードが左から右の順に出力されます。

出力結果

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

leaf nodes at end level are : 41 59 33 70

このように、再帰を使わずスタックを1つだけ用いても、二分木の葉ノードを正しく左から右の順序で出力できることが確認できます。

  1. C++で二分木の奇数レベルにあるノードを出力するプログラム

    このチュートリアルでは、与えられた二分木(バイナリツリー)の中から、奇数レベルに存在するノードを出力するC++プログラムについて解説します。 本プログラムでは、ルートノードのレベルを「1」と定義し、それ以降のレベルは交互にカウントしていきます。つまり、レベル1・3・5…といった奇数番目の階層に属するノードが出力の対象となります。 例として、以下のような二分木が与えられた場合を考えてみましょう。 この二分木の場合、奇数レベルに存在するノードは 1, 4, 5, 6 となります。 アルゴリズムの考え方 実装には再帰呼び出しを利用します。ルートから探索を開始し、現在のレベルが奇数かどうかをブール

  2. C++で二分木のノードを葉ノードになった順に出力する方法

    問題概要 二分木が与えられたとき、まずその葉ノード(リーフノード)を出力します。次に、出力した葉ノードを木から取り除き、新たに葉ノードとなったノードを出力します。この操作を、木の中にノードが一つも残らなくなるまで繰り返します。 例 以下のような二分木を例に考えてみましょう。 まず最下層の葉ノード「6 7 9 13 14」を出力して取り除き、次に新たな葉ノードとなった「3 4」を出力、続いて「2」、最後に根ノード「1」を出力します。したがって、この問題の出力は以下のようになります。 6 7 9 13 14 3 4 2 1 アプローチ この問題では、DFS(深さ優先探索)を用いたアプロ