📗 二分木.
📌二分木の特徴.
- 1つの根を持ち全ての節点についてその子の数が2以下である木が根付き二分木.
- 各節点を1度ずつ訪問するので計算量O(n)となる.
📌二分木の構造.
1️⃣節点の数に変化がない二分木では、節点が子を持たない場合にはNILを設定し、番兵の役割を担う.
高さを求めるアルゴリズムは左の子の高さ+1と右の子の高さ+1の大きい方を節点とする.
int setHeight(int u) {
int h1 = 0, h2 = 0;
// 左の子の高さ+1
if (T[u].left != NIL) {
h1 = setHeight(T[u].left) + 1;
}
// 右の子の高さ+1
if (T[u].right != NIL) {
h2 = setHeight(T[u].right) + 1;
}
return H[u] = (h1 > h2 ? h1 : h2);
}
根付き二分木Tの各節点uの各種情報を出力するプログラム.
#include <iostream>
#define MAX 10000
#define NIL - 1
struct Node {int parent, left, right;};
Node T[MAX];
int n, D[MAX], H[MAX];
using namespace std;
void setDepth(int u, int d) {
if (u == NIL) return;
D[u] = d;
setDepth(T[u].left, d+1);
setDepth(T[u].right, d+1);
}
// 節点uの兄弟を返す
int getSibling(int u) {
if (T[u].parent == NIL) {
return NIL;
}
if (T[T[u].parent].left != u && T[T[u].parent].left != NIL) {
return T[T[u].parent].left;
}
if (T[T[u].parent].right != u && T[T[u].parent].right != NIL) {
return T[T[u].parent].right;
}
return NIL;
}
void print(int u) {
printf("node %d: ", u);
printf("parent = %d: ", T[u].parent);
printf("sibling = %d: ", getSibling(u));
// 節点の子の数
int deg = 0;
if (T[u].left != NIL) {
deg++; // 子要素の追加
}
if (T[u].right != NIL) {
deg++; // 子要素の追加
}
printf("degree %d: ", deg);
printf("depth = %d: ", D[u]);
printf("height = %d: ", H[u]);
if (T[u].parent == NIL) {
printf("root/n");
} else if (T[u].left == NIL && T[u].right == NIL) {
printf("leaf/n");
} else {
printf("internal node/n");
}
}
// 二分木の表現
int main(int argc, char** argv) {
int v, l, r, root = 0;
int n = 9;
for (int i = 0; i < n; i++) {
T[i].parent = NIL;
}
// 二分木を表現
// v:id(節点の番号) l:left(左要素の番号) r:right(右要素の番号)
for (int i = 0; i < n; i++) {
scanf("%d %d %d", &v, &l, &r);
T[v].left = l;
T[v].right = r;
if (l != NIL) {
T[l].parent = v;
}
if (r != NIL) {
T[r].parent = v;
}
}
// root要素の検索
for (int i = 0; i < n; i++) {
if (T[i].parent == NIL) {
root = i;
}
}
setDepth(root, 0);
setHeight(root);
for (int i = 0; i < n; i++) {
print(i);
}
return 0;
}
🔎対象ソースは以下に格納.
/source/6.tree/binary.cpp