• 検索結果がありません。

アルゴリズム論 (第6回)

N/A
N/A
Protected

Academic year: 2021

シェア "アルゴリズム論 (第6回)"

Copied!
33
0
0

読み込み中.... (全文を見る)

全文

(1)

アルゴリズム論

(第6回)

佐々木研(情報システム構築学講座)

講師  山田敬三

[email protected]

(2)

中間試験

11/17(

) 14:40

16:10

,共

301

講義室

各自が履修しているクラスで受験すること

(でなければ,評価されない)

座席指定あり

持ち込み:一切不可

(

鉛筆と消しゴムのみ可

)

解答時間:60分

11/24(

)

採点(参加者は

+10

点)

(3)

木構造

(4)

木構造 (Tree Structure)

グラフ

(Graph)

の一種.階層構造を持つデータを扱

う.

章や節などの構造をもつ本,ディレクトリ,など

複数のノードからなる

(5)

木構造

ルート

部分木 ノード

親 子

葉 深さ

3 2 1 0

(6)

木構造

• 二分木( Binary Tree )

すべてのノードの子が高々2の木

• 完全二分木( Complete Binary Tree )

詰められた二分木

ルートから,上から下へ

同深さでは左から右へノードを隙間なく詰めた二分木

(7)

二分木と完全木分木

(a)

二分木

(b)

完全二分木

(8)

二分木の実装

struct person { char *name;

int year;

};

struct node {

struct person *value;

struct node *child_l;

struct node *child_r;

};

親からのポインタ

左の子へのポインタ 右の子へのポインタ

(9)

完全二分木の場合

配列と簡単な計算式で実現可能

あるノード

n

に対して

親ノードは

n/2

子ノードは

2n

および

2n+1

# 1

# 2 # 3

# 4 # 5 # 6 # 7

# 8 # 9 # 1 0

# 1 # 2 # 3 # 4 # 5 # 6 # 7 # 8 # 9 # 1 0

(10)

二分探索木

(11)

二分探索木

Binary Search Tree

ある検索キーを与えると,それに対応する値を検索可能

あるノード

x

に対して

左部分木の各ノードのキーは

x

のキーより小さい.

右部分木の各ノードのキーは

x

のキーより大きい.

二分探索木の探索は,その構造を利用する.

二分探索木の操作(挿入,削除など)は,

データ構造を保存することが重要.

(12)

ノードの探索

Minks: 1985

Cindy: 1983 Rady:1998

Bridget: 1982 Luther:1989 Minuet:1978 Ruby:1995

Jack:1995 Maroon: 1998Maroon: 1998 Tiki:1982 Maroon を検索

(13)

ノードの追加

Minks: 1985

Cindy: 1983 Rady:1998

Bridget: 1982 Luther:1989 Minuet:1978 Ruby:1995

Jack:1995 Maroon: 1998 Tiki:1982

Elpe:1982

Elpe:1982 を追加

(14)

ノードを探索する関数

struct node *search_node(struct node *pointer, c har *key);

• 見つかったノードへのポインタを返す

• ノードへのポインタと探索用のキーを引数

(15)

ノードを探索する関数

1.

引数として与えられたポインタが

NULL

な らば、見つからなかったとして

NULL

を返 す

if(pointer

の示す先が

NULL)

{

NULL

を返す

; }

2.

値が探索対象だったら、そのノードへのポ インタを返す

if(pointer

の示す先の値がキー

) { pointer

の値を返す

;

}

(16)

ノードを探索する関数

3.

ポインタの示す先の値が探索対象より大きければ

(探索対象のほうが小さければ)左子部分木を再 帰的に探索、小さければ右子部分木を再帰的に探 索

if(pointer の示す値が対象より大きい ) { 左の子部分木を探した結果を返す ;

} else {

右の子部分木を探した結果を返す ;

}

二分木

(17)

ノードの探索

Minks: 1985

Cindy: 1983 Rady:1998

Bridget: 1982 Luther:1989 Minuet:1978 Ruby:1995

Jack:1995 Maroon: 1998Maroon: 1998 Tiki:1982 Maroon を検索

(18)

ノードを追加する関数

void add_node(struct node **pointer, struct node *new_node)

• ノードの追加位置の候補を示すポインタへのポ インタと、追加するノードへのポインタを引数

if(*pointer

の示す先が

NULL) {

*pointer

に新規ノードへのポインタを代入

; }

1. 追加位置の候補を示すポインタが

NULL なら追加

(19)

ノードを追加する関数

2.

空いてなければ、そのノードの値と新規ノードを 比較し、新規ノードの値が小さければ左の子、大 きければ右の子を調べる

if(*pointer

の示す値より新規ノードが小さ い

) {

左の部分木に対し追加位置を調べる

; } else {

右の部分木に対し追加位置を調べる

; }

(20)

ノードの追加

Minks: 1985

Cindy: 1983 Rady:1998

Bridget: 1982 Luther:1989 Minuet:1978 Ruby:1995

Jack:1995 Maroon: 1998 Tiki:1982

Elpe:1982

Elpe:1982 を追加

(21)

トラバーサル

二分探索木のすべてのノードを訪問

二分木の構造に沿った処理に使用

二分木を評価する

再帰的な処理

(例)全ノードの表示

訪れたノードを表示する処理をどこに置くかで

3

種類

(22)

行きがけ順

先順:

Preorder Traversal

1.

ノードの表示

2.

左の部分木を走査する再帰呼出

3.

右の部分木を走査する再帰呼出

(23)

通りがけ順

中順:

Inorder Traversal

1.

左の部分木を走査する再帰呼出

2.

ノードの表示

3.

右の部分木を走査する再帰呼出

(24)

帰りがけ順

後順:

Postorder Traversal

1.

左の部分木を走査する再帰呼出

2.

右の部分木を走査する再帰呼出

3.

ノードの表示

(25)

トラバースの結果

Pre-order: 1 2 4 5 3 6 7 In-order: 4 2 5 1 6 3 7 Post-order: 4 5 2 6 7 3 1

1

2 3

4 5 6 7

(26)

完全にバランスした二分木

(27)

バランスのよい2分木

2分木はバランスしていることが望ましい.

0

-バランスとは

-2分探索木と連結リストとの比 較

10

20

30

40

(28)

完全にバランスした木

全てのノードにおいて,その左部分木と右部分木で  それぞれのノードの数が高々1違う木.

完全にバラン

ス 高さがバランス

(AVL

)

(29)

変換

2分木から「完全にバランスした2分木」への変換

読み込むデータが昇順で与えられている.

データの数があらかじめわかっている.

1: node* pbtree(int n) {

2: int nleft, nright, nleftplusright

= n - 1;

3: node* p;

4: if (n == 0) { return NULL; } 5: nleft = nleftplusright / 2;

6: nright = nleftplusright - nleft;

7: p = (node*)malloc(sizeof(node));

8: p->left = pbtree(nleft);

9: scanf("%d", &p->num);

10: p->right = pbtree(nright);

11: return p;

12: }

typedef struct Node { int num;

struct Node *left,

*right;

} node;

(30)

2分探索木(データ数:10)

15

18 16

12

19

17 20

11 13

14

(31)

情報システムへの応用

データ:個人名と数値(電話番号,登録番号など)

1.

ファイルから全てのデータを読み込み,

完全にバランスした2分探索木を生成する.

(.L) 2.

指定した名前のデータを探索する.

(<name> ?)

3.

新しいデータを追加する.

(<name>

<value>)

4.

指定したデータを削除する.

(<name> /)

5.

指定したデータの数値を変更する.

(<name>

<value>)

6.

全てのデータをファイルにセーブする.

(.S) 7.

全てのデータをアルファベット順に表示する.

(.P)

P.175

~ ソースファイル :

infsys2.c

(32)

問題

下記の

8

個のデータに対して,関数

pbtree

を実行 したときの,完全にバランスした

2

分木を答えなさ い.

1, 2, 3, 4, 5, 6, 7, 8

(33)

2分探索木(データ数: 8 )

4

6 5

2

7

8

1 3

参照

関連したドキュメント

- ImageStract* nm30_retrieve_frame (void) 取得した映像フレームへのポインタを返す 戻り値 : 映像フレームへのポインタ(SSK.h で定義) ・映像フレーム情報構造体定義

構造体へのポインタ

終点(ノード 5 )の最短経路長が確定した時点で 終了.

new_cell=(struct cell *)malloc (sizeof(struct

new_cell=(struct cell *)malloc (sizeof(struct

new_cell=(struct cell *)malloc (sizeof(struct

new_cell=(struct cell *)malloc (sizeof(struct

new_cell=(struct cell *)malloc (sizeof(struct