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

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

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

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

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

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

プログラミングI第10回

memo

PowerPoint プレゼンテーション

Microsoft PowerPoint - lec10.ppt

PowerPoint プレゼンテーション

Microsoft Word - no205.docx

PowerPoint Template

Microsoft Word - no15.docx

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

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

問 2 ( 型変換 ) 次のプログラムを実行しても正しい結果が得られない 何が間違いかを指摘し 正しく修正せよ ただし int サイズが 2 バイト long サイズが 4 バイトの処理系での演算を仮定する #include <stdio.h> int main( void ) { int a =

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

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

cp-7. 配列

プログラミング基礎

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

r07.dvi

1. 入力した正の整数を降順に並べ換えて出力するプログラムを作成せよ プログラムは個別にコンパイルし make コマンドで実行すること 入力データは 50 以下とし 以下の数が混在しているとする 16 進数 : 先頭 1 文字が x または X( エックスの小文字か大文字 ) 8 進数 : 先頭 1

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

ohp07.dvi

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

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

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

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

PowerPoint Presentation

gengo1-11

PowerPoint プレゼンテーション

PowerPoint プレゼンテーション

Microsoft PowerPoint - CproNt02.ppt [互換モード]

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

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

Taro-cshプログラミングの応用.jt

char int float double の変数型はそれぞれ 文字あるいは小さな整数 整数 実数 より精度の高い ( 数値のより大きい より小さい ) 実数 を扱う時に用いる 備考 : 基本型の説明に示した 浮動小数点 とは数値を指数表現で表す方法である 例えば は指数表現で 3 書く

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

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

第2回

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) * *

人工知能入門

Transcription:

0. 目次 1. 1. 1 配列によるの実現 1. 2 再帰的なデータ構造によるの実現 1. 3 地図情報処理 1. 4 問題 問題 1 グラフ探索問題 - 1 -

1. は データの出し入れが一カ所で行われ 操作は追加と削除ができるデータ構造をいう 出入口 追加 削除 操作 最初 111 追加 111 222 追加 111 222 333 追加 111 222 333 444 追加 111 222 333 は一杯で追加失敗 333 削除 111 222 222 削除 111-2 -

1. 1 配列によるの実現 配列での実現 : 変数 top でに保存されるデータの位置を示す 変数 top の初期値は 0 とする データを保存する場合 変数 top が指す位置にデータが保存され 変数 top の値を 1 増やす データを取り出す場合 変数 top の値を 1 減らし 変数 top の指す位置からデータが取り出される 変数 top の値は 要素の数でもある 最初 配列 0 1 2 top=0 0 1 2 111 追加配列 111 top=1 0 1 2 222 追加配列 111 222 top=2 0 1 2 333 追加 配列 111 222 333 top=3 0 1 2 444 追加 配列 111 222 333 は一杯で追加失敗 top=3 0 1 2 333 削除配列 111 222 top=2 0 1 2 222 削除配列 111 top=1-3 -

( 配列表現 ) へ要素の追加 追加前 0 1 top=2 stack 111 222 追加データ : 333 追加後 0 1 2 top=3 stack 111 222 333 stack[top] = x; top++; ( 配列表現 ) から要素の削除 削除前 0 1 2 top=3 111 222 333 削除データ : 333 削除後 0 1 top=2 111 222 top--; - 4 -

プログラム ( st111.c) の操作を行うプログラム 操作 1: 正整数を読み込みに追加 操作 0: からデータを取り出す 操作 -1: 終了 1 /* << st111.c >> */ 2 #include <stdio.h> 3 #define SMAX 2 /* に保存できるデータ数 */ 4 5 int main() { 6 int i, 7 op, /* 操作 */ 8 stack[smax], /* を実現する配列 */ 9 top, /* に保存されるデータの位置 */ 10 x; /* データ */ 11 12 /* の初期化 */ 13 top = 0; 14 15 /* 操作 */ 16 while( 1 ) { 17 /* の表示 */ 18 printf(" : "); 19 for( i=0; i<top; i++ ) { printf("%d ",stack[i]); } 20 printf("\n"); 21 22 /* 操作入力 */ 23 printf(" 操作 : "); scanf("%d",&op); 24 switch( op ) { 25 26 case 1: /* 追加データを読み込む */ 27 printf(" データ :"); scanf("%d",&x); 28 /* にデータを追加 */ 29 if( top < SMAX ) { 30 stack[top] = x; top++; 31 } else { 32 printf(" が一杯です \n"); 33 } 34 break; 35 36 case 0: /* からデータを削除 */ 37 if( top > 0 ) { 38 top--; 39 } else { 40 printf(" が空です \n"); 41 } 42 break; - 5 -

43 44 case -1: /* 終了 */ 45 exit(0); 46 } 47 } 48 } 実行結果 % cc st111.c %./a.out : 操作 : 1 データ :111 : 111 操作 : 1 データ :222 : 111 222 操作 : 1 データ :333 が一杯です : 111 222 操作 : 0 : 111 操作 : 0 : 操作 : 0 が空です : 操作 : -1-6 -

1. 2 再帰的なデータ構造によるの実現 構造体を用いた再帰的なデータ構造 ( 構造体のメンバに他の構造体を指すポインタを含む ) で実現する head は の先頭を指す NULL はリストの最後を意味する head リストヘッド NULL 操作 最初 head NULL 111 追加 head 111 NULL 222 追加 head 222 111 NULL 333 追加 head 333 222 111 NULL 333 削除 ( 注意 ) 構造体が確保できる間 追加操作が可能 head 222 111 NULL 222 削除 head 111 NULL - 7 -

( 再帰的表現 ) へ要素の追加 追加前 head a b NULL 追加後 追加データ : x head x a b NULL p p = (struct NODE *)malloc(sizeof(struct NODE)); p->info = x; p->next = head->next; head->next = p; ( 再帰的表現 ) から要素の削除 削除前 head a b c NULL q 削除後 head b c NULL q = head->next; head->next = q->next; - 8 -

プログラム ( st121.c) の操作を行うプログラム操作 1: 正整数を読み込みに追加 操作 0: からデータを取り出す 操作 -1: 終了 1 /* << st121.c >> */ 2 #include <stdio.h> 3 #include <stdlib.h> 4 struct NODE { 5 int info; 6 struct NODE *next; 7 }; 8 9 int main() { 10 int op, /* 操作 */ 11 x; /* データ */ 12 struct NODE *head, /* の先頭を指すポインタ変数 */ 13 *p, /* 作業用ポインタ変数 */ 14 *q; /* 作業用ポインタ変数 */ 15 16 /* リストヘッドの作成 */ 17 head = (struct NODE *)malloc(sizeof(struct NODE)); 18 head->next = NULL; 19 20 while( 1 ) { 21 /* の表示 */ 22 printf(" : "); 23 p = head->next; 24 while( p!= NULL ) { printf("%d ",p->info); p = p->next; } 25 printf("\n"); 26 27 /* 操作入力 */ 28 printf(" 操作 : "); scanf("%d",&op); 29 switch( op ) { 30 31 case 1: /* 追加データを読み込む */ 32 printf(" データ :"); scanf("%d",&x); 33 /* にデータを追加 */ 34 p = (struct NODE *)malloc(sizeof(struct NODE)); 35 p->info = x; 36 p->next = head->next; 37 head->next = p; 38 break; 39 40 case 0: /* からデータを削除 */ 41 if( head->next!= NULL ) { 42 q = head->next; 43 head->next = q->next; - 9 -

44 } else { 45 printf(" は空です \n"); 46 } 47 break; 48 49 case -1: /* 終了 */ 50 exit(0); 51 } 52 } 53 } 実行結果 % cc st121.c %./a.out : 操作 : 1 データ :111 : 111 操作 : 1 データ :222 : 222 111 操作 : 1 データ :333 : 333 222 111 操作 : 0 : 222 111 操作 : 0 : 111 操作 : 0 : 操作 : 0 は空です : 操作 : -1-10 -

1. 3 地図情報処理 0 と 1 で与えられた地図情報から島 (1 が上下左右に隣接する領域 ) の個数を求める問題を考察する なお 0 は海を表し 1 は陸を表す 地図情報 000001100000 000111111000 000110000000 011000111100 000000001100 011100000000 000100000000 この場合 島の個数は 4 となる 考え方 1 地図のすべての点について 2 を行う 2 点の値が 1 の場合 隣接する点で値が 1 となる点をひとつの島として登録する 登録した島の点は 再度登録されないように値を変更しておく 動作 ( 1 ) 地図情報 ( 2 ) 地図情報 ( 3 ) 地図情報 000001100000 000002200000 000002200000 000111111000 000222222000 000222222000 000110000000 000220000000 000220000000 011000111100 011000111100 033000111100 000000001100 000000001100 000000001100 011100000000 011100000000 011100000000 000100000000 000100000000 000100000000 ( 4 ) 地図情報 ( 5 ) 地図情報 000002200000 000002200000 000222222000 000222222000 000220000000 000220000000 033000444400 033000444400 000000004400 000000004400 011100000000 055500000000 000100000000 000500000000-11 -

プログラム ( st131.c) 1 /* << st131.c >> */ 2 #include <stdio.h> 3 #include <stdlib.h> 4 #define M 30 /* 行の最大値 */ 5 #define N 30 /* 列の最大値 */ 6 7 int main() { 8 int a[m+2][n+2], /* 地図情報を保存する配列 */ 9 i,j,k,l, 10 m, /* 行数 */ 11 n, /* 列数 */ 12 num, /* 島の番号 */ 13 ti,tj; 14 int si[m*n], /* 関連の配列 */ 15 sj[m*n], /* 関連の配列 */ 16 top; /* 関連の変数 */ 17 18 /* 地図情報 ( m: 行数 n: 列数 ) の読み込み */ 19 scanf("%d%d",&m,&n); 20 if( (m <= 0) (m > M) 21 (n <= 0) (n > N) ) { exit; } 22 for( i=1; i<=m; i++ ) { 23 for( j=1; j<=n; j++ ) { scanf("%1d",&a[i][j]); } 24 } 25 26 /* 与えられた地図情報の周囲を海としておくと 処理が簡潔になる */ 27 for( j=0; j<=n+1; j++ ) { 28 a[0][j] = 0; a[m+1][j] = 0; 29 } 30 for( i=1; i<=m; i++ ) { 31 a[i][0] = 0; a[i][n+1] = 0; 32 } 33 34 /* 地図情報の表示 */ 35 printf(" 探索前 \n"); 36 for( i=1; i<=m; i++ ) { 37 for( j=1; j<=n; j++ ) { printf("%d",a[i][j]); } 38 printf("\n"); 39 } 40 41 /* 初期設定 */ 42 num = 1; 43 44 /* 地図情報のすべての点について 探索する */ 45 for( i=1; i<=m; i++ ) { 46 for( j=1; j<=n; j++ ) { 47 /* 点 (i,j) が 0 すなわち 海の場合 スキップ */ 48 if( a[i][j] == 0 ) { continue; } - 12 -

49 50 /* 点 (i,j) が 1 以外 すなわち すでに探索済みの場合 スキップ */ 51 if( a[i][j] > 1 ) { continue; } 52 53 /* 点 (i,j) が 1 すなわち未探索の場合 島を確定する */ 54 num++; 55 56 /* の初期化 */ 57 si[0] = i; sj[0] = j; top = 1; 58 59 /* (si[*],sj[*]) を使って 点 (ti,tj) に隣接する陸の 60 点をすべて同じ島の番号に設定する */ 61 while( top > 0 ) { 62 ti = si[top-1]; tj = sj[top-1]; top--; 63 a[ti][tj] = num; 64 65 if( a[ti-1][tj] == 1 ) { 66 si[top]=ti-1; sj[top]=tj; top++; 67 } 68 if( a[ti+1][tj] == 1 ) { 69 si[top]=ti+1; sj[top]=tj; top++; 70 } 71 if( a[ti][tj-1] == 1 ) { 72 si[top]=ti; sj[top]=tj-1; top++; 73 } 74 if( a[ti][tj+1] == 1 ) { 75 si[top]=ti; sj[top]=tj+1; top++; 76 } 77 } 78 79 /* 途中結果の表示 */ 80 printf(" 途中結果 \n"); 81 for( k=1; k<=m; k++ ) { 82 for( l=1; l<=n; l++ ) { printf("%1d",a[k][l]); } 83 printf("\n"); 84 } 85 } 86 } 87 88 /* 最終結果の表示 */ 89 printf(" 探索後 \n"); 90 for( i=1; i<=m; i++ ) { 91 for( j=1; j<=n; j++ ) { printf("%1d",a[i][j]); } 92 printf("\n"); 93 } 94 printf(" 島の個数 : %d\n",num-1); 95 } - 13 -

実行結果 % cat st131.dat 7 12 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 1 1 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 % cc st131.c %./a.out < st131.dat 探索前 000001100000 000111111000 000110000000 011000111100 000000001100 011100000000 000100000000 途中結果 000002200000 000222222000 000220000000 011000111100 000000001100 011100000000 000100000000 途中結果 000002200000 000222222000 000220000000 033000111100 000000001100 011100000000 000100000000 途中結果 000002200000 000222222000 000220000000 033000444400 000000004400 011100000000 000100000000 途中結果 000002200000 000222222000 000220000000 033000444400-14 -

000000004400 055500000000 000500000000 探索後 000002200000 000222222000 000220000000 033000444400 000000004400 055500000000 000500000000 島の個数 : 4-15 -

1. 4 問題 問題 1 グラフ探索問題 与えられたグラフにおいて 開始節点から到達できる節点をすべて求める問題を考察する 1 3 5 2 4 考え方 節点に隣接する節点を隣接節点とよぶ ( 手順 a) 始点を訪問済節点とし に格納する 他の節点は未訪問節点とする ( 手順 b) から節点をひとつ取り出す この節点の隣接節点が未訪問の場合 訪問済節点とした後 に格納する 訪問済の場合 何もしない ( 手順 c) 手順 b をが空になるまで繰り返す ( 手順 d) 訪問済節点を表示する 動作開始節点を節点 1 とする ( 1 ) 手順 a 節点 1 3 1 訪問済 2 5 3 4 2 4 1 5 未訪問節点は空欄とする ( 2 ) 手順 b 節点 1 3 1 訪問済 2 訪問済 5 3 訪問済 3 4 2 4 2 5 未訪問節点は空欄とする - 16 -

( 3 ) 手順 b 節点 1 3 1 訪問済 2 訪問済 5 5 3 訪問済 4 4 訪問済 2 4 2 5 訪問済 未訪問節点は空欄とする ( 4 ) 手順 b 節点 1 3 1 訪問済 2 訪問済 5 3 訪問済 4 4 訪問済 2 4 2 5 訪問済 未訪問節点は空欄とする ( 5 ) 手順 b 節点 1 3 1 訪問済 2 訪問済 5 3 訪問済 4 訪問済 2 4 2 5 訪問済 未訪問節点は空欄とする ( 6 ) 手順 b 終了 節点 1 3 1 訪問済 2 訪問済 5 3 訪問済 4 訪問済 2 4 5 訪問済 未訪問節点は空欄とする プログラム ( st141.c) 1 /* << st141.c >> */ 2 #include <stdio.h> 3 #include <stdlib.h> 4 #define N 99 /* 節点の最大数 */ 5 struct NODE { 6 int info; 7 struct NODE *next; /* nextはポインタ変数 */ 8 }; 9 10 int main() { 11 struct NODE *head[n+1], /* 節点 iに隣接する節点のリスト */ 12 *p, /* 作業用ポインタ変数 */ - 17 -

13 *q; /* 作業用ポインタ変数 */ 14 int d0,d1, /* (d0,d1) は辺を意味する */ 15 i, 16 n, /* 節点の個数 */ 17 s, /* 開始節点 */ 18 v[n+1]; /* v[i]=0 節点 iが未訪問 19 v[i]=1 節点 iが訪問済を意味する */ 20 int stack[99], /* 関係の配列 */ 21 top; /* 関係の変数 */ 22 23 /* 節点の個数 nを入力 */ 24 scanf("%d",&n); 25 if( (n <= 0) (n > N) ) { exit; } 26 27 /* 各節点のリストヘッドの作成 */ 28 for( i=1; i<=n; i++ ) { 29 head[i] = (struct NODE *)malloc(sizeof(struct NODE)); 30 head[i]->info = i; 31 head[i]->next = NULL; 32 } 33 34 /* グラフの作成 */ 35 while( 1 ) { 36 /* 辺の入力 (d0,d1) は辺を意味する */ 37 scanf("%d%d",&d0,&d1); 38 if( (d0 <= 0) (d0 > n) (d1 <= 0) (d1 > n) ) { break; } 39 40 q = (struct NODE *)malloc(sizeof(struct NODE)); 41 q->info = d1; 42 q->next = NULL; 43 44 /* 入力した辺 (d0,d1) をリストの先頭に挿入する */ 45 p = head[d0]->next; 46 head[d0]->next = 1 ; 47 q->next = 2 ; 48 } 49 50 /* グラフの表示 */ 51 printf(" グラフ \n"); 52 for( i=1; i<=n; i++ ) { 53 printf("%d: ",i); 54 p = head[i]->next; 55 while( p!= NULL ) { 56 printf("%d ",p->info); 57 p = p->next; 58 } 59 printf("\n"); 60 } 61 62 /* 到達節点の探索 */ - 18 -

63 64 while( 1 ) { 65 /* 開始節点の入力 */ 66 scanf("%d",&s); 67 if( s == 0 ) { break; } 68 69 /* 初期設定 */ 70 for( i=1; i<=n; i++ ) { /* すべての節点を未訪問に設定 */ 71 v[i] = 0; 72 } 73 stack[0] = s; top = 1; /* topは 次に格納する位置を意味する 74 格納されている節点数でもある */ 75 v[s] = 1; /* 開始節点 sを訪問済にする */ 76 77 /* 操作 */ 78 while( top > 0 ) { 79 /* 節点 v[top-1] に隣接する節点で 未訪問であればに格納 */ 80 p = head[stack[top-1]]->next; top--; 81 while( p!= NULL ) { 82 /* 節点 p->infoが未訪問の場合 */ 83 if( v[p->info] == 3 ) { 84 stack[top] = 4 ; 85 v[stack[top]] = 5 ; 86 top++; 87 } 88 p = p->next; 89 } 90 } 91 92 /* 到達節点の出力 */ 93 printf(" 開始節点 : %d ",s); 94 printf(" 到達節点 : "); 95 for( i=1; i<=n; i++ ) { 96 if( v[i] == 1 ) { printf(" %d",i); } 97 } 98 printf("\n"); 99 } 100 } - 19 -

グラフ 1 1 3 5 2 4 実行結果 % cat g1.dat 5 1 2 1 3 2 1 2 4 3 1 3 4 3 5 4 2 4 3 4 5 5 3 5 4 0 0 1 5 0 % cc st141.c %./a.out < g1.dat グラフ 1: 3 2 2: 4 1 3: 5 4 1 4: 5 3 2 5: 4 3 開始節点 : 1 到達節点 : 1 2 3 4 5 開始節点 : 5 到達節点 : 1 2 3 4 5-20 -

グラフ 2 1 3 7 5 6 2 4 8 実行結果 % cat g2.dat 8 1 2 1 3 2 1 2 4 3 1 3 4 3 5 4 2 4 3 4 5 5 3 5 4 6 7 6 8 7 6 7 8 8 6 8 7 0 0 1 8 0 %./a.out < g2.dat グラフ 1: 3 2 2: 4 1 3: 5 4 1 4: 5 3 2 5: 4 3 6: 8 7 7: 8 6 8: 7 6 開始節点 : 1 到達節点 : 1 2 3 4 5 開始節点 : 8 到達節点 : 6 7 8-21 -