Taro-2分探索木Ⅱ(公開版).jtd

Similar documents
Taro-2分探索木Ⅰ(公開版).jtd

Taro-リストⅠ(公開版).jtd

Taro-リストⅢ(公開版).jtd

Taro-スタック(公開版).jtd

Microsoft PowerPoint - kougi10.ppt

memo

Microsoft PowerPoint - 05.pptx

Microsoft Word - no206.docx

Taro-再帰関数Ⅲ(公開版).jtd

Taro-再帰関数Ⅱ(公開版).jtd

Microsoft Word - 13

memo

Microsoft PowerPoint - kougi11.ppt

Taro-最大値探索法の開発(公開版

第2回

バイオプログラミング第 1 榊原康文 佐藤健吾 慶應義塾大学理工学部生命情報学科

Taro-ポインタ変数Ⅰ(公開版).j

PowerPoint プレゼンテーション

PowerPoint プレゼンテーション

Taro-プログラミングの基礎Ⅱ(公

プログラミングI第10回

Microsoft PowerPoint - kougi9.ppt

[Problem F] 古い記憶 良さそうな方法は思いつかなかった アイディア募集中!!! かなり強引に解いている 各判定データに対して 30 秒程度かかる 元の文章と改ざん文章の関係を考える ウィルス感染の可能性は高々 2 回であり 各々の感染では 1 文字削除 1 文字追加 1 文字変更が行われ

Microsoft Word - NonGenTree.doc

二分木の実装

Microsoft PowerPoint - algo ppt [互換モード]

Microsoft Word - 12

Microsoft PowerPoint - 06.pptx

Microsoft PowerPoint - algo ppt [互換モード]

< F2D837C E95CF CF68A4A94C5816A2E6A>

alg2015-6r3.ppt

Microsoft PowerPoint - 7.pptx

untitled

I. Backus-Naur BNF : N N 0 N N N N N N 0, 1 BNF N N 0 11 (parse tree) 11 (1) (2) (3) (4) II. 0(0 101)* (

C言語によるアルゴリズムとデータ構造

文字数は1~6なので 同じ本数の枝を持つパスで生成される呪文の長さは最大で6 倍の差がある 例えば 上図のようなケースを考える 1サイクル終了した時点では スター節点のところに最強呪文として aaaaaac が求まる しかしながら サイクルを繰り返していくと やがてスター節点のところに aaaaaa

PowerPoint プレゼンテーション

I ASCII ( ) NUL 16 DLE SP P p 1 SOH 17 DC1! 1 A Q a q STX 2 18 DC2 " 2 B R b

II 3 yacc (2) 2005 : Yacc 0 ~nakai/ipp2 1 C main main 1 NULL NULL for 2 (a) Yacc 2 (b) 2 3 y

LIFO(last in first out, ) 1 FIFO(first in first out, ) 2 2 PUSH POP : 1

始めに, 最下位共通先祖を求めるための関数 LcaDFS( int v ) の処理を記述する. この関数は値を返さない再帰的な void 関数で, 点 v を根とする木 T の部分木を深さ優先探索する. 整数の引数 v は, 木 T の点を示す点番号で, 配列 NodeSpace[ ] へのカーソル

memo

I. Backus-Naur BNF S + S S * S S x S +, *, x BNF S (parse tree) : * x + x x S * S x + S S S x x (1) * x x * x (2) * + x x x (3) + x * x + x x (4) * *

cp-7. 配列

Microsoft Word - Cプログラミング演習(11)

Microsoft Word - 3new.doc

C プログラミング演習 1( 再 ) 2 講義では C プログラミングの基本を学び 演習では やや実践的なプログラミングを通して学ぶ

第12回:木構造

今回のプログラミングの課題 ( 前回の課題で取り上げた )data.txt の要素をソートして sorted.txt というファイルに書出す ソート (sort) とは : 数の場合 小さいものから大きなもの ( 昇順 ) もしくは 大きなものから小さなもの ( 降順 ) になるよう 並び替えること

kiso2-09.key

次に示す数値の並びを昇順にソートするものとする このソートでは配列の末尾側から操作を行っていく まず 末尾の数値 9 と 8 に着目する 昇順にソートするので この値を交換すると以下の数値の並びになる 次に末尾側から 2 番目と 3 番目の 1

PowerPoint Presentation

r07.dvi

プログラミング基礎

ohp07.dvi

Microsoft PowerPoint - C言語の復習(配布用).ppt [互換モード]

C のコード例 (Z80 と同機能 ) int main(void) { int i,sum=0; for (i=1; i<=10; i++) sum=sum + i; printf ("sum=%d n",sum); 2

Taro-数値計算の基礎Ⅱ(公開版)

Microsoft Word - Cプログラミング演習(10)

Microsoft Word - no205.docx

Microsoft Word - 第5回 基本データ構造2(連結リスト).doc

Prog1_15th

memo

Microsoft Word - Cプログラミング演習(12)

:30 12:00 I. I VI II. III. IV. a d V. VI

Microsoft Word - no15.docx

:30 12:00 I. I VI II. III. IV. a d V. VI

memo

(search: ) [1] ( ) 2 (linear search) (sequential search) 1

第2回

PowerPoint Presentation

2018年度「プログラミング言語」配布資料 (12)

PowerPoint Presentation

プログラミング方法論 II 第 14,15 回 ( 担当 : 鈴木伸夫 ) 問題 17. x 座標と y 座標をメンバに持つ構造体 Point を作成せよ 但し座標 は double 型とする typedef struct{ (a) x; (b) y; } Point; 問題 18. 問題 17 の

memo

main

II ( ) prog8-1.c s1542h017%./prog8-1 1 => 35 Hiroshi 2 => 23 Koji 3 => 67 Satoshi 4 => 87 Junko 5 => 64 Ichiro 6 => 89 Mari 7 => 73 D

Taro-ファイル処理(公開版).jtd

memo

Microsoft PowerPoint - 4.pptx

/* do-while */ #include <stdio.h> #include <math.h> int main(void) double val1, val2, arith_mean, geo_mean; printf( \n ); do printf( ); scanf( %lf, &v

P05.ppt

Microsoft PowerPoint - 計算機言語 第7回.ppt

Taro-再帰関数Ⅰ(公開版).jtd

gengo1-11

Taro-ビット処理(公開版).jtd

memo

memo

PowerPoint Presentation

Microsoft PowerPoint - 説明3_if文switch文(C_guide3)【2015新教材対応確認済み】.pptx

Microsoft PowerPoint - lec4.ppt

プログラミング基礎

PowerPoint Template

() / (front end) (back end) (phase) (pass) 1 2

Microsoft PowerPoint - lec10.ppt

超初心者用

( ) ( ) 30 ( ) 27 [1] p LIFO(last in first out, ) (push) (pup) 1

新・明解C言語で学ぶアルゴリズムとデータ構造

Microsoft Word - Cプログラミング演習(9)

‚æ4›ñ

Transcription:

2 分探索木 Ⅱ 0. 目次 5. 2 分探索木の操作 5. 1 要素の探索 5. 2 直前の要素の探索 5. 3 直後の要素の探索 5. 4 要素の削除 5. 5 問題 問題 1-1 -

5. 2 分探索木の操作 5. 1 要素の探索 要素 44 の探索 (1) 要素 と 44 を比較して 左部分木をたどる (2) 要素 33 と 44 を比較して 右部分木をたどる (3) 要素 44 を見つけた 要素 68 の探索 (1) 要素 と 68 を比較して 右部分木をたどる (2) 要素 99 と 68 を比較して 左部分木をたどる (3) 要素 77 と 68 を比較して 左部分木をたどる (4) 要素 66 と 68 を比較して 右部分木をたどる (5) 右部分木は空なので 要素 68 を見つけられなかった - 2 -

プログラム 再帰版 ( bt511.c) 1 /* << bt511.c >> */ 2 #include <stdio.h> 3 #include <stdlib.h> 4 struct NODE { 5 int info; /* 節点がもつデータ */ 6 struct NODE *left; /* 左の子節点を指すポインタ */ 7 struct NODE *right; /* 右の子節点を指すポインタ */ 8 }; 9 struct NODE *mktree(); 10 struct NODE *search(struct NODE *p, int x); 11 12 int main() { 13 int x; 14 struct NODE *root, 15 *pos; 16 17 /* 2 分探索木の作成 */ 18 root = mktree(); 19 20 /* 探索 */ 21 while( 1 ) { 22 /* 探索データ xの読み込み */ 23 scanf("%d",&x); 24 if( x <= 0 ) { break; } 25 printf(" 探索データ : %d ",x); 26 27 /* データ xを指定し探索 pos: 要素 xの位置 */ 28 pos = search(root->left,x); 29 if( pos!= NULL ) { 30 printf("%d 見つかりました \n",pos->info); 31 } else { 32 printf(" 見つかりません \n"); 33 } 34 } 35 } 36 37 /* 探索 */ 38 struct NODE *search(struct NODE *p, int x) { 39 struct NODE *q; /* q: 要素 xの位置 */ 40 41 if( p == NULL ) { return NULL; } 42 43 /* 要素 xを見つけた場合 */ 44 if( x == p->info ) { return p; } 45 46 /* 要素 xが見つからない場合 */ 47 if( x < p->info ) { 48 /* 左部分木を探索する */ - 3 -

49 q = search(p->left,x); 50 } else { 51 /* 右部分木を探索する */ 52 q = search(p->right,x); 53 } 54 return q; } 実行結果 % cc bt511.c % a.out 0 44 探索データ : 44 44 見つかりました 68 探索データ : 68 見つかりません 0-4 -

5. 2 直前の要素の探索 直前の要素の要素の探索を行う 2 分探索木において 直前の要素は 離れた位置にある たとえば において の直前の要素 44 は の左部分木にあり 66 の直前の要素 は 親をたどった先にある すなわち 直前の要素は 指定した要素に左部分木がある場合 左部分木の中で最大の要素 左部分木がない場合 親をたどっていき 最初に右部分木へ分岐した辺の親節点である 要素 の直前の要素 44 の探索 1 2 (1) 要素 を見つけるまで 2 分探索木をたどる (2) 要素 を見つけたら 左部分木があるかないか調べ ある場合 左部分木の節点に移動し その木の右部分木を最後までたどる 最後の節点に求める要素がある ない場合 親節点をたどり 最初に右部分木へ分岐した辺の親節点に求める要素がある - 5 -

要素 66 の直前の要素 の探索 3 2 1 (1) 要素 66 を見つけるまで 2 分探索木をたどる (2) 要素 66 を見つけたら 左部分木があるかないか調べ ある場合 左部分木の節点に移動し その木の右部分木を最後までたどる 最後の節点に求める要素がある ない場合 親節点をたどり 最初に右部分木へ分岐した辺の親節点に求める要素がある 手順は 1,2,3 とたどり親節点を探す代わりに 要素 66 を見つける途中で右部分木へ移動するときに 親節点の位置を記憶しておく - 6 -

プログラム 再帰版 ( bt521.c) 1 /* << bt521.c >> */ 2 #include <stdio.h> 3 #include <stdlib.h> 4 struct NODE { 5 int info; /* 節点がもつデータ */ 6 struct NODE *left; /* 左の子節点を指すポインタ */ 7 struct NODE *right; /* 右の子節点を指すポインタ */ 8 }; 9 struct NODE *mktree(); 10 struct NODE *before(struct NODE *root, int x,struct NODE *t); 11 12 int main() { 13 int x; 14 struct NODE *root, 15 *pos; 16 17 /* 2 分探索木の作成 */ 18 root = mktree(); 19 20 while( 1 ) { 21 /* データ xの読み込み */ 22 scanf("%d",&x); 23 if( x <= 0 ) { break; } 24 printf(" データ : %d ",x); 25 26 /* データ xを指定し探索する pos: 直前の要素の位置 */ 27 pos = before(root->left,x,null); 28 if( pos!= NULL ) { 29 printf(" 直前のデータ : %d\n",pos->info); 30 } else { 31 printf(" 直前のデータなし \n"); 32 } 33 } 34 } 35 36 /* 直前のデータを求める */ 37 struct NODE *before(struct NODE *p, int x, struct NODE *t) { 38 struct NODE *q; /* q: 直前の要素の位置 */ 39 40 if( p == NULL ) { return NULL; } 41 /* 要素 xを見つけた場合 */ 42 if( x == p->info ) { 43 if( p->left!= NULL ) { 44 /* 左部分木がある場合 */ 45 p = p->left; 46 while( p->right!= NULL ) { p = p->right; } 47 return p; 48 } else { - 7 -

49 /* 左部分木がない場合 */ 50 return t; 51 } 52 } 53 54 /* 要素 xが見つからない場合 */ if( x < p->info ) { 56 /* 左部分木へ進む */ 57 q = before(p->left,x,t); 58 } else { 59 /* 右部分木に進んだとき 節点 pを保存する */ 60 q = before(p->right,x,p); 61 } 62 return q; 63 } 実行結果 % cc bt521.c %./a.out 0 11 データ : 11 直前のデータなし 22 データ : 22 直前のデータ : 11 33 データ : 33 直前のデータ : 22 44 データ : 44 直前のデータ : 33 データ : 直前のデータ : 44 66 データ : 66 直前のデータ : 77 データ : 77 直前のデータ : 66 88 データ : 88 直前のデータ : 77 99 データ : 99 直前のデータ : 88 0-8 -

5. 3 直後の要素の探索 直後の要素の探索を行う 2 分探索木において 直前及び直後の要素は 離れた位置にある たとえば において 44 の直後の要素 は 親をたどった先にあり の直後の要素 66 は の右部分木にある すなわち 直後の要素は 指定した要素に右部分木がある場合 右部分木の中で最小の要素 右部分木がない場合 親をたどり 最初に左部分木へ分岐した辺の親節点である 要素 の直後の要素 66 の探索 1 2 3 (1) 要素 を見つけるまで 2 分探索木をたどる (2) 要素 を見つけたら 右部分木があるかないか調べ ある場合 右部分木の節点に移動し その木の左部分木を最後までたどる 最後の節点に求める要素がある ない場合 親節点をたどり 最初に左部分木へ分岐した辺の親節点に求める要素がある - 9 -

要素 44 の直後の要素 の探索 2 1 (1) 要素 44 を見つけるまで 2 分探索木をたどる (2) 要素 44 を見つけたら 右部分木があるかないか調べ ある場合 右部分木の節点に移動し その木の左部分木を最後までたどる 最後の節点に求める要素がある ない場合 親節点をたどり 最初に左部分木へ分岐した辺の親節点に求める要素がある 手順は 1,2 とたどり親節点を探す代わりに 要素 44 を見つける途中で左部分木へ移動するときに 親節点の位置を記憶しておく - 10 -

プログラム 再帰版 ( bt531.c) 直後のデータを求めるプログラム 1 /* << bt531.c >> */ 2 #include <stdio.h> 3 #include <stdlib.h> 4 struct NODE { 5 int info; /* 節点がもつデータ */ 6 struct NODE *left; /* 左の子節点を指すポインタ */ 7 struct NODE *right; /* 右の子節点を指すポインタ */ 8 }; 9 struct NODE *mktree(); 10 struct NODE *after(struct NODE *root, int x,struct NODE *t); 11 12 int main() { 13 int x; 14 struct NODE *root, 15 *pos; 16 17 /* 2 分探索木の作成 */ 18 root = mktree(); 19 20 while( 1 ) { 21 /* データの読み込み */ 22 scanf("%d",&x); 23 if( x <= 0 ) { break; } 24 printf(" データ : %d ",x); 25 26 /* データ xを指定し探索する pos: 直後の要素の位置 */ 27 pos = after(root->left,x,null); 28 if( pos!= NULL ) { 29 printf(" 直後のデータ : %d\n",pos->info); 30 } else { 31 printf(" 直後のデータなし \n"); 32 } 33 } 34 } 35 36 /* 直後のデータを求める */ 37 struct NODE *after(struct NODE *p, int x, struct NODE *t) { 38 struct NODE *q; 39 40 if( p == NULL ) { return NULL; } 41 42 /* 要素 xを見つけた場合 */ 43 if( x == p->info ) { 44 if( p->right!= NULL ) { 45 /* 右部分木がある場合 */ 46 p = p->right; 47 while( p->left!= NULL ) { 48 p = p->left; - 11 -

49 } 50 return p; 51 } else { 52 /* 右部分木がない場合 */ 53 return t; 54 } } 56 57 /* 要素 xが見つからない場合 */ 58 if( x < p->info ) { 59 /* 左部分木に進んだとき 節点 pを保存する */ 60 q = after(p->left,x,p); 61 } else { 62 /* 右部分木に進む */ 63 q = after(p->right,x,t); 64 } 65 return q; 66 } - 12 -

実行結果 % cc bt531.c %./a.out 0 11 データ : 11 直後のデータ : 22 22 データ : 22 直後のデータ : 33 33 データ : 33 直後のデータ : 44 44 データ : 44 直後のデータ : データ : 直後のデータ : 66 66 データ : 66 直後のデータ : 77 77 データ : 77 直後のデータ : 88 88 データ : 88 直後のデータ : 99 99 データ : 99 直後のデータなし 0-13 -

5. 4 要素の削除 2 分探索木から要素を削除する方法を考察する 考え方 2 分探索木から 指定した要素を削除する 次の 4 つの場合が考えられる ( 場合 1 ) 削除するデータ が葉の場合 親節点からの辺を取り除けばよい ( 場合 2 ) 削除するデータ の左部分木が空 右部分木が空でない場合 ( 場合 3 ) 削除するデータ の左部分木が空でなく 右部分木が空の場合 - 14 -

( 場合 4 ) 削除するデータ の左部分木 右部分木が空でない場合 (4.1 ) データ の直前のデータ を探し の位置に を代入する この位置ならば 全体の構成に 変更を生じない (4.2 ) の位置の左部分木から を削除する操作を続ける 最後には 場合 1, 2, 3 のいずれかになり終了する - 15 -

プログラム 再帰版 ( bt541.c) 要素を削除するプログラム 1 /* << bt541.c >> */ 2 #include <stdio.h> 3 #include <stdlib.h> 4 struct NODE { 5 int info; /* 節点がもつデータ */ 6 struct NODE *left; /* 左の子節点を指すポインタ */ 7 struct NODE *right; /* 右の子節点を指すポインタ */ 8 }; 9 void inorder(struct NODE *p); 10 struct NODE *mktree(); 11 void del(struct NODE *root, int x); 12 13 int main() { 14 int x; 15 struct NODE *root; 16 17 /* 2 分探索木の作成 */ 18 root = mktree(); 19 20 while( 1 ) { 21 /* 削除データ xの読み込み */ 22 scanf("%d",&x); 23 if( x <= 0 ) { break; } 24 printf(" 削除前 : "); 25 inorder(root->left); printf("\n"); 26 printf(" 削除データ : %d\n",x); 27 28 /* 削除データ xを指定する */ 29 del(root,x); 30 printf(" 削除後 : "); 31 inorder(root->left); printf("\n"); 32 } 33 } 34 35 /* データの削除 */ 36 void del(struct NODE *root, int x) { 37 struct NODE *before(struct NODE *p, int x, struct NODE *t); 38 struct NODE *p, 39 *q, 40 *r; 41 42 p = root->left; 43 q = root; 44 45 /* 要素 xを探す */ 46 while( p!= NULL ) { 47 if( x == p->info ) { break; } 48 q = p; - 16 -

49 if( p->info < x ) { p = p->right; } else { p = p->left; } 50 } 51 if( p == NULL ) { return; } 52 53 /* 削除操作 */ 54 /* 場合 1 : 削除節点が葉の場合 */ 56 if( (p->left == NULL)&&(p->right == NULL) ) { 57 if( p == q->left ) { 58 /* 削除データが左部分木にある */ 59 q->left = NULL; 60 } else { 61 /* 削除データが右部分木にある */ 62 q->right = NULL; 63 } 64 return; 65 } 66 67 /* 場合 2 : 削除節点の左部分木が空の場合 */ 68 if( p->left == NULL ) { 69 if( p == q->left ) { 70 /* 削除データが左部分木にある */ 71 q->left = p->right; 72 } else { 73 /* 削除データが右部分木にある */ 74 q->right = p->right; 75 } 76 return; 77 } 78 79 /* 場合 3 : 削除節点の右部分木が空の場合 */ 80 if( p->right == NULL ) { 81 if( p == q->left ) { 82 /* 削除データが左部分木にある */ 83 q->left = p->left; 84 } else { 85 /* 削除データが右部分木にある */ 86 q->right = p->left; 87 } 88 return; 89 } 90 91 /* 場合 4 */ 92 r = before(p,x,null); 93 p->info = r->info; 94 del(p,r->info); } - 17 -

実行結果 % cc bt541.c %./a.out 22 44 11 33 66 0 削除前 : 11 22 33 44 66 削除データ : 削除後 : 11 22 33 44 66 22 削除前 : 11 22 33 44 66 削除データ : 22 削除後 : 11 33 44 66 66 削除前 : 11 33 44 66 削除データ : 66 削除後 : 11 33 44 11 削除前 : 11 33 44 削除データ : 11 削除後 : 33 44 33 削除前 : 33 44 削除データ : 33 削除後 : 44 44 削除前 : 44 削除データ : 44 削除後 : 0-18 -

5. 5 問題 問題 1 データを読み込み 二分探索木を作成する つぎに 指定された順に要素を削除した後の二分探索木を求めよ ただし 講義で説明した方法を使うこと ( 1 ) 入力データ : 44,22,66,11,33,,77 削除する要素 : 44,33,66 1 ( 2 ) 入力データ : 77,22,88,99,11,66,44,33, 削除する要素 : 77,66, 2-19 -