プログラミングI第10回

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

PowerPoint Template

PowerPoint プレゼンテーション

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

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

memo

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

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

PowerPoint プレゼンテーション

Microsoft PowerPoint - lec10.ppt

PowerPoint プレゼンテーション

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

Microsoft Word - no205.docx

Microsoft Word - no15.docx

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

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

第1回 プログラミング演習3 センサーアプリケーション

第3回 配列とリスト

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

RX ファミリ用 C/C++ コンパイラ V.1.00 Release 02 ご使用上のお願い RX ファミリ用 C/C++ コンパイラの使用上の注意事項 4 件を連絡します #pragma option 使用時の 1 または 2 バイトの整数型の関数戻り値に関する注意事項 (RXC#012) 共用

プログラミング基礎

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

02: 変数と標準入出力

第2回

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

プログラミング実習I

gengo1-11

コマンドラインから受け取った文字列の大文字と小文字を変換するプログラムを作成せよ 入力は 1 バイトの表示文字とし アルファベット文字以外は変換しない 1. #include <stdio.h> 2. #include <ctype.h> /*troupper,islower,isupper,tol

PowerPoint Presentation

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

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

PowerPoint プレゼンテーション

02: 変数と標準入出力

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

02: 変数と標準入出力

r07.dvi

ohp07.dvi

JavaプログラミングⅠ

untitled

プログラミング及び演習 第1回 講義概容・実行制御

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

Transcription:

プログラミング 1 第 10 回 構造体 (3) 応用 リスト操作 この資料にあるサンプルプログラムは /home/course/prog1/public_html/2007/hw/lec/sources/ 下に置いてありますから 各自自分のディレクトリにコピーして コンパイル 実行してみてください Prog1 2007 Lec 101 Programming1 Group 19992007

データ構造 : リスト データが 一連 のメモリに保管される 最も簡単なデータ構造は配列である リニアサーチ は配列を検索するための方法だった 1072004 調べたい学生番号 1072001 1072004 1072050 データ 64 93 59 検索して得た情報 もっと効率的なデータ構造として 連結リスト (linked list) がある Prog1 2007 Lec 102 Programming1 Group 19992007

連結リスト (list) リスト はデータ構造の一種 何らかのしかけで一方向又は双方向に順に繋がる ( 連結 ) 矢印で繋がった各データを ノード ( 節 ) 又はセル と呼ぶ リストを矢印の方向にたどることが出来る 連結リストの実現 ( 実装 ) 方法は様々である ここでは 教科書 6.1とはちょっと違う実装を試みる この授業では一方向のものだけを説明する 双方向につながる 双方向リスト もあるので興味の有る人は調べてみると良い Prog1 2007 Lec 103 Programming1 Group 19992007

ノード 各ノードは構造体 ( タグ node) で実現されており 以下の要素を持つ データを保管する領域 : この例においては int 型変数 key 次のノードを示す領域 :node 型構造体ポインタ next KEY NEXT KEY NEXT struct node { int key; struct node *next; ; typedef struct node * NodePointer; 簡単のため Node 型ポインタを NodePointer と typedef する 構造体の宣言の中に自分自身の構造体へのポインタを持つものを 自己参照的構造体 と言う データを保管する領域には key 以外に他のデータも入れることができる Prog1 2007 Lec 104 Programming1 Group 19992007

リストの特徴 リストは配列とは異なり 各ノードがメモリの中で順に並んでいる必要はないし sizeof(struct node) のアドレスだけ離れている必要もない 大量のメモリ空間を一括に確保できなくても容易に利用できるし 必要に応じて長さを動的に変更することも簡単である 配列より少し複雑になるが メモリをより効率的に利用できる特徴がある Prog1 2007 Lec 105 Programming1 Group 19992007

ノードの連結 次のノードへのリンク ( 矢印 ) の実現 (x y の順で繋げるとする ) ノード x y のアドレスがそれぞれ 1200 番地 1100 番地だとする ノード x の next ( つまり x>next) に次のノード ( つまり y) のアドレス ( つまり 1100) というアドレスを入れる これで x y と言う連結が出来た事になる リストをたどるには順に next のアドレスをたどれば良い x(1200) KEY NEXT=1100 y(1100) KEY NEXT x>next = &y &y Prog1 2007 Lec 106 Programming1 Group 19992007

リストの構造 head NULL ノード 便宜的に先頭 (head) ノードを連結リストに付加する 先頭 (head) はリスト先頭にあり 前のノードがない headではkeyは使わないので不定とする headは外部変数として定義されてる ( 複数のリストを扱うときは不便 ) リストの終端 ( 最後のノード ) はヌルポインタ (NULL) となっている 初期状態はhead のみが存在し nextはヌルポインタとなっている ( 下図 ) リスト構造の実現方法は様々なバリエーションがある head KEY NEXT NULL Prog1 2007 Lec 107 Programming1 Group 19992007

新しいノードを作る : ノードへのメモリの割り当て 連結リストでは通常必要な分だけノードを作成する このような方法を 実行の途中にメモリを割り当てることから 動的リストと呼ぶ 以下がノード作成の関数である ノード1 個分のメモリ割り当てでは 割り当てるバイト数は sizeof(struct node) である NodePointer make_1node(int keydata, NodePointer p){ NodePointer n; if((n = malloc(sizeof(struct node))) == NULL) { printf("error in memory allocation\n"); exit(8); 何らかの理由でmalloc が失敗したら終了する n>key = keydata; n>next = p; keyとnextに引数の値をセットする return n; n KEY NEXT Prog1 2007 Lec 108 Programming1 Group 19992007

リストの初期化 head KEY NEXT NULL リストの初期化は簡単である 行うことは以下の 2 つで 関数 make_1node を呼ぶだけである head ノードの作成 next を NULL( ヌルポインタ ) にする NodePointer head; head; head は main の外で定義つまり外部 ( グローバル ) 変数 head head = make_1node(0,null); head ノードを作成する値は仮に 0 とする ( 何でも良い ) next に NULL( ヌルポインタ ) を設定する Prog1 2007 Lec 109 Programming1 Group 19992007

リストの表示 Head 2 5 7 NULL 1 回目 n 2 回目 n 3 回目 n 終了 head から NULL の前まで key の値を出力 void listprint(void){ NodePointer n; head の次からスタート 例の場合の出力 : Head 2 5 7 printf("head"); for(n = head>next; n!= NULL; n = n>next){ printf(" %d", n>key); リストを順にたどる printf("\n"); NULLになるまでノードを一つずつ表示する Prog1 2007 Lec 1010 Programming1 Group 19992007

検索方法 23 23を検索 発見! 終了 15 23 42 NULL 1 つ前のポインタを返す key が keydata( 例では 23) のノード n を検索する手順 : 1 値 keydata を head の次から NULL の前まで順に key と比較する 2 発見したら一つ前のノードへのポインタを返す 3 発見出来なかったら NULL を返す 一つ前のポインタを返す理由 : 削除の時に便利 ( 後述 ) Prog1 2007 Lec 1011 Programming1 Group 19992007

検索ソース NodePointer finditem(int keydata) { NodePointer n; next が NULL になるまで探す 1 for(n = head; n>next!= NULL; n = n>next){ if(n>next>key == keydata) return n; return NULL; 次のノードの key と keydata を比較する 1 見つかったら一つ前のノード (n) をリターン 2 発見出来なかったら NULL をリターン 3 keydata を head の次から NULL の前まで順に key と比較し 発見したら一つ前のノードへのポインタを返す ; 発見出来なかったら NULL を返す Prog1 2007 Lec 1012 Programming1 Group 19992007

検索イメージ head NULL 最初 n n>next ループ 2 回目 n n>next ループ 3 回目 n n>next ループ 4 回目 終了 n n>next Prog1 2007 Lec 1013 Programming1 Group 19992007

リストの構築 ( 挿入 ) 方法 head 4 3 NULL 2 newnode head の直後に key が keydata の値のノード newnode を挿入する手順 : 1 keyがkeydataのノードを検索する もしあればNULLをリターンし 終了 もしなければ ( 検索結果がNULLなら ) 以下の処理を行う 2 keyがkeydataのノード newnode を作成 3 newnode>next を head>next と同じ ( 代入 ) にする 4 head>next を newnode にする Prog1 2007 Lec 1014 Programming1 Group 19992007

挿入ソース headの直後にkeyがkeydataのノードnewnode を挿入する NodePointer insert(int keydata) { NodePointer newnode; key が keydata のノードを検索し なければ新しいノードを作り リストに挿入する ; あれば NULL を返す 1 if(finditem(keydata) == NULL){ newnode = make_1node(keydata,head>next); head>next = newnode; return newnode; else return NULL; head>next を newnode にする 4 key が keydata のノード newnode を作成 2 newnode>next を head>next と同じ ( 代入 ) にする 3 Prog1 2007 Lec 1015 Programming1 Group 19992007

プログラム (1) /* struct declaration */ struct node { int key; struct node *next; ; typedef struct node * NodePointer; ヘッダファイル list.h /* prototype declaration */ NodePointer insert(int); NodePointer finditem(int); void listprint(void); NodePointer make_1node(int,nodepointer); /* Global Variable head */ NodePointer head; プログラム全体はプログラム全体は /home/course/prog1/public_html/2007/lec/source/{lec101.c,list.h にあるにある Prog1 2007 Lec 1016 Programming1 Group 19992007

プログラム (2) #include <stdio.h> #include <stdlib.h> #include "list.h" main(){ int i,num; printf("[initial]\n"); head = make_1node(0,null); for (i = 1; i <= 9 ; ++i) insert(i); listprint(); printf("[insert](enter number)\n"); while(scanf("%d",&num) == 1){ if (insert(num) == NULL) printf("data %d is already on the list\n",num); listprint(); Prog1 2007 Lec 1017 Programming1 Group 19992007

NodePointer insert(int keydata){ NodePointer newnode; プログラム (3) if(finditem(keydata) == NULL){ newnode = make_1node(keydata,head>next); head>next = newnode; return newnode; else return NULL; /* in case of data found */ void listprint(void){ NodePointer n; printf("head"); for(n = head>next; n!= NULL; n = n>next) { printf(" %d", n>key); printf("\n"); Prog1 2007 Lec 1018 Programming1 Group 19992007

NodePointer finditem(int keydata){ NodePointer n; プログラム (4) for(n = head; n>next!= NULL; n = n>next){ if(n>next>key == keydata) return n; return NULL; /* in case of not found */ NodePointer make_1node(int keydata, NodePointer p){ NodePointer n; if((n = malloc(sizeof(struct node))) == NULL) { printf("error in memory allocation\n"); exit(8); n>key = keydata; n>next = p; return n; Prog1 2007 Lec 1019 Programming1 Group 19992007

実行結果 s1000000{std0ss0:1 s1000000{std0ss0:1./a.out./a.out [Initial] [Initial] Head Head 9 9 8 8 7 7 6 6 5 5 4 4 3 3 2 2 1 1 [Insert](enter [Insert](enter number) number) 55 Data Data 5 5 is is already already on on the the list list Head Head 9 9 8 8 7 7 6 6 5 5 4 4 3 3 2 2 1 1 10 10 Head Head 10 10 9 9 8 8 7 7 6 6 5 5 4 4 3 3 2 2 1 1 25 25 Head Head 25 25 10 10 9 9 8 8 7 7 6 6 5 5 4 4 3 3 2 2 1 1 Control+D Control+D s1000000{std0ss0:2 s1000000{std0ss0:2 Prog1 2007 Lec 1020 Programming1 Group 19992007