1
最下位共通先祖問題と MF 木
** ここで理解すべき内容 **
抽象データ型
Merge-Find 集合 (Union-Find 集合)
データ構造
Merge-Find 木 (Merge-Find tree)
計算量評価方法
均し計算量 (amortized complexity)
2
例として考える問題
オフライン
最下位共通先祖
問題
3
オフライン最下位共通先祖問題
Off-line Lowest Common Ancestors Problem
入力:
根付き木 T = (V,E)
点対の集合 P = { p=(v,w) | v, w は T の点 }
出力:
各点対 p=(v,w)∈P に対する
(木 T 上での)最下位共通先祖 anc(p)
4
最下位共通先祖
木 T 上の質問点対 p=(v,w) に対する
最下位共通先祖 anc(p) = a
木 T の点 a で,以下の性質を持つもの
v と w の共通の先祖であり,
a の真の子孫には
v と w の共通の先祖が無い
5
オフライン最下位共通先祖問題
質問点対の集合 P
P = { (c,h), (e,f),
(f,g), (g,h) }
木T
b
d
a
g
c
h
e
f
最下位共通先祖
anc( (c,h) ) = b
anc( (e,f) ) = e
anc( (f,g) ) = b
anc( (g,h) ) = d
6
オフライン(off-line)問題
オフライン(off-line)問題
全ての質問を予め知った上で
各質問に対する答えを求めるもの
オンライン(on-line)問題
全質問を予め知ることができず,
質問毎に答えを出すもの
7
オフライン最下位共通先祖問題
に対するアルゴリズム
8
アルゴリズム
木 T を深さ優先探索(DFS)して求める.
void DFS( v, T ) {
行きがけの処理 ;
c := lm_child(v) ;
/* c を v の長男に */
while ( 子 c が存在する ) {
DFS( c, T ) ;
子 c の情報を利用する処理 ;
c := r_sibling( c ) ; /* c を次弟に */
}
帰りがけの処理 ;
} /* end DFS */
帰りがけに,最下位共通先祖が求められる ?
r
v
c
c'
9
点 v からの帰りがけ時の検査
(v,w)∈P なる質問点対が存在し
w は既に探索済みか?
b
d
もし,そうならば,
w の先祖で探索中の点の内,
最下位にある点 a は,
v と w の最下位共通先祖
anc( (v,w) )
a
w
e
v
10
必要な操作
1. 点 v を含む質問点対 (v,w)
∈P が存在するか否かの検査
b
d
2. もう一方の点 w は既に探索
済みか否かの検査
3. w の探索中の先祖で,最下
位の点の探索
これらを効率良く実行したい
a
w
e
v
11
必要な操作 1
点 v を含む質問点対 (v,w)∈P
が存在するか否かの検査に対しては,
木 T の各点 v に対して,
v を含む質問点対 p=(v,w) ∈ P の集合
P(v) = { p | p=(v,w)∈ P }
を覚えておく
w
v
w'
12
必要な操作 2
b
点 v を含む質問点対 (v,w)∈P
のもう一方の点 w が,
既に探索済みか否かの検査は
d
a
点に
未探索
探索中
探索済み
の印を付けておけば良い
w
e
v
13
必要な操作 3
b
点 w の探索中の先祖で,
最下位のもの a を求めるには,
d
“探索中” の各点 a に対して,
集合 U(a) = { a }
{ w, ・・・
a
}
w は a の子孫で探策済み,
w の先祖で a より下に探索中の点は無い
を覚える
w ∈U(a) と現在探索中の点 v との
最下位共通先祖は a = anc( (v,w) )
U(a) の初期値は, U(a) = { a } とする
w
e
v
14
アルゴリズムの例
集合 U(・) に対する操作
15
木 T と集合 U(・) および P(・)
木T
b
d
a
g
c
h
e
f
A = U(a) = { a }
B = U(b) = { b }
C = U(c) = { c }
D = U(d) = { d }
E = U(e) = { e }
F = U(f) = { f }
G = U(g) = { g }
H = U(h) = { h }
P(c) = { (c,h) }
P(e) = { (e,f) }
P(f) = { (e,f), (f,g) }
P(g) = { (f,g), (g,h) }
P(h) = { (c,h), (g,h) }
16
木 T の深さ優先探索
木T
探索中
b
d
a
g
c
h
e
f
A = U(a) = { a }
B = U(b) = { b }
C = U(c) = { c }
D = U(d) = { d }
E = U(e) = { e }
F = U(f) = { f }
G = U(g) = { g }
H = U(h) = { h }
P(c) = { (c,h) }
P(e) = { (e,f) }
P(f) = { (e,f), (f,g) }
P(g) = { (f,g), (g,h) }
P(h) = { (c,h), (g,h) }
17
木 T の深さ優先探索
探索中
木T
b
d
a
g
c
h
e
f
A = U(a) = { a }
B = U(b) = { b }
C = U(c) = { c }
D = U(d) = { d }
E = U(e) = { e }
F = U(f) = { f }
G = U(g) = { g }
H = U(h) = { h }
P(c) = { (c,h) }
P(e) = { (e,f) }
P(f) = { (e,f), (f,g) }
P(g) = { (f,g), (g,h) }
P(h) = { (c,h), (g,h) }
18
木 T の深さ優先探索
木T
b
d
a
g
c
h
e
f
A = U(a) = { a }
B = U(b) = { b }
C = U(c) = { c }
D = U(d) = { d }
E = U(e) = { e }
F = U(f) = { f }
G = U(g) = { g }
H = U(h) = { h }
P(c) = { (c,h) }
P(e) = { (e,f) }
P(f) = { (e,f), (f,g) }
P(g) = { (f,g), (g,h) }
P(h) = { (c,h), (g,h) }
19
木 T の深さ優先探索
木T
b
d
a
g
c
h
e
f
A = U(a) = { a }
B = U(b) = { b }
C = U(c) = { c }
D = U(d) = { d }
E = U(e) = { e }
F = U(f) = { f }
G = U(g) = { g }
H = U(h) = { h }
P(c) = { (c,h) }
P(e) = { (e,f) }
P(f) = { (e,f), (f,g) }
P(g) = { (f,g), (g,h) }
P(h) = { (c,h), (g,h) }
20
点 g の探索終了: P(g) の検査
木T
b
d
a
c
h
g
探索済
e
f
f, h は未探索
⇒ 何もしない
A = U(a) = { a }
B = U(b) = { b }
C = U(c) = { c }
D = U(d) = { d }
E = U(e) = { e }
F = U(f) = { f }
G = U(g) = { g }
H = U(h) = { h }
P(c) = { (c,h) }
P(e) = { (e,f) }
P(f) = { (e,f), (f,g) }
P(g) = { (f,g), (g,h) }
P(h) = { (c,h), (g,h) }
21
点 g から戻る: A と G の併合
木T
A = U(a) = { a, g }
b
d
a
g
c
h
e
f
A = U(a) = { a }
B = U(b) = { b }
C = U(c) = { c }
D = U(d) = { d }
E = U(e) = { e }
F = U(f) = { f }
G = U(g) = { g }
H = U(h) = { h }
P(c) = { (c,h) }
P(e) = { (e,f) }
P(f) = { (e,f), (f,g) }
P(g) = { (f,g), (g,h) }
P(h) = { (c,h), (g,h) }
22
点 a に戻った
木T
b
d
a
g
c
h
e
f
A = U(a) = { a, g }
B = U(b) = { b }
C = U(c) = { c }
D = U(d) = { d }
E = U(e) = { e }
F = U(f) = { f }
G = U(g) = { g }
H = U(h) = { h }
P(c) = { (c,h) }
P(e) = { (e,f) }
P(f) = { (e,f), (f,g) }
P(g) = { (f,g), (g,h) }
P(h) = { (c,h), (g,h) }
23
点 a の探索終了:
木T
b
d
a
g
c
h
e
f
P(a) は空
A = U(a) = { a, g }
B = U(b) = { b }
C = U(c) = { c }
D = U(d) = { d }
E = U(e) = { e }
F = U(f) = { f }
G = U(g) = { g }
H = U(h) = { h }
P(c) = { (c,h) }
P(e) = { (e,f) }
P(f) = { (e,f), (f,g) }
P(g) = { (f,g), (g,h) }
P(h) = { (c,h), (g,h) }
24
点 a から戻る : A と D を併合
木T
b
d
a
g
c
h
A = U(a) = { a, g }
B = U(b) = { b }
D = U(d) = { a, d, g }
C = U(c) = { c }
D = U(d) = { d }
E = U(e) = { e }
F = U(f) = { f }
e
G = U(g) = { g }
H = U(h) = { h }
f
P(c) = { (c,h) }
P(e) = { (e,f) }
P(f) = { (e,f), (f,g) }
P(g) = { (f,g), (g,h) }
P(h) = { (c,h), (g,h) }
25
点 d に戻った
木T
b
d
a
g
c
h
e
f
A = U(a) = { a, g }
B = U(b) = { b }
C = U(c) = { c }
D = U(d) = { a, d, g }
E = U(e) = { e }
F = U(f) = { f }
G = U(g) = { g }
H = U(h) = { h }
P(c) = { (c,h) }
P(e) = { (e,f) }
P(f) = { (e,f), (f,g) }
P(g) = { (f,g), (g,h) }
P(h) = { (c,h), (g,h) }
26
点 h を深さ優先探索
木T
b
d
a
g
c
h
e
f
A = U(a) = { a, g }
B = U(b) = { b }
C = U(c) = { c }
D = U(d) = { a, d, g }
E = U(e) = { e }
F = U(f) = { f }
G = U(g) = { g }
H = U(h) = { h }
P(c) = { (c,h) }
P(e) = { (e,f) }
P(f) = { (e,f), (f,g) }
P(g) = { (f,g), (g,h) }
P(h) = { (c,h), (g,h) }
27
点 h の探索終了: P(h) の検査
木T
b
d
a
c
h
e
f
g
g は探索済み
⇒ anc((g,h)) は?
A = U(a) = { a, g }
B = U(b) = { b }
C = U(c) = { c }
D = U(d) = { a, d, g }
E = U(e) = { e }
F = U(f) = { f }
G = U(g) = { g }
H = U(h) = { h }
P(c) = { (c,h) }
P(e) = { (e,f) }
P(f) = { (e,f), (f,g) }
P(g) = { (f,g), (g,h) }
P(h) = { (c,h), (g,h) }
28
点 g を含む集合 U(・) の探索
木T
b
d
a
c
h
e
f
g
g ∈ U(d)
⇒ anc((g,h)) = d
A = U(a) = { a, g }
B = U(b) = { b }
C = U(c) = { c }
D = U(d) = { a, d, g }
E = U(e) = { e }
F = U(f) = { f }
G = U(g) = { g }
H = U(h) = { h }
P(c) = { (c,h) }
P(e) = { (e,f) }
P(f) = { (e,f), (f,g) }
P(g) = { (f,g), (g,h) }
P(h) = { (c,h), (g,h) }
29
点 h から戻る : H と D を併合
a
g
A = U(a) = { a, g }
木T
D = U(d) = { a, d, g, h } B = U(b) = { b }
C = U(c) = { c }
b
D = U(d) = { a, d, g }
E = U(e) = { e }
F = U(f) = { f }
d
c
e
G = U(g) = { g }
H = U(h) = { h }
f
h
P(c) = { (c,h) }
P(e) = { (e,f) }
P(f) = { (e,f), (f,g) }
P(g) = { (f,g), (g,h) }
P(h) = { (c,h), (g,h) }
30
点 d に戻った
木T
b
d
a
g
c
h
e
f
A = U(a) = { a, g }
B = U(b) = { b }
C = U(c) = { c }
D = U(d) = { a, d, g, h }
E = U(e) = { e }
F = U(f) = { f }
G = U(g) = { g }
H = U(h) = { h }
P(c) = { (c,h) }
P(e) = { (e,f) }
P(f) = { (e,f), (f,g) }
P(g) = { (f,g), (g,h) }
P(h) = { (c,h), (g,h) }
31
点 d から戻る
木T
b
d
a
c
h
e
f
g
P(d) は空
⇒ B と D を併合
A = U(a) = { a, g }
B = U(b) = { b }
C = U(c) = { c }
D = U(d) = { a, d, g, h }
E = U(e) = { e }
F = U(f) = { f }
G = U(g) = { g }
H = U(h) = { h }
P(c) = { (c,h) }
P(e) = { (e,f) }
P(f) = { (e,f), (f,g) }
P(g) = { (f,g), (g,h) }
P(h) = { (c,h), (g,h) }
32
点 b に戻った
木T
b
d
a
g
c
h
e
f
A = U(a) = { a, g }
B = U(b) = { a, b, d, g, h }
C = U(c) = { c }
D = U(d) = { a, d, g, h }
E = U(e) = { e }
F = U(f) = { f }
G = U(g) = { g }
H = U(h) = { h }
P(c) = { (c,h) }
P(e) = { (e,f) }
P(f) = { (e,f), (f,g) }
P(g) = { (f,g), (g,h) }
P(h) = { (c,h), (g,h) }
33
点 c を深さ優先探索
木T
b
d
a
g
c
h
e
f
A = U(a) = { a, g }
B = U(b) = { a, b, d, g, h }
C = U(c) = { c }
D = U(d) = { a, d, g, h }
E = U(e) = { e }
F = U(f) = { f }
G = U(g) = { g }
H = U(h) = { h }
P(c) = { (c,h) }
P(e) = { (e,f) }
P(f) = { (e,f), (f,g) }
P(g) = { (f,g), (g,h) }
P(h) = { (c,h), (g,h) }
34
点 c の探索終了: P(c) の検査
a
A = U(a) = { a, g }
h
を含む
U(・)
は?
木T
B = U(b) = { a, b, d, g, h }
⇒ anc((c,h)) = b
C = U(c) = { c }
b
D = U(d) = { a, d, g, h }
E = U(e) = { e }
F = U(f) = { f }
d
c
e
G = U(g) = { g }
H = U(h) = { h }
f
h
g
h は探索済み
⇒ anc((c,h)) は?
P(c) = { (c,h) }
P(e) = { (e,f) }
P(f) = { (e,f), (f,g) }
P(g) = { (f,g), (g,h) }
P(h) = { (c,h), (g,h) }
35
点 c から戻る : C と B を併合
木T
b
d
a
g
c
h
e
f
A = U(a) = { a, g }
B = U(b) = { a, b, d, g, h }
C = U(c) = { c }
D = U(d) = { a, d, g, h }
E = U(e) = { e }
F = U(f) = { f }
G = U(g) = { g }
H = U(h) = { h }
P(c) = { (c,h) }
P(e) = { (e,f) }
P(f) = { (e,f), (f,g) }
P(g) = { (f,g), (g,h) }
P(h) = { (c,h), (g,h) }
36
点 b に戻った
木T
b
d
a
g
c
h
e
f
A = U(a) = { a, g }
B = U(b) = { a, b, c, d, g, h }
C = U(c) = { c }
D = U(d) = { a, d, g, h }
E = U(e) = { e }
F = U(f) = { f }
G = U(g) = { g }
H = U(h) = { h }
P(c) = { (c,h) }
P(e) = { (e,f) }
P(f) = { (e,f), (f,g) }
P(g) = { (f,g), (g,h) }
P(h) = { (c,h), (g,h) }
37
点 e, f へ深さ優先探索
木T
b
d
a
g
c
h
e
f
A = U(a) = { a, g }
B = U(b) = { a, b, c, d, g, h }
C = U(c) = { c }
D = U(d) = { a, d, g, h }
E = U(e) = { e }
F = U(f) = { f }
G = U(g) = { g }
H = U(h) = { h }
P(c) = { (c,h) }
P(e) = { (e,f) }
P(f) = { (e,f), (f,g) }
P(g) = { (f,g), (g,h) }
P(h) = { (c,h), (g,h) }
38
点 f の探索終了 : P(f) の検査
a
g
A = U(a) = { a, g }
g
を含む
U(・)
は?
木T
B = U(b) = { a, b, c, d, g, h }
⇒ anc((f,g)) = b
C = U(c) = { c }
b
D = U(d) = { a, d, g, h }
E = U(e) = { e }
F = U(f) = { f }
d
c
e
G = U(g) = { g }
H = U(h) = { h }
f
h
P(c) = { (c,h) }
P(e) = { (e,f) }
P(f) = { (e,f), (f,g) }
g は探索済み
P(g) = { (f,g), (g,h) }
⇒ anc((f,g)) は? P(h) = { (c,h), (g,h) }
39
点 f から戻る : F と E の併合
木T
b
d
a
g
c
h
e
f
A = U(a) = { a, g }
B = U(b) = { a, b, c, d, g, h }
C = U(c) = { c }
D = U(d) = { a, d, g, h }
E = U(e) = { e }
F = U(f) = { f }
G = U(g) = { g }
H = U(h) = { h }
P(c) = { (c,h) }
P(e) = { (e,f) }
P(f) = { (e,f), (f,g) }
P(g) = { (f,g), (g,h) }
P(h) = { (c,h), (g,h) }
40
点 e に戻った
木T
b
d
a
g
c
h
e
f
A = U(a) = { a, g }
B = U(b) = { a, b, c, d, g, h }
C = U(c) = { c }
D = U(d) = { a, d, g, h }
E = U(e) = { e, f }
F = U(f) = { f }
G = U(g) = { g }
H = U(h) = { h }
P(c) = { (c,h) }
P(e) = { (e,f) }
P(f) = { (e,f), (f,g) }
P(g) = { (f,g), (g,h) }
P(h) = { (c,h), (g,h) }
41
点 e の探索終了
a
A = U(a) = { a, g }
f
を含む
U(・)
は?
木T
B = U(b) = { a, b, c, d, g, h }
⇒ anc((e,f)) = e
C = U(c) = { c }
b
D = U(d) = { a, d, g, h }
E = U(e) = { e, f }
F = U(f) = { f }
d
c
e
G = U(g) = { g }
H = U(h) = { h }
f
h
g
f は探索済み
⇒ anc((e,f)) は?
P(c) = { (c,h) }
P(e) = { (e,f) }
P(f) = { (e,f), (f,g) }
P(g) = { (f,g), (g,h) }
P(h) = { (c,h), (g,h) }
42
点 e から戻る : E と B の併合
木T
b
d
a
g
c
h
e
f
A = U(a) = { a, g }
B = U(b) = { a, b, c, d, g, h }
C = U(c) = { c }
D = U(d) = { a, d, g, h }
E = U(e) = { e, f }
F = U(f) = { f }
G = U(g) = { g }
H = U(h) = { h }
P(c) = { (c,h) }
P(e) = { (e,f) }
P(f) = { (e,f), (f,g) }
P(g) = { (f,g), (g,h) }
P(h) = { (c,h), (g,h) }
43
根 b に戻り
木T
B = U(b) = { a, b, c, d, e, f, g, h }
b
d
a
g
c
h
e
f
全探索終了
44
アルゴリズムの記述と
計算量
深さ優先探索の再帰的記述
45
アルゴリズムの概要
void DFS( v, T )
/* 再帰的関数 */
木 T の点 v を根とする部分木の深さ優先探索をする関数
入力:
v
T
P(v)
出力:
anc(p) : 各質問点対 p に対する
最下位共通先祖
NODE
各点 v に対して,未探索の印しを付けておき,
集合 U(v) の初期化 U(v) = { v } を行って,
関数 DFS( 木 T の根,T ) を呼ぶ.
c
: NODE(値呼び)
: 木
: v を含む質問点対の集合
/* 局所変数 */
46
アルゴリズムの概要
void DFS( v, T ) {
v に探索中の印を付ける ;
c := lm_child(v) ;
while ( 子 c が存在する ) {
DFS( c, T ) ;
U(c) を U(v) に併合する ;
c := r_sibling( c ) ;
}
for ( 各 p=(v,w)∈P(v) ) {
if ( 点 w は探索済み ) {
点 w を含む U(a) を求める ;
v に探索済みの印を付ける ;
} /* end DFS */
実は不要
Merge( )
Find( )
}
}
47
集合 U(・) に対する操作
指定された点 w を含む集合 U(a) を見出す
Find( w )
計算量を O(TF) と書く
点 a は点 v と w の最下位共通先祖
集合 U(v) と U(c) を併合し,U(v) とする
Merge( U(c), U(v), U(v) )
計算量を O(TM) と書く
48
アルゴリズムの計算量
どの点も高々 1 回しか訪問しない
点 v に関する下記の操作は 1 回しか実行しない
各点における操作
Merge の操作
質問点対があれば,Find の操作
子を順に探索するための操作
全 Merge 回数: n-1 回 (n : 点の個数)
全 Find 回数:
m 回 (m : 質問点対の個数)
全計算量
O( 全 Merge の計算量 + 全 Find の計算量 + その他 )
= O( (n-1)・TM + m・TF + n )
49
Merge-Find 集合と
Merge-Find 木
Merge, Find に対する
効率的なデータ構造
50
Merge-Find 集合 (MF set)
以下の操作を持った抽象データ型
Merge( A, B, C )
互いに素な集合 A および B に対して,
C := A∪B とする手続き.
A∩B=φなる集合 A, B に対する Union( A, B, C ) と同じ.
Find( x )
要素 x を含む集合を返す関数.
Initialize( A, a )
要素 a だけから成る集合 A を作る手続き
51
Merge-Find 木
MF 木 U
g
d
B
C
E
F
a
c
e
f
h
b
B = { a, b, d, g, h }
C={c}
E={e}
F={f}
MF 木 U
・ 各集合を根付き木で表現
・ 根には集合名を覚える
* : 集合名
・ 各点は親へのポインタを持つ
* : 要素
52
Merge( C, E, C )
MF 木 U
g
B
C
CE
F
a
c
ee
f
h
b
B = { a, b, d, g, h }
C={c}
E={e}
F={f}
c
d
C = { c, e }
Merge の計算量 : TM = O(1)
53
Find( d )
MF 木 U
g
d
B
C
F
a
e
f
h
b
c
B = { a, b, d, g, h }
C = { c, e }
F={f}
MF 木 U の点 d から,
親を辿り,根まで到達すれば,
そこには集合名が書かれている
Find の計算量 : TM = O( 木の高さ h(・) )
54
Merge( C, F, F )
C
F
F
e
f
f
?
c
B = { a, b, d, g, h }
C = { c, e }
F={f}
e
c
F
F = { c, e, f }
e
c
f
Find の手間が小さくなるので,
好ましい
55
Merge 操作の改良
木の高さを抑える
Find の効率化になる
56
Merge( A, B, C )
A
a
B
b
C
a
b
|A| > |B|
要素数の少ない木の根を,
もう一方の木の根の子にする
要素数が n の木の
高さは,常に O(logn)
各木の点の個数を覚えていれば,Merge の計算量 TM = O(1)
57
命題
点の個数の少ない方の木の根を,
個数が大きい方の木の根の子にするように
Merge を行うと,
どのような順序で Merge が行われても,
木の点の個数を n とすると,
できた木の高さ h(・) は高々
log n
2
58
数学的帰納法で証明
n = 1 のとき,木の高さ h(・) は 0 であり,
log2 n log2 1 0
であるから, n = 1 のとき成立する.
n < n’ のとき成立を仮定し,n = n’ の時を考える.
n = n’ の木が,Merge( A, B, C ) でできたとすると,
|A| < n, |B| < n であるから,帰納法の仮定より,
A, B の高さ h(A), h(B) は
h( A) log2 | A | log2 n
,
h( B ) log2 | B | log2 n
59
数学的帰納法で証明
一方,木 C の高さ h(C) は,
C
h(C) = max[ h(A), h(B)+1 ]
a
であるから,
一般性を失うことなく,
b
h(A)
A
|A| |B| と仮定できる.
log2 | B | 1
log2 2 | B |
max log2 n , log2 n log2 n
h(B)
B
h (C ) max log2 | A |,
max log2 | A |,
Q.E.D.
60
Find 操作の改良
木の高さを抑える
後の Find の効率化になる
均し計算量
61
Find の改良
最下位共通先祖のアルゴリズムの計算量
O( (n-1)・TM + m・TF + n )
= O( (n-1) + m・logn + n ) = O( m・logn + n )
全 Find の計算量 O( m・logn ) の削減
道の圧縮(path compression)
62
Find の改良 (道の圧縮)
Find の操作において辿った点を
全て木の根の子にする操作
B
B
a
b
g
c
d
e
x
a
c
f
Find(x)
d
x
b
g
e
f
63
Find の改良 (道の圧縮)
Find の最悪計算量 TF のオーダは変化なし
B
B
a
b
g
c
d
e
x
a
c
f
Find(x)
d
x
b
g
e
f
64
Find の改良 (道の圧縮)
しかし,全 Find 操作に要する総計算量
O(m・TF) は
O(m・logn)
O(m・α(n) )
から
になる
ここで, α(n) はアッカーマン(Ackerman)
関数の逆関数
65
Ackermann’s Function
j
アッカーマン関数 A1, j 2 :
j2
: i2
Ai,1 Ai - 1,2 Ai, j Ai - 1, Ai, j - 1 : i, j 2
A2,1 A1,2 22 4
A2,2 A1, A2,1 2
A 2 ,1
A2,3 A1, A2,2 2
A2 , 2
2 24 16
22
2
22
2
216 65,536
A2,4 A1, A2,3 2 A2,3 265,536 1020,000
A3,1 A2,2 16
A4,1 A3,2 A2, A3,1 2 A3,1 216 65,536
66
アッカーマン関数の逆関数
pseudo-inverse function of Ackermann’s function
n min i 1 | Ai,1 log2 n n, n
m
m, n mini 1 | A i, log2 n
n
n 2 Ai ,1
n 2 A1,1 2 log2 n A1,1 n 1
n 2 A2,1 22 log2 n A2,1 n 2
n2
A 3,1
2 log2 n A3,1 n 3
16
n 2 A4,1 265536 log2 n A4,1 n 4
67
アッカーマン関数の逆関数
アッカーマン(Ackerman)関数の逆関数
α(n) は
n < 216 なる n に対して, α(n) ≦ 3
216 ≦ n < 265,536
なる n に対して,
α(n) = 4 なので
実用上,定数 O(1) と考えても良い.
68
均し計算量
均し計算量(amortized time complexity)
ある操作 A の均し計算量とは,
A が何回か繰返された時,
その最悪総計算量を,
繰返し回数で割った
操作 A の 1 回当たりの計算量
69
均し計算量
MF 木の Find 操作に関しては,
Merge と Find がどのような順序で行われても,
m 回の Find に要する総計算量は,高々
O( m・α(n) ) なので,
Find 1回当たりの計算量(均し計算量)は
O(α(n) )
70
均し計算量
最下位共通先祖を求めるアルゴリズムを
効率化するには,
Find の最悪計算量を小さくするのではなく
全 Find に要する総計算量を
小さくしなければならない
すなわち,Find の均し計算量を小さくす
れば良い
71
均し計算量
最悪計算量を小さくするデータ構造は,
しばしば,複雑で,実際の計算時間が長い
均し計算量を小さくするデータ構造は,
単純で,実際の計算時間も小さくなる
ことが多い
このため,均し計算量は,
データ構造を考える上での重要な概念
72
データ構造の詳細
最下位共通先祖問題に対する
アルゴリズム実現用
73
木 T に必要なデータ構造
集合 U(・) : MF 木で実現する
Merge :
Find :
集合名を指定する
要素名を指定する
木 T = (V,E) の各点 v∈V に対して
lm_child(v) : v の長男
r_sibling(v) : v の次弟
mark(v) :
未探索,探索中,探索済みの印
集合 P(v) :
v を含む質問点対の集合
集合 U(v) :
集合名 U(v) を持つ MF 木の根
MF点 MFnode(v) : v を示す MF 木内の点
74
MF 木のデータ構造
MF 木の根が持つべきデータ
set_name : その木が表す集合の名称 U(・)
size :
その木に含まれる要素の個数
MF 木の点が持つべきデータ
parent : その点の親(根まで辿れるように)
MF 木の点用のセル
parent
set_name size
75
Merge-Find 木
MF 木 U
U(b)
U(c)
U(f)
a
e
f
g
h
b
U(b)
U(c)
U(f)
・
・
・
b 5
c 2
f 5
c
d
根には,集合名 U(v) の
v だけを書いておく
76
木 T のデータ構造
各点 v∈V に対して
lm_child(v) : 長男のセルへのポインタ
r_sibling(v) : 次弟のセルへのポインタ
mark(v) :
未探索,探索中,探索済みの印
集合 P(v) : 連結リストへのポインタ
集合 U(v) : MF 木の根のセルへのポインタ
MF点 MFnode(v) : MF 木内の点のセルへのポインタ
木 T の点用のセル
mark
lm_child
U(・)
Mfnode(・)
P(・)
r_sibling
77
木 T のデータ構造
mark U P(・)
M U ・
LmC
RSb
Mfn ・ Mfn
木T
c h・
b
d
a
c
M U ・
Mfn
e
h
M U
Mfn ・
e f ・
f
M U ・
Mfn
M U
・ Mfn ・
M U
・ Mfn ・
c h
g
M U
・ Mfn ・
P(・) 用のセル : g h ・
M U
・ Mfn
e f ・
f g
g h・
g h・
78
木 T と MF 木との関連
M U ・
Mfn ・
M U
M U ・
MfnMfn
b
d
a
c
h
M U ・
Mfn
e
f
g
MF 木
M U
・ Mfn
M U
・ Mfn ・
M U
Mfn ・
M U
・ Mfn ・
M U
M U
・ Mfn ・
Mfn
・
g 1
・
a 1
・
d 1
・
f 1
79
木 T と MF 木との関連
M U ・
Mfn ・
点 a に戻った時点
M U ・
Mfn
b
d
a
g
a
c
h
e
f
g
M U ・
Mfn
M U
・ Mfn
M U
・ Mfn ・
M U
Mfn ・
M U
・ Mfn ・
M U
・ Mfn ・
・
a 21
MF 木
g 1
・
d 1
・
f 1
80
木 T と MF 木との関連
M U ・
Mfn ・
点 a に戻った時点
d
b
d
a
g
a
c
h
e
f
g
M U ・
Mfn
M U ・
Mfn
M U
・ Mfn
M U
・ Mfn ・
M U
Mfn ・
M U
・ Mfn ・
M U
・ Mfn ・
・
a 21
MF 木
g 1
・
d 1
・
f 1
81
木 T と MF 木との関連
M U ・
Mfn ・
点 d に戻った時点
d
b
d
a
g
a
c
h
e
f
g
M U ・
Mfn
M U ・
Mfn
M U
・ Mfn
M U
・ Mfn ・
M U
Mfn ・
M U
・ Mfn ・
M U
・ Mfn ・
・
da 32
MF 木
g 1
・
d 1
・
f 1
82
木 T と MF 木との関連
M U ・
Mfn ・
点 d に戻った時点
d
b
d
a
g
a
c
h
e
f
g
M U ・
Mfn
M U ・
Mfn
M U
・ Mfn
M U
・ Mfn ・
M U
Mfn ・
M U
・ Mfn ・
M U
・ Mfn ・
・
da 31
MF 木
g 1
・
d 1
・
f 1
83
木 T と MF 木との関連
M U ・
Mfn ・
点 d に戻った時点
d
b
d
a
g
a
c
h
e
f
g
M U ・
Mfn
M U ・
Mfn
M U
・ Mfn
M U
・ Mfn ・
M U
Mfn ・
M U
・ Mfn ・
M U
・ Mfn ・
・
da 31
MF 木
g 1
・
d 1
・
f 1
84
木 T と MF 木との関連
M U ・
Mfn ・
点 h を深さ優先探索
d
b
d
a
g
a
c
h
e
f
g
M U ・
Mfn
M U ・
Mfn
M U
・ Mfn
M U
・ Mfn ・
M U
Mfn ・
h
M U
・ Mfn ・
M U
・ Mfn ・
・
d 3
MF 木
g 1
・
h 1
・
f 1
85
木 T と MF 木との関連
M U ・
Mfn ・
点 d に戻った時点
d
b
d
a
g
a
c
h
e
f
g
M U ・
Mfn
M U ・
Mfn
M U
・ Mfn
M U
・ Mfn ・
M U
Mfn ・
h
M U
・ Mfn ・
M U
・ Mfn ・
・
d 43
MF 木
g 1
・
h 1
・
f 1
86
木 T と MF 木との関連
M U ・
Mfn ・
点 d に戻った時点
d
b
d
a
g
a
c
h
e
f
g
M U ・
Mfn
M U ・
Mfn
M U
・ Mfn
M U
・ Mfn ・
M U
Mfn ・
h
M U
・ Mfn ・
M U
・ Mfn ・
・
d 4
MF 木
g 1
・
f 1
87
まとめ
オフライン最下位共通先祖問題を例に,
MF 木と均し計算量の説明をした.
また,アルゴリズムの解析と実現についても
触れた.
アルゴリズムが与えられたとき,ここで述べ
たような手順でデータ構造を構築できれば,
単位を修得!!
© Copyright 2026 ExpyDoc