C言語で木構造(ツリー)を削除する方法|後順走査を使った実装例
木構造を削除するには?
木(ツリー)を完全に削除するには、木を走査して各ノードにアクセスし、それらを一つずつ解放していく必要があります。すべてのノードを削除し終えると、木は空の状態になります。
このとき重要なのは、必ず子ノードを先に削除してから親ノードを削除するという点です。親ノードを先に解放してしまうと、子ノードへの参照が失われ、メモリリークなどの問題が発生します。そこで、木を「下から上へ」という順序で走査できる手法が必要になります。
後順走査(ポストオーダー走査)が最適な理由
この条件に最も適しているのが後順走査(postorder traversal)です。後順走査は、左右の子部分木をすべて処理した後に根ノードを訪問するため、葉に近いノードから順に安全かつ効率的に削除できます。その結果、余計な複雑さが生じず、プログラム全体を最適な状態に保つことができます。
後順走査におけるノードの訪問順序は次の通りです。
- ① 左の子ノード(左部分木)を走査する
- ② 右の子ノード(右部分木)を走査する
- ③ 最後に根ノードを処理する

例として、次のような二分木を考えてみましょう。この木を後順走査すると、ノードは以下の順序で訪問されます。
2 - 6 - 4 - 12 - 17 - 15 - 9
C言語による実装例
以下は、後順走査を利用して二分木を削除するC言語のサンプルプログラムです。
#include<stdio.h>
#include<stdlib.h>
struct node {
int data;
struct node* left;
struct node* right;
};
struct node* addnode(int data) {
struct node* node = (struct node*)
malloc(sizeof(struct node));
node->data = data;
node->left = NULL;
node->right = NULL;
return(node);
}
void nodedel(struct node* node) {
if (node == NULL) return;
nodedel(node->left);
nodedel(node->right);
printf("\n Node deleted, value is %d", node->data);
free(node);
}
int main() {
struct node *root = addnode(9);
root->left = addnode(4);
root->right = addnode(15);
root->left->left = addnode(2);
root->left->right = addnode(6);
root->right->left = addnode(12);
root->right->right = addnode(17);
nodedel(root);
root = NULL;
printf("\n Tree deleted ");
return 0;
}コードのポイント
- addnode関数: malloc()で新しいノードのメモリを確保し、データを格納したうえで、左右の子ポインタをNULLで初期化します。
- nodedel関数: 再帰的に呼び出され、まず左部分木、続いて右部分木を削除し、最後に自分自身をfree()で解放します。引数がNULLの場合は何もせずに即座にreturnします。
- main関数: サンプル用の二分木を構築し、nodedel(root)を呼び出して全ノードを解放した後、root = NULL を代入して木が空になったことを明示しています。
実行結果
Node deleted, value is 2 Node deleted, value is 6 Node deleted, value is 4 Node deleted, value is 12 Node deleted, value is 17 Node deleted, value is 15 Node deleted, value is 9 Tree deleted
このように、葉に近いノード(2や6など)から順に削除され、最後に根ノード(9)が解放されることがわかります。これはまさに後順走査の特徴であり、子ノードより先に親を消してしまう危険を回避できるため、木の削除には最適な手法といえます。
-
Pythonでn分木(n-aryツリー)のコピーを作成する方法を解説
n分木のコピーとは本記事では、ルートノード「root」が与えられたn分木(n-aryツリー)の完全なコピーを作成し、元の木とコピーした木の両方に対して先行順走査(preorder traversal)を実行する方法を解説します。作成したコピーは、別の新しいルートノードに格納する必要があります。使用するノードの構造は以下のとおりです。Node: value : <整数> children : <配列>入力例と出力例たとえば、次のようなn分木が与えられた場合を考えてみましょう。この場合、出力は次のようになります。[14, 27, 32, 42, 56, 65
-
Pythonで二分木の左端の最深ノードを求めるプログラム
二分木が与えられたとき、最も深い位置にあるノードの値を求めることを考えます。最深ノードが複数存在する場合は、その中で最も左側にあるノードの値を返します。 例えば、次のような二分木が入力された場合を考えてみましょう。 この場合、出力は 4 になります。最も深いレベルには 4 と 7 の2つのノードがありますが、4 の方が左側に位置しているためです。 解法のアプローチ この問題は、幅優先探索(BFS)を使って木をレベルごとに走査することで効率的に解けます。各レベルの最初のノード(=そのレベルの最も左のノード)の値を記録していき、すべてのレベルの走査が完了した時点で記録されている値が、最も深いレ