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

C++で二分木の最短ルートから葉までのパスを出力するプログラム

このチュートリアルでは、二分木(バイナリツリー)において、根(ルート)から葉(リーフ)までの最短パスのうち最初に見つかったものを出力するC++プログラムについて解説します。

ここでは、すべてのノードが異なる値を持つ二分木が与えられ、その木の中で根ノードから葉ノードまでの最短経路を見つける必要があります。

この問題を解くには、キュー(queue)を使って二分木をレベル順走査(幅優先探索)し、最短パス上のノードを記録する方法が有効です。具体的には、最も浅いレベルにある最初の葉ノードに到達した時点で探索を終了し、記録しておいた親ノード情報をたどることで、最短パスを出力します。

アルゴリズムのポイント

幅優先探索(BFS)はレベルごとにノードを訪問するため、最初に見つかった葉ノードが必ず最短パスの終点となります。各ノードの親の値をハッシュマップ(unordered_map)に記録しておけば、葉ノードから根ノードへ遡ってパスを再構築できます。

サンプルコード

#include <bits/stdc++.h>
using namespace std;
struct Node{
    struct Node* left;
    struct Node* right;
    int data;
};
struct Node* create_node(int data){
    struct Node* temp = new Node;
    temp->data = data;
    temp->left = NULL;
    temp->right = NULL;
    return temp;
}
void print_spath(int Data, unordered_map<int, int> parent){
    if (parent[Data] == Data)
        return;
    print_spath(parent[Data], parent);
    cout << parent[Data] << " ";
}
void leftmost_path(struct Node* root){
    queue<struct Node*> q;
    q.push(root);
    int LeafData = -1;
    struct Node* temp = NULL;
    unordered_map<int, int> parent;
    parent[root->data] = root->data;
    while (!q.empty()){
        temp = q.front();
        q.pop();
        if (!temp->left && !temp->right){
            LeafData = temp->data;
            break;
        }
        else{
            if (temp->left){
                q.push(temp->left);
                parent[temp->left->data] = temp->data;
            }
            if (temp->right) {
                q.push(temp->right);
                parent[temp->right->data] = temp->data;
            }
        }
    }
    print_spath(LeafData, parent);
    cout << LeafData << " ";
}
int main(){
    struct Node* root = create_node(21);
    root->left = create_node(24);
    root->right = create_node(35);
    root->left->left = create_node(44);
    root->right->left = create_node(53);
    root->right->right = create_node(71);
    root->left->left->left = create_node(110);
    root->left->left->right = create_node(91);
    root->right->right->left = create_node(85);
    leftmost_path(root);
    return 0;
}

実行結果

21 35 53

コードの解説

このサンプルでは、根ノード21から始まる二分木を構築しています。幅優先探索により、最初に見つかった葉ノードは53です。53に到達するまでのパスは「21 → 35 → 53」となり、これが出力結果として表示されます。

処理の流れ:

1. 根ノードをキューに追加し、親マップに自分自身を登録します。
2. キューからノードを取り出し、左右の子が存在しない場合、そのノードを葉として記録し探索を終了します。
3. 子が存在する場合は、子ノードをキューに追加するとともに、親マップに「子の値 → 親の値」の対応を記録します。
4. 葉ノードが見つかったら、再帰関数 print_spath を使って親マップを遡り、根ノードから順にパスを出力します。

このアルゴリズムの計算量は、ノード数をNとすると時間計算量O(N)、空間計算量O(N)となります。全ノードの深さを比較する必要がないため、深さ優先探索よりも効率的に最短パスを求められる点が大きな利点です。

  1. C++で二分木の根から葉への最短経路を出力する方法|BFS(幅優先探索)による実装

    問題の概要二分木が与えられたとき、根(ルート)から葉(リーフ)に至る複数の経路の中から、最も短い経路を見つけ出して出力するプログラムを作成します。木は左から右へと走査するため、同じ深さの最短経路が複数存在する場合は、左側にある最初に走査された最短経路を出力します。この問題は、キュー(queue)を使ったレベル順走査(幅優先探索・BFS)で各レベルを順にたどることで解くことができます。BFSは浅い階層から順に探索を進めるため、最初に見つかった葉への経路が、すなわち根から葉への最短経路となります。上図の二分木では、根から葉への経路として以下のものが考えられます。10 -> 3(すべての経路の

  2. Pythonで二分木の葉ノードを新しいルートに変更するプログラムの実装方法

    二分木と、その葉(リーフ)に位置する1つのノードが与えられたとしましょう。ここでの課題は、その葉ノードを二分木の新しいルート(根)ノードへと変更することです。この操作は、次の2つのルールに従って行います。 左の子の移動: ノードに左の子が存在する場合、その子は右側へ移動します。 親の移動: ノードの親は、そのノードの左の子になります。この処理の過程で、元の親ノードからそのノードへのリンクは切断(null)されるため、親ノードは子を1つだけ持つ状態になります。 今回扱うツリーのノード構造は以下の通りです。 TreeNode: data: <整数> left: &