二分木(binary tree)とは、空の木であるか、根と、左部分木・右部分木と呼ぶ 2 つの二分木の組であるものとして帰納的に定まる木で、各節点の子を左右で区別する。深さ $d$ の節点は高々 $2^d$ 個なので、葉の深さ $d_1,\dots,d_\ell$ は $\sum_i2^{-d_i}\le1$ を満たし、等号は全二分木に限る。逆にこの不等式を満たす深さはある二分木の葉の深さになり(符号理論の Kraft の不等式)、ここから比較による並べ替えには $\log_2n!$ 回以上の比較が要ることが従う。節点の名前が相異なれば、前順と中順の 2 つの列から木を復元できる。
二分木 は、各節点から左と右の 2 つの枝が出る(どちらも、あるいは片方がない場合も含む)根付きの木である。左右を区別することが根付き木との違いで、この区別によって、式の構文、比較による判定の手順、0 と 1 の符号語などを 1 つの形で表せる。
二分木の基本的な数量は、深さ $d$ の節点が高々 $2^d$ 個であることから決まる。とくに葉の深さ $d_1,\dots,d_\ell$ は $\sum_i2^{-d_i}\le1$ を満たし、逆にこの不等式を満たす深さの組はある二分木の葉の深さとして実現される(thm-btr-kraft)。ここから、$\ell$ 個の葉をもつ二分木の葉の平均の深さは $\log_2\ell$ 以上であることが従い、比較だけで $n$ 個のものを並べ替えるには $\log_2 n!$ 回以上の比較が要ること(cor-btr-sorting)が分かる。また、節点に相異なる名前を付けた二分木は、前から順になぞった列と、中ほどでなぞった列の 2 つから復元できる(thm-btr-traversal)。
二分木(binary tree)を次のように帰納的に定める。
この定義は Catalan数 の記事の定義「左右を区別する二分木」と同じである。左右を区別するので、根 $v$ と節点 $w$ からなる二分木は、$w$ が左の子である $(v,(w,\epsilon,\epsilon),\epsilon)$ と右の子である $(v,\epsilon,(w,\epsilon,\epsilon))$ の 2 つがあり、両者は異なる。根付き木としてはどちらも「根と子 1 つ」で同じものである。
節点の位置は 0 と 1 の列で表せる。根の位置を空の列とし、左部分木の節点の位置には先頭に $0$ を、右部分木の節点の位置には先頭に $1$ を付ける。位置 $w$ の節点の左の子の位置は $w0$、右の子の位置は $w1$ であり、位置の列の長さを節点の 深さ という(根の深さは $0$)。節点の深さの最大値を二分木の 高さ といい、空の木の高さは $-1$ と約束する。位置の全体 $P(T)$ は、「$w\in P(T)$ なら $w$ の最後の文字を除いた列も $P(T)$ に属する」という性質をもつ有限集合で、逆にこの性質をもつ有限集合はちょうど 1 つの二分木の位置の全体になる。以下では二分木と位置の全体をしばしば同一視する。
空でない二分木で、どの節点も子を $0$ 個か $2$ 個もつものを 全二分木(full binary tree)という。全二分木で、すべての葉の深さが等しいものを 完全二分木(perfect binary tree)という。
呼び方は文献によって異なり、完全二分木を complete binary tree と呼ぶこともあれば、complete binary tree を「最後の深さ以外はすべて埋まり、最後の深さは左から詰まっている」二分木の意味に使うこともある。この記事では上の定義に従う。
二分木は「はい・いいえ」で枝分かれする判定の連鎖である。根から始めて、各節点で左か右を選び、葉に着いたら止まる。根から葉までの道は 0 と 1 の列で書け、葉の深さはその列の長さ、すなわち答えに着くまでの判定の回数である。深さ $d$ の場所は $2^d$ 個しかないので、深い葉は「場所を細かく分けて」しか置けない。葉 1 つが全体の $2^{-d}$ を占めると考えれば、葉の取り分の合計が $1$ を超えないのは自然である。これが thm-btr-kraft の内容であり、判定の回数の下限はここから出てくる。
節点が $0,1,2,3$ 個の二分木は、それぞれ $1,1,2,5$ 個ある。3 個の 5 つのうち、高さ $1$ のものは根に左右の子がある 1 つだけで、これは全二分木(しかも完全二分木)である。残りの 4 つは、節点が 1 本の道に並ぶ高さ $2$ のもので、左右の選び方で $2\cdot2=4$ 個ある。一般に節点が $n$ 個の二分木の個数は Catalan 数 $C_n=\frac1{n+1}\binom{2n}n$ である(Catalan数 の記事の命題「二分木の個数」)。
式 $(a+b)\times c$ は、根が $\times$、その左部分木が「根 $+$、左の子 $a$、右の子 $b$」、右部分木が $c$ だけの二分木で表せる。内部節点が演算、葉が変数である全二分木であり、葉 $3$ 個・内部節点 $2$ 個である。この木を下の def-btr-traversal の 3 通りの順になぞると、
$$
\text{前順}:\ \times\ +\ a\ b\ c,\qquad \text{中順}:\ a\ +\ b\ \times\ c,\qquad \text{後順}:\ a\ b\ +\ c\ \times
$$
となる。前順と後順は括弧なしで式を表す書き方(前置記法・後置記法)で、中順は括弧を補わないと $a+(b\times c)$ と区別できない。
相異なる数 $x_1,x_2,x_3$ を大きさの順に並べる。まず $x_1$ と $x_2$ を比べ、$x_1< x_2$ なら $x_2$ と $x_3$ を比べる。$x_2< x_3$ なら順は $x_1,x_2,x_3$ と決まり、そうでなければ $x_1$ と $x_3$ を比べて決める。$x_1>x_2$ の側も同様にする。比較を内部節点、答えを葉とする全二分木ができ、葉は $3!=6$ 個で、深さは $2,3,3,2,3,3$ である。最悪で $3$ 回、6 通りの順が等しく起こるとすると平均 $\frac{16}6\approx2.67$ 回の比較を使う。cor-btr-sorting によれば、どんな比較の手順でも、最悪の回数は $\log_26\approx2.58$ 以上、すなわち $3$ 以上であり、平均も $\log_26$ 以上である。
1:$n$ 個の節点はそれぞれ左右 2 つの枝の場所をもち、場所は全部で $2n$ 個ある。根以外の節点はちょうど 1 つの場所(親の左か右)を埋めるので、埋まった場所は $n-1$ 個で、空の場所は $2n-(n-1)=n+1$ 個である($n=0$ なら空の木そのものが 1 個の空の部分木である)。
2:内部節点を $i$ 個とする。全二分木では内部節点はちょうど 2 つの子をもち、根以外の節点はちょうど 1 つの親をもつので、$2i=n-1$ である。$n=\ell+i$ と合わせて $\ell=i+1$、$n=2\ell-1$ である。
3:深さ $k$ の節点の位置は長さ $k$ の 0 と 1 の列で、互いに異なるので $2^k$ 個以下である。$k=0,\dots,h$ について足して $n\le2^{h+1}-1$ である。葉については、深さ $d$ の葉の位置 $w$ に、$w$ を先頭にもつ長さ $h$ の列の集合($2^{h-d}\ge1$ 個)を対応させる。葉の位置は互いに他の先頭部分にならない(先頭部分は祖先の位置である)ので、これらの集合は互いに交わらず、葉は $2^h$ 個以下である。
$n=2^{h+1}-1$ なら、長さ $h$ 以下のすべての列が位置であり、深さ $h$ 未満の節点はすべて 2 つの子をもち、深さ $h$ の節点は葉なので、高さ $h$ の完全二分木である。逆に高さ $h$ の完全二分木では、葉はすべて深さ $h$ にあるので深さ $h$ 未満の節点はすべて内部節点で、全二分木だから 2 つの子をもつ。深さについての帰納法で、各 $k\le h$ について長さ $k$ のすべての列が位置になり、$n=2^{h+1}-1$ である。最後の主張は $n\le2^{h+1}-1$ を書き直したものである。$\square$
1 は、節点を $n$ 個もつ二分木を「空の部分木を $n+1$ 個の葉とみなした全二分木」と読み替えられることを示している。2 と合わせると、葉が $n+1$ 個の全二分木と節点が $n$ 個の二分木が 1 対 1 に対応し、どちらも $C_n$ 個ある。
空でない二分木 $T$ の葉の深さを $d_1,\dots,d_\ell$ とし、$S(T):=\sum_{i=1}^\ell2^{-d_i}$ とおく。空の木では $S(\epsilon):=0$ とする。次の定理は、符号理論で Kraft の不等式 と呼ばれるものの二分木による言い換えである。0 と 1 の列からなる符号語の集合で、どの符号語もほかの符号語の先頭部分にならないもの(接頭符号)は、符号語を葉の位置とする二分木と同じものであり、符号語の長さは葉の深さである(Eri19 §4.4、p. 165)。
1:節点の個数についての帰納法で示す。節点が 1 個なら、根が深さ $0$ の葉なので $S(T)=1$ であり、$T$ は全二分木である。節点が 2 個以上の $T=(v,L,R)$ では、$v$ は葉でなく、$T$ の葉は $L$ の葉と $R$ の葉で、深さは $L,R$ の中での深さより $1$ 大きい。よって
$$
S(T)=\frac12\bigl(S(L)+S(R)\bigr)
$$
である。帰納法の仮定と $S(\epsilon)=0$ により $S(L),S(R)\le1$ なので $S(T)\le1$ である。等号は $S(L)=S(R)=1$ のときに限り、それは $L,R$ がともに空でなく($S(\epsilon)=0$ だから)全二分木であることと同値で、さらにそれは $T$ が全二分木であることと同値である($T$ の根が子を 2 個もち、ほかの節点の子の個数は $L$ か $R$ の中で決まる)。
2:番号を付け替えて $d_1\le d_2\le\dots\le d_\ell$ としてよい。$a_i:=2^{d_i}\sum_{j< i}2^{-d_j}$ とおく。$j< i$ なら $d_j\le d_i$ なので $2^{d_i-d_j}$ は整数で、$a_i$ は $0$ 以上の整数である。また $\sum_{j< i}2^{-d_j}\le1-2^{-d_i}$ なので $a_i\le2^{d_i}-1$ である。そこで $a_i$ を $d_i$ 桁の 2 進法で(先頭に $0$ を補って)書いた列を $c_i$ とする($d_i=0$ なら $\ell=1$ で $c_1$ は空の列)。
$i< j$ のとき $c_i$ は $c_j$ の先頭部分でないことを示す。$c_j$ の先頭の $d_i$ 文字が表す整数は $\lfloor a_j2^{d_i-d_j}\rfloor=\bigl\lfloor2^{d_i}\sum_{k< j}2^{-d_k}\bigr\rfloor$ である。ここで $\sum_{k< j}2^{-d_k}\ge\sum_{k< i}2^{-d_k}+2^{-d_i}$ なので、この整数は $a_i+1$ 以上で、$a_i$ と異なる。とくに $c_1,\dots,c_\ell$ は互いに異なる。
$c_1,\dots,c_\ell$ とそれらの先頭部分の全体を $P$ とすると、$P$ は先頭部分をとる操作で閉じた有限集合なので、ある二分木の位置の全体である。$c_i$ はほかの $c_j$ の先頭部分でないので、その真の延長は $P$ に属さず、$c_i$ は葉の位置である。$c_i$ でない $P$ の元は、ある $c_j$ の真の先頭部分なので子をもち、葉でない。よって葉はちょうど $c_1,\dots,c_\ell$ の位置にあり、深さは $d_1,\dots,d_\ell$ である。$\square$
2 で作った二分木は全二分木とは限らない。たとえば $\ell=1$、$d_1=2$ なら、根から左に 2 回進んだ道になる。和が $1$ のときは 1 の等号の条件により全二分木になる。符号の言葉では、2 は「長さの組が不等式を満たせば、その長さをもつ接頭符号がある」という主張で、これを証明したのが Kraft であり、一意に復号できる符号では長さが不等式 $\sum_i2^{-d_i}\le1$ を満たすことを McMillan が示した(Mac03 §5.2、pp. 94–95)。
葉が $\ell$ 個の二分木の葉の深さを $d_1,\dots,d_\ell$ とすると
$$
\frac1\ell\sum_{i=1}^\ell d_i\ \ge\ \log_2\ell,\qquad \max_i d_i\ \ge\ \log_2\ell
$$
である。
thm-btr-kraft の 1 と、相加平均と相乗平均 の不等式により
$$
\frac1\ell\ \ge\ \frac1\ell\sum_{i=1}^\ell2^{-d_i}\ \ge\ \Bigl(\prod_{i=1}^\ell2^{-d_i}\Bigr)^{1/\ell}=2^{-\frac1\ell\sum_id_i}
$$
であり、両辺の $\log_2$ をとって $-\log_2\ell\ge-\frac1\ell\sum_id_i$ を得る。平均は最大値以下なので、後半も従う。$\square$
相異なる $n$ 個の数 $x_1,\dots,x_n$ の大小の順を、2 つを比べる操作だけで決める手順は、次の二分木で表せる。内部節点には「$x_p< x_q$ か」という問いを置き、答えが「はい」なら左、「いいえ」なら右へ進む。葉には答えとして $1,\dots,n$ の並べ替え($x$ を小さい順に並べたときの添字の列)を置く。入力の大小の順は $n!$ 通りあり、どの順についても、根から問いに答えながら進むと 1 つの葉に着く。手順が正しいとは、どの順についても、着いた葉の答えがその順に一致することである。この二分木を 比較の木(決定木)という。
$n$ 個のものを比較だけで正しく並べ替えるどの手順についても、最悪の場合の比較の回数は $\log_2n!$ 以上である。$n!$ 通りの順が等しく起こるとしたときの比較の回数の平均も $\log_2n!$ 以上である。
相異なる 2 つの順は正しい答えが異なるので、正しい手順では異なる葉に着く。よって着く葉は $n!$ 個あり、それぞれの順で使う比較の回数はその葉の深さである。それら $n!$ 個の葉の深さを $e_1,\dots,e_{n!}$ とする。thm-btr-kraft の 1 により、比較の木のすべての葉について $2^{-(\text{深さ})}$ を足しても $1$ 以下なので、$\sum_k2^{-e_k}\le1$ である。cor-btr-average-depth の証明と同じ計算により、$e_k$ の平均と最大値はどちらも $\log_2n!$ 以上である。$\square$
$n!\ge(n/2)^{n/2}$(大きい方の半分の因子はどれも $n/2$ 以上)なので、$\log_2n!\ge\frac n2\log_2\frac n2$ であり、比較による並べ替えには $n\log n$ に比例する回数が避けられない。ex-btr-decision の $n=3$ では $\log_26\approx2.58$ で、最悪 $3$ 回の手順は最良である。
各節点に名前(ラベル)を付けた二分木を考える。
節点に名前を付けた二分木 $T$ の 前順(preorder)$\mathrm{pre}(T)$、中順(inorder)$\mathrm{in}(T)$、後順(postorder)$\mathrm{post}(T)$ を、名前の列として次で定める。空の木では 3 つとも空の列とし、$T=(v,L,R)$ で $v$ の名前を $x$ とするとき
$$
\mathrm{pre}(T)=x,\ \mathrm{pre}(L),\ \mathrm{pre}(R),\qquad \mathrm{in}(T)=\mathrm{in}(L),\ x,\ \mathrm{in}(R),\qquad \mathrm{post}(T)=\mathrm{post}(L),\ \mathrm{post}(R),\ x
$$
とする(コンマは列をつなぐことを表す)。
3 つの列はどれも、すべての節点の名前を 1 回ずつ並べたもので、長さは節点の個数に等しい。前順は根を最初に、後順は根を最後に置き、中順は根を左部分木と右部分木の間に置く。根から 深さ優先探索 を行い、各節点で左の子、右の子の順に進むと、前順は節点を発見した順、後順は訪問を終えた順になる。
節点の名前が互いに異なる 2 つの二分木 $T,T'$ について、$\mathrm{pre}(T)=\mathrm{pre}(T')$ かつ $\mathrm{in}(T)=\mathrm{in}(T')$ なら、$T$ と $T'$ は同じ形で、同じ位置に同じ名前をもつ。
節点の個数 $n$ についての帰納法で示す。列の長さは節点の個数なので、$T,T'$ の節点の個数は等しい。$n=0$ ならどちらも空の木である。$n\ge1$ とし、$T=(v,L,R)$、$T'=(v',L',R')$ とする。前順の最初の名前は根の名前なので、$v$ と $v'$ の名前は等しい。それを $x$ とする。名前は互いに異なるので、$x$ は中順の列にちょうど 1 回現れ、その位置を $k+1$ 番目とする。$\mathrm{in}(T)=\mathrm{in}(L),x,\mathrm{in}(R)$ で $x$ は $\mathrm{in}(L)$ に現れないので、$L$ の節点は $k$ 個で、$\mathrm{in}(L)$ は中順の最初の $k$ 個、$\mathrm{in}(R)$ は $k+2$ 番目以降である。同じことが $T'$ についても成り立つので $\mathrm{in}(L)=\mathrm{in}(L')$、$\mathrm{in}(R)=\mathrm{in}(R')$ である。前順では、$\mathrm{pre}(L)$ は 2 番目から $k+1$ 番目、$\mathrm{pre}(R)$ はそれ以降なので、$\mathrm{pre}(L)=\mathrm{pre}(L')$、$\mathrm{pre}(R)=\mathrm{pre}(R')$ である。$L,L'$ と $R,R'$ の節点はそれぞれ $n$ 個未満で名前は互いに異なるので、帰納法の仮定により $L$ と $L'$、$R$ と $R'$ は同じである。よって $T$ と $T'$ は同じである。$\square$
証明は復元の手順にもなっている。前順の先頭で根を知り、中順の中の根の位置で左右の節点の個数を知り、それぞれの部分木について同じことを繰り返せばよい。中順と後順の組からも、後順の末尾が根であることを使って同じように復元できる。一方、前順と後順の組からは一般には復元できない(ex-btr-counterexamples)。左右の部分木の一方が空のとき、前順と後順のどちらにも「どちら側が空か」が現れないからである。全二分木ではこの曖昧さがない。
節点の名前が互いに異なる 2 つの全二分木 $T,T'$ について、$\mathrm{pre}(T)=\mathrm{pre}(T')$ かつ $\mathrm{post}(T)=\mathrm{post}(T')$ なら、$T$ と $T'$ は同じである。
節点の個数 $n$ についての帰納法で示す。$n=1$ なら根だけの木で、名前も前順で決まる。$n\ge2$ なら $T=(v,L,R)$ の根は葉でなく、全二分木なので $L,R$ はともに空でない全二分木である($T'=(v',L',R')$ も同じ)。根の名前は前順の最初で決まる。前順の 2 番目の名前 $y$ は $L$ の根の名前である。後順は $\mathrm{post}(L),\mathrm{post}(R),x$ の形で、$L$ の根の名前 $y$ は $\mathrm{post}(L)$ の最後にある。名前は互いに異なるので、$y$ が後順の $k$ 番目にあれば $L$ の節点は $k$ 個である。これは $T'$ でも同じなので、前順と後順をそれぞれ左部分木の分と右部分木の分に切り分けられ、$\mathrm{pre}(L)=\mathrm{pre}(L')$、$\mathrm{post}(L)=\mathrm{post}(L')$、$R,R'$ についても同様である。帰納法の仮定により $L=L'$、$R=R'$ であり、$T=T'$ である。$\square$
| 外す条件 | 反例 | 成り立たなくなること |
|---|---|---|
| 左右の区別 | 節点 2 個の二分木 | 節点 $n$ 個のものが $C_n$ 個ある |
| 全二分木であること | 根と左の子だけの二分木 | $S(T)=1$、葉と内部節点の個数の差が $1$ |
| 深さの和の条件 $\sum2^{-d_i}\le1$ | 深さ $1,1,1$ | その深さの葉をもつ二分木がある |
| 中順を後順に替える | 根 $a$ と子 $b$ だけの 2 つの二分木 | 前順と組にして木が決まる |
| 名前が互いに異なること | 2 つの節点の名前がどちらも $a$ | 前順と中順で木が決まる |
1 行目:節点 2 個の二分木は、子が左にあるものと右にあるものの $2=C_2$ 個あるが、根付き木としては 1 個である。
2 行目:根と左の子だけの二分木では、葉は深さ $1$ の 1 個で $S(T)=\frac12<1$ であり、葉 $1$ 個・内部節点 $1$ 個である。
3 行目:$\frac12+\frac12+\frac12>1$ である。実際、深さ $1$ の節点は位置 $0$ と $1$ の 2 個しかないので、深さ $1$ の葉を 3 個もつ二分木はない。
4 行目:根 $a$ に左の子 $b$ だけがある木と、右の子 $b$ だけがある木は、前順がどちらも $a,b$、後順がどちらも $b,a$ である。中順はそれぞれ $b,a$ と $a,b$ で異なり、thm-btr-traversal と矛盾しない。この 2 つは全二分木でないので、prop-btr-full-pre-post とも矛盾しない。
5 行目:4 行目の 2 つの木の $b$ を $a$ に替えると、前順も中順もどちらも $a,a$ になる。
二分木は計算機で集まりを扱う基本の形である。各節点に数を置き、どの節点についても左部分木の数はそれより小さく右部分木の数はそれより大きいようにしたものを 二分探索木 という。定義から、二分探索木の中順は数を小さい順に並べた列である。探索の手間は高さに比例するので、prop-btr-counts の 3 により、節点 $n$ 個なら高さを $\log_2(n+1)-1$ 程度まで下げられることが重要になる。葉に符号語を置く見方は情報の圧縮に使われ、出現の頻度に応じて葉の深さを選び、深さの重み付きの和を最小にする全二分木を作る方法が Huffman の符号である(Eri19 §4.4、pp. 165–166)。
Mathpediaは寄付と、参考文献の書籍リンク(Amazonアソシエイト)の紹介料で運営されています。 支援について / 寄付する