C++で二分木の後順(ポストオーダー)走査を非再帰的に実装する方法
二分木を後順(ポストオーダー)で走査する場合、まず左の部分木を訪問し、次に右の部分木、最後に根(ルート)を訪問します。この記事では、再帰を使わずに後順走査を実現するC++プログラムを紹介します。ここではスタックを利用して実装します。
アルゴリズム
後順走査の手順:
開始
関数 postorder_traversal(struct node *t, struct tree **top) を宣言
もし t == NULL ならば
「空の木です」と表示して return
「Postorder Data Using Stack :」と表示
ノードを挿入するために push(t, top) を呼び出す
tree 構造体へのポインタ store を宣言し、NULL で初期化
t != NULL の間、以下を繰り返す
store = *top
もし store->v == 0 ならば
もし t->r != NULL ならば
(store->v)++
push(t->r, top)
もし t->l != NULL ならば
(store->v)++
push(t->l, top)
もし store->v == 0 ならば(葉ノードの場合)
ノードの値を出力
t = NULL
pop(top)
それ以外ならば
ノードの値を出力
t = NULL
pop(top)
もし *top != NULL ならば
t = (*top)->link
終了
サンプルコード
以下が実際のC++コードです。スタックの各要素には、木のノードへのポインタ(link)と訪問状態を記録するカウンタ(v)を持たせています。
#include<iostream>
#include<stdlib.h>
using namespace std;
struct node {
int d;
struct node *l,*r;
};
struct tree {
int v;
struct node*link;
struct tree*n;
};
struct node*create_node(int);
struct node*create_node(int value) {
struct node*new_node=(struct node*)malloc(sizeof(struct node));
if(new_node!=NULL) {
new_node->d=value;
new_node->l=new_node->r=NULL;
return new_node;
} else {
printf("\n Memory overflow.");
return NULL;
}
}
void push(struct node*,struct tree*);
void push(struct node*node,struct tree**top) {
struct tree*new_node=(struct tree*)malloc(sizeof(struct tree));
if(new_node!=NULL) {
new_node->link=node;
new_node->n=*top;
new_node->v=0;
*top=new_node;
} else {
cout<<"\n Memory overflow.";
return ;
}
}
void pop(struct tree**);
void pop(struct tree**top) {
if(*top!=NULL) {
struct tree*remove=*top;
*top=(*top)->n;
remove->link=NULL;
remove->n=NULL;
remove=NULL;
}
}
void postorder_traversal(struct node*,struct tree**);
void postorder_traversal(struct node*t,struct tree**top) {
if(t==NULL) {
cout<<"\n Empty Tree";
return;
}
cout<<"\n Postorder Data Using Stack :";
push(t,top);
struct tree*store=NULL;
while(t!=NULL) {
store=*top;
if(store->v==0) {
if(t->r!=NULL) {
(store->v)++;
push(t->r,top);
}
if(t->l!=NULL) {
(store->v)++;
push(t->l,top);
}
if(store->v==0) {
cout<<t->d;
t=NULL;
pop(top);
}
}
else {
cout<<t->d;
t=NULL;
pop(top);
}
if(*top!=NULL)
t=(*top)->link;
}
}
int main(){
struct node*root=NULL;
struct tree*top=NULL;
root = create_node(20);
root->l = create_node(10);
root->r = create_node(30);
root->r->r = create_node(7);
root->l->l = create_node(25);
root->l->r = create_node(35);
root->l->r->r = create_node(40);
root->l->l->r = create_node(26);
postorder_traversal(root,&top);
return 0;
}
プログラムのポイント
- スタック構造体: 各要素は木のノードへのポインタ(
link)、訪問カウンタ(v)、次のスタック要素へのポインタ(n)を持ちます。 - push関数: 新しいノードをスタックの先頭に追加します。訪問カウンタ
vは 0 で初期化されます。 - pop関数: スタックの先頭要素を取り除き、メモリ上の参照を解放します。
- 後順走査の仕組み: ノードをスタックに積む際、先に右の子、次に左の子を積むため、取り出される順序は「左 → 右 → 根」となります。子を持たない葉ノードや、両方の子の処理が完了したノード(
v > 0)は、その時点で値が出力されます。
実行結果
Postorder Data Using Stack :26 25 40 35 10 7 30 20
-
【C++】二分木の中順走査(Inorder Traversal)を再帰的に実装する方法
木の走査(Tree Traversal)は、グラフ走査の一種であり、木に含まれるすべてのノードをそれぞれ一度だけ訪問(チェックまたは出力)する操作です。二分探索木における中順走査(Inorder Traversal、通りがけ順とも呼ばれます)では、「左の子 → 根 → 右の子」の順序で各ノードを訪問します。 二分木の中順走査の具体例を見てみましょう。次のような二分木が与えられたとします。 この二分木に対する中順走査の結果は次のとおりです。 中順走査の結果:1 4 5 6 8 それでは、中順走査を再帰的に実行するC++プログラムを見ていきましょう。 サンプルコード #include<i
-
二分木の先行順(プレオーダー)走査を再帰的に実行するC++プログラム
二分木の先行順走査とは木の走査(トラバーサル)はグラフ走査の一種であり、木に含まれるすべてのノードをそれぞれ一度だけ訪れて処理を行うことを指します。二分探索木における先行順走査(プレオーダー走査)では、「根 → 左部分木 → 右部分木」の順序で各ノードを訪問するのが特徴です。次のような二分木を例に考えてみましょう。この二分木に対する先行順走査の結果は 6 4 1 5 8 となります。ここからは、この先行順走査を再帰的に実行するC++プログラムを紹介します。C++による実装例#include<iostream> using namespace std; struct node {