二分探索木編

Download Report

Transcript 二分探索木編

情報システム基盤学 基礎1
アルゴリズムとデータ構造
Elements of Information
Systems Fundamentals1
アルゴリズムとデータ構造 第3回
木(Tree)と
2分探索木(Binary search tree)
1
目次: 今日やること



木構造
木の深さ優先探索,幅優先探索
2分木・2分探索木




2分探索
頂点の挿入
頂点の削除
木の頂点の番号づけ
4
木構造
木構造:上から下へ枝分かれした構造
r
:頂点(点)
:辺
a
e
b
f
k
g
l
n
h
c
i
d
j
m
木(根つき木)の例
:根
親と子
葉と内点
祖先と子孫
頂点 x を根とする部分木
深さ
5
木構造
木構造:上から下へ枝分かれした構造
:頂点(点)
r
:辺
e
k
a
b
f
h
g
l
n
c
i
d
j
:根
親と子
隣接する2頂点のうち,
・根に近い方 → 親
・根から遠い方 → 子
m
木(根つき木)の例
6
木構造
木構造:上から下へ枝分かれした構造
:頂点(点)
r
:辺
e
k
a
b
f
h
g
l
n
c
i
d
j
:根
葉と内点
葉:
子をもたない頂点
m
内点:
葉以外の頂点
木(根つき木)の例
7
木構造
木構造:上から下へ枝分かれした構造
:頂点(点)
r
:辺
a
b
c
d
:根
子孫と祖先
e
f
k
g
l
n
h
i
j
m
頂点x の祖先:
頂点 x から根へのパス上に
存在する点(x は含まない)
頂点x の子孫:
頂点 x を祖先として含む頂点
木(根つき木)の例
8
木構造
木構造:上から下へ枝分かれした構造
:頂点(点)
r
:辺
a
b
c
d
:根
頂点x を根とする部分木
e
f
k
g
l
h
i
j
頂点x を根とする部分木:
頂点 x と x の子孫からなる木
m
x
n
木(根つき木)の例
9
木構造
木構造:上から下へ枝分かれした構造
深さ0
r
:頂点(点)
:辺
a
b
深さ1
d
c
:根
深さ
e
f
k
g
l
n
h
m
i
j
深さ2
深さ3
深さ4
高さ“5”の木の例
頂点 x の深さ:
頂点 x から根へのパ
ス上にある辺の数
x
10
まとめ: 木構造について見てきた
木構造:上から下へ枝分かれした構造
r
:頂点(点)
:辺
a
e
b
f
k
g
l
n
h
c
i
d
j
m
木(根つき木)の例
:根
親と子
葉
祖先と子孫
頂点 x を根とする部分木
深さ
11
木の深さ優先探索
現ノードAの最左の子ノードから順に再帰降下する探索
A
B
C
D
Search(A)
1. Mark A;
2. if ( A is leaf )
return;
3. Search(B);
4. Search(C);
5. Search(D);
深さ優先探索
(depth-first search)
12
2
例:12, 5, 2, 9, 18, 15, 17, 19
18
5
9
19
15
17
12
木の幅優先探索
現ノードAの子ノードを全て検査してから次の深さの
子ノードを順に検査する探索
A
B
C
例:12, 5, 18, 2, 9, 15, 19, 17
12
D
18
5
2
9
19
15
17
13
木の幅優先探索
現ノードAの子ノードを全て検査してから次の深さの
子ノードを順に検査する探索
A
C
B
E
F
D
G
H
BFS(A)
1. enq(Q, A);
1. While (Q != Φ) do
2.
q = deq(Q);
3.
mark q;
4.
enq all children of q;
5. end
A, B, C, D, E, F, G, H
目次: 今日やること


木構造
2分木・2分探索木





2分探索
頂点の挿入
頂点の削除
木の頂点の番号づけ
トライ・サフィックス木(の紹介だけ)
19
2分木
2分木の定義
子の数が高々2個の木
(ちょっと特殊な木)
木
2分木
20
2分木
2分木の定義
子の数が高々2個の木
(ちょっと特殊な木)
2分木の例
その1
2分木の例
その2:完全2分木
(内点は2個の子をもつ)
2分木の例
その3:これも2分木
21
完全2分木の頂点数について
完全2分木の頂点数
高さ d の完全2分木 は 2d – 1 個の頂点をもつ
注意: 高さ = “最大深さ + 1”と考えてください
(左下の木の高さは“4”)
1 = 20
2倍
2 = 21
2倍
4 = 22
2倍
8=
23
各点は, ちょうど2個の子をもつので
1つ深くなるごとに頂点数は2倍
高さ d の完全2分木 の
頂点の個数を n とすると
d-1
n =
∑ 2i
i=0
= 2d – 1
22
目次: 今日やること


木構造
2分木・2分探索木





2分探索
頂点の挿入
頂点の削除
木の頂点の番号づけ
トライ・サフィックス木(の紹介だけ)
23
2分探索木
2分探索木とは…
2分木の構造をデータ構造として利用したもの
各点にキー(= 自然数)を1つ格納
左の子を根とする部分木に, より小さなキーを格納
右の子を根とする部分木に, より大きなキーを格納
2分探索木の例:
2分探索木のイメージ:
18
10
5
3
小
35
13
7
23
20
x
46
50
xより小
大
xより大
24
2分探索木の実装
こんな
感じ
35
2分探索木の表し方の例
頂点を構造体で表す
struct vertex {
int key;
struct vertex *p;
struct vertex *left;
struct vertex *right;
};
フィールドの構成:
・ キー フィールド
・ 親フィールド
・ 左の子 フィールド
・ 右の子 フィールド
“キー = 自然数”と考えてね!!
18
18
35
10
5
3
13
7
23
20
10
46
35
35
13
23
50
3
7
20
46
50
25
目次: 今日やること


木構造
2分木・2分探索木





2分探索
頂点の挿入
頂点の削除
木の頂点の番号づけ
トライ・サフィックス木(の紹介だけ)
26
2分探索
(= 2分探索木上での探索)
問題
キー k が与えられたとき, 2分探索木上で k を探したい
アルゴリズム
キー7の探索:水色網かけ
キー28の探索:ピンク網かけ
(根からスタートして)
現在の頂点のキーと k を比較
繰
り
返
し
両者は等しい → 現在の頂点を返し, 終了
キー k の方が大きい → 右の子へ移動
キー k の方が小さい → 左の子へ移動
(子がなければNULLを返す)
18
35
10
5
3
13
7
23
20
46
50
27
2分探索: 擬似コード
TREE-SEARCH(x,k)
1 if x = NULL or k = key[x]
2
then return x
3 if k < key[x]
4
then return TREE-SEARCH(left[x],k)
5
else return TREE-SEARCH(right[x],k)
x: 2分探索木上の頂点
x
key[x]
key[x]: 頂点 x がもつキー
left[x]: 頂点 x の左の子
right[x]: 頂点 x の右の子
key[x]
より小
key[x]
より大
28
目次: 今日やること


木構造
2分木・2分探索木





2分探索
頂点の挿入
頂点の削除
木の頂点の番号づけ
トライ・サフィックス木(の紹介だけ)
29
2分探索木へデータを挿入
2分探索木へのデータ挿入
2分探索木へ点を1つ追加する
(※2分探索木の性質が失われないように!)
12
根
13 を挿入
18
5
2
12
9
19
15
17
根
18
5
2
9
19
15
13
17
30
2分探索木へデータを挿入
2分探索木へのデータ挿入
2分探索木へ点を1つ追加する
(※2分探索木の性質が失われないように!)
アルゴリズム
根
12
(根からスタートして)
現在の頂点のキーと k を比較
繰
り
返
し
18
5
キー k の方が大きい → 右の子へ移動
右の子がNULLならば, ここに挿入
2
9
19
15
キー k の方が小さい → 左の子へ移動
左の子がNULLならば, ここに挿入
13
17
31
挿入の擬似コード
TREE-INSERT(k)
1 Creat a new vertex z
with key[z] ← k, left[x] ← NULL, right[x] ← NULL
2 y ← NULL, x ← root
3 while x ≠ NULL
4
5
6
7
8
9
10
11
do y ← x
if key[z] < key[x]
root: 2分探索木の根
x: 2分探索木上の頂点
p[x]: 頂点 x の親
key[x]: 頂点 x がもつキー
left[x]: 頂点 x の左の子
then x ← left[x]
right[x]: 頂点 x の右の子
else x ← right[x]
y = NULL
xy 12 根(= root)
k = 13 の例:
p[z] ← y
if y = NULL // 2分木が空だったとき
xy
18
5
then root ← z
else if key[z] < key[y]
12
then left[y] ← z
13
else right[y] ← z
2
x
9
15
y
x
13
19
32
17
目次: 今日やること


木構造
2分木・2分探索木





2分探索
頂点の挿入
頂点の削除
木の頂点の番号づけ
トライ・サフィックス木(の紹介だけ)
33
2分探索木からデータを削除
2分探索木からデータ削除
2分探索木へ点を1つ削除する
(※2分探索木の性質が失われないように!)
根(= root)
根(= root)
15
5
16
3
1
15
10
6
13 を削除
20
12
2
5
13
18
16
3
23
1
2
10
6
7
20
12
18
23
なくなってる!!!
7
34
削除の難しさ
2分探索木からデータ削除
2分探索木へ点を1つ削除する
(※2分探索木の性質が失われないように!)
探索・挿入と比べるとちょっと難しい
ここの穴埋め
どうする!?
15
5
3
1
15
16
10
6
5 を削除
20
12
2
16
13
18
3
23
1
20
12
2
10
13
18
23
6
35
ポイントとなるアイデア
2分探索木からデータ削除
2分探索木へ点を1つ削除する
(※2分探索木の性質が失われないように!)
探索・挿入と比べるとちょっと難しい
ポイント
子の個数で3つに場合分けして考える
Case 1: 子の個数が0
Case 2: 子の個数が1
Case 3: 子の個数が2
36
Case 1: 子の個数が0(簡単!)
削除の仕方
(削除したい頂点を z とする)
1. z を削除
根(= root)
根(= root)
15
5
16
3
1
15
10
6
13 を削除
20
12
2
5
13
18
16
3
23
1
20
12
2
10
18
23
6
7
7
37
Case 2: 子の個数が1(これも簡単!)
削除の仕方
(削除したい頂点を z とする)
1. z の子と z の親を繋げる
2. z を削除
根(= root)
根(= root)
15
5
16
3
1
15
10
6
16 を削除
20
12
2
5
13
18
23
20
3
1
12
2
18
23
10
6
7
7
38
Case 3: 子の個数が2(ちょいムズ)
方針: z を削除し、 z のsuccessor に穴埋めさせる
削除の仕方
(削除したい頂点を z とする)
1. key[z] の次に大きいキーをもつ頂点を探す(y とする)
2. y をいったん削除
z のsuccessor
3. x を y に置き換える
15
5
3
1
15
16
12
2
10
6
6
5 を削除
3
20
13
18
23
1
16
12
2
10
20
13
18
23
7
7
(削除後も, ちゃーんと2分木の性質を満たしてます)
39
目次: 今日やること


木構造
2分木・2分探索木




2分探索
頂点の挿入
頂点の削除
木の頂点の番号づけ
40
木の頂点の番号づけ(3種類)
1. preorder(先行順)
深さ優先探索で, 訪れた順に番号づけ
(課題に出します)
例:12, 5, 2, 9, 18, 15, 17, 19
2. inorder(中間順)
深さ優先探索で, 左子から戻ってきたときに番号づけ
(注意:2分木だけに定義される番号づけです)
12
例: 2, 5, 9, 12, 15, 17, 18, 19
深さ優先探索で, 最後に去っていく順
に番号づけ
例:2, 9, 5, 17, 15, 19, 18, 12
18
5
3. postorder(後行順)
2
9
19
15
17
41
木の頂点の番号づけ(3種類)
1. preorder(先行順)
深さ優先探索で, 訪れた順に番号づけ
例:12, 5, 2, 9, 18, 15, 17, 19
A
B
C
Search(A)
1. Mark A;
2. if ( A is leaf )
return;
3. Search(B);
4. Search(C);
(課題に出します)
深さ優先探索
(depth-first search)
12
18
5
2
9
19
15
17
42
(課題に出します)
Search(A)
1. Search(B);
2. Mark A;
3. Search(C);
A
// modify it
// if A is a leaf.
12
B
C
18
5
2
9
19
15
17
43
(課題に出します)
Search(A)
1. Search(B);
2. Search(C);
3. Mark A;
A
// modify it
// if A is a leaf.
12
B
C
18
5
2
9
19
15
17
44
第1回 レポート課題
出題日: 2013/May 1
締切日: 2013/May 15
課題1
O(n^2) sort, O(n lg n) sort を作り,n = 10 から 10^4 まで
実行時間を測定してみよ.整数配列のsort で良い.
** copy paste でも今回だけは良いが 擬似コードで
分かれば 自由に 書けるはずだ.
Free Yourself
でも 行き詰ったら 基礎1TA メーリングリストへ.
[email protected]
提出: IS棟2F事務室ポストへ.コードと測定結果をA4印刷.
第2回 レポート課題
.
課題2. 2分探索木の全キーを preorder で出力するプログラムを作成してくださ
い. 余裕のある人は inorder, postorder についても同様にプログラムを
作成してください。
12
Hint: 再帰呼出を使うと
楽に作れる
18
5
2
9
15
12, 5, 2, 9, 18, 15, 17, 19
19
17
左の2分木の全キーを
preorderで出力
出題: H25年5月1日
締切: 同年 5月22日まで.
提出先:IS棟2F事務ポスト (コード,実行結果をA4
用紙に出力,簡単にコメントをつける)
このスライドは2010年に山中先生が
作成したものを今回 大森が改訂しました.
木の深さ優先探索,幅優先探索は独自作成
です.
これから面白いところで 交代.
アルゴリズムの設計と解析(上)(下)
Aho, Hopcroft, Ullman, サイエンス社
が ほぼ全ての古典的教科書の源.
MIT本(コルメン著) – 分厚い.翻訳が下手.
Knuth本 – 難しいがBibleなので仕方ない.
基本とは難しいものだと分かる.
「データ構造」(星守 著,昭晃堂) -数理工学科向きのアルゴリズム講義の
教科書. 見た目よりも お勧め.
47