木構造の実装

Similar documents
第3回 配列とリスト

二分木の実装

PowerPoint Presentation

第3回 配列とリスト

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

Microsoft Word - no206.docx

プログラミングI第10回

memo

PowerPoint Presentation

Microsoft PowerPoint - kougi9.ppt

Microsoft Word - no12.doc

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

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

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

PowerPoint プレゼンテーション

PowerPoint Template

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

Microsoft PowerPoint - lec10.ppt

第2回

プログラミング基礎

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

memo

Microsoft PowerPoint - 6.pptx

O(N) ( ) log 2 N

memo

CプログラミングI

PowerPoint プレゼンテーション

Microsoft PowerPoint - 06.pptx

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

Microsoft PowerPoint - kougi10.ppt

PowerPoint Presentation

Prog1_15th

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

Microsoft PowerPoint - 05.pptx

PowerPoint Presentation

r07.dvi

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

ohp07.dvi

アルゴリズムとデータ構造

Microsoft PowerPoint - exp2-02_intro.ppt [互換モード]

Microsoft Word - no15.docx

memo

プログラミング基礎

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

Microsoft PowerPoint - 11.pptx

DVIOUT

第2回

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

memo

Microsoft Word - no205.docx

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

alg2015-3r3.ppt

プログラミング実習I

memo

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

プログラミング基礎

untitled

PowerPoint プレゼンテーション

void hash1_init(int *array) int i; for (i = 0; i < HASHSIZE; i++) array[i] = EMPTY; /* i EMPTY */ void hash1_insert(int *array, int n) if (n < 0 n >=

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

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

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

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

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

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

Microsoft PowerPoint - Pro110111

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

配列, 関数, 構造体

演算増幅器

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

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

Microsoft Word - 13

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

memo

データ構造

演算増幅器

第 3 回 Java 講座 今回の内容 今週の Java 講座はコレクション 拡張 for 文, ガベージコレクションについて扱う. 今週の Java 講座は一番内容が薄いも のになるだろう. コレクション コレクションとは大きさが決まっていない配列だと考えればよい. コレクションには List 先

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

joho07-1.ppt

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

人工知能入門

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

Microsoft Word - no13.docx

Prog1_10th

Microsoft Word - C言語研修 C++編 3.doc

Microsoft Word - no204.docx

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

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

Microsoft Word - NonGenList.doc

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

Microsoft Word - no11.docx

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

PowerPoint プレゼンテーション

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

DVIOUT

program.dvi

PowerPoint プレゼンテーション

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

Microsoft Word - 【第5分科会】ConcolicTestingグループ_付録_修正_ doc

Transcription:

汎用的構造と反復子 Algorithms and Data Structures on C

この回の要点 汎用的構造とは これまでのリストでは何か問題か? 解決する方法は? 反復子とは 何をするものか? どのように使うか? 実装コード ListNode 型 List 型 ListIterator 型

個人情報 PD 型 ( 第 4 回で作成 ) 個人情報 名前 (char *name) 年齢 (int age) リストとしての構造 前の要素 (PD *prev) 次の要素 (PD *next) typedef struct PDtag { struct PDtag *prev; struct PDtag *next; char *name; int age; PD; ListPD 型 PD 型 個人情報のリスト構造 NULL 前 次 前 次 前 次 NULL 太郎 (21) first 次郎 (18) 三郎 (15) last

残念なこと データと構造とが混在している 別なデータのリスト構造を使いたいときは もう一度同様な型を書く必要がある リスト構造に対する操作も再度作り直し p1 の前に p2 を接続 insertbefore(pd *p1,pd *p2); p1 の後に p2 を接続 insertafter(pd *p1,pd *p2); pd を削除 remove(pd *pd); など 本来 リスト構造と中のデータは関係ない リストでは数珠つなぎになっていること が重要 データと構造を分離できると便利 構造に対する操作は流用できる

これまでのリスト構造 ( 問題あり ) PD 型 ListNodePD 型に変更 リストにつながれることを前提とした個人情報の型 個人情報 ( 名前と年齢 ) の他に前後のリンクを持つ ListPD 型 ListNodePD 型のデータが一列につながった構造 処理 データが個人情報であることが前提 print(list*) 関数で すべての個人情報が表示される

リスト内容の表示 (1) /*** *** 個人情報リストのテスト ***/ #include "ListPD.h" TestListPD.cc addtop(lp,makelistnodepd(" 近藤 ",41)); printf("**before** n"); print(lp); remove(lp,pd); printf("**after** n"); print(lp); int main(void){ printf("2 番目は "); ListPD *lp=makelistpd(); print(get(lp,1)); printf(" です n"); この部分 ListNodePD *pd; add(lp,makelistnodepd(" 山田 ",19)); add(lp,pd=makelistnodepd(" 森 ",50)); free(lp); すべての要素を表示する add(lp,makelistnodepd(" 田中 ",23)); print(lp);

リスト内容の表示 (2) // 表示 void print(listpd *lp){ ListNodePD *p=lp->first; printf("listpd:(%d): n",lp->size); for(int i=1;p;p=p->next,i++){ printf("%d:",i); print(p); printf(" "); printf(" n"); ListPD.cc 先頭のノードから始めて 次々にノードをたどりながら そのノードを表示する 要素の反復が関数の中で行われている

リスト内容の表示 (3) // 個人情報を表示する void print(listnodepd *pd){ printf("%s(%d)",pd->name,pd->age); ListNodePD.cc 個人情報として表示する $ ListTestPD ListPD:(3): 1: 山田 (19) 2: 森 (50) 3: 田中 (23) **before** ListPD:(4): 1: 近藤 (41) 2: 山田 (19) 3: 森 (50) 4: 田中 (23) **after** ListPD:(4): 1: 近藤 (41) 2: 山田 (19) 3: 田中 (23) 2 番目は山田 (19) です

問題点は? リストをたどる目的は表示だけではない 全員の点数を +5 点したい 鹿児島市内に居住する人の名前を表示したい 20 歳の人にメールを出したい すべてのインベーダとの衝突判定をしたい その都度 print() と同様な関数を書く? 非効率的 データ構造の内部に立ち入ることになる 汎用性の低下

リスト構造の見直し 中に入っているデータには興味はない 順に並んでいることが本質 データとして void* を持てば 何でも入れられる 最小限持つべき機能 リストの先頭や末尾に要素を追加できる 要素を取り出すことができる 要素を削除できる List 型 NULL 要素数がわかる ListNode 型 前 次 前 次 汎用的リスト構造 前 次 NULL void* first void* void* last

新しいリスト構造 List データ型は構造とデータを分離 リンクノードを表す ListNode 型 構造 ( 前後の腕 ) はそのまま データは void* のポインタ リンクリストを表す List 型 先頭要素 first 末尾要素 last 要素数 size 反復子 ListIterator 型 リストの中の要素を次々に取り出すための型 ListIterator void* first last ListNode void* ListNode void* ListNode void* ListNode void* ListNode void*

反復子 (Iterator) とは ある構造の中のデータを順に取り出す仕組み for 文でループを組むのと似ている データそのものを取り出すので どんな処理でも可能 使用方法 1. 反復子を生成する 2. ループ条件で反復子が次の要素を持つかどうかをチェック 3. 次の要素を持つなら それを取り出して処理する 疑似コード Iterator it=makeiterator(set); while(hasnext(it)){ data *d=next(it); // d を処理 set の中の要素の反復子を生成する 次の要素がある間 要素を取り出して処理する

ListNode.h #ifndef ListNode h #define ListNode h /*** *** 双方向リンクリストのノード ***/ #include <stdio.h> #include <stdlib.h> // ノード型 typedef struct ListNodeTag { struct ListNodeTag *prev,*next; void *data; 実際のデータ ListNode; // プロトタイプ宣言 ListNode *makelistnode(void*); void free(listnode*); void insertbefore(listnode*,listnode*); void insertafter(listnode*,listnode*); void remove(listnode*); void *get(listnode*); #endif // ListNode h

ListNode.cc /*** *** ListNode の実装 ***/ #include "ListNode.h" 入れるデータは // 生成 ListNode *makelistnode(void *d){ void* 型 ListNode *n=(listnode*)malloc(sizeof(listnode)); n->data=d; return n; // 破棄 void free(listnode *n){ if(n->data) free(n->data); free((void*)n); 続く

ListNode.cc // 前に挿入 void insertbefore(listnode *n1,listnode *n2){ if(n1==null n2==null) return; if(n1->prev) n1->prev->next=n2; n2->prev=n1->prev; n2->next=n1; n1->prev=n2; // 次に挿入 void insertafter(listnode *n1,listnode *n2){ if(n1==null n2==null) return; if(n1->next) n1->next->prev=n2; n2->prev=n1; n2->next=n1->next; n1->next=n2; 続く

ListNode.cc // 取り外す void remove(listnode *n){ if(n==null) return; if(n->prev) n->prev->next=n->next; if(n->next) n->next->prev=n->prev; n->prev=n->next=null; // データを取り出す void *get(listnode *n){ return n->data;

List.h #ifndef List h #define List h /*** *** リスト ***/ #include "ListNode.h" // リスト型 typedef struct { ListNode *first,*last; int size; List; // プロトタイプ宣言 List *makelist(); void free(list*); void addtop(list*,void*); void add(list*,void*); void remove(list*,void*); void *getfirst(list*); void *getlast(list*); void *get(list*,int); int getsize(list*); #endif // List h

List.cc /*** *** List の実装 ***/ #include "List.h" // 生成 List *makelist(){ List *l=(list*)malloc(sizeof(list)); l->first=l->last=null; l->size=0; return l; // 破棄 // 中の要素も破棄する void free(list *l){ ListNode *n=l->first,*nn; while(n){ nn=n->next; free(n); n=nn; free((void*)l); 続く

List.cc // 先頭に追加 void addtop(list *l,void *d){ ListNode *n=makelistnode(d); if(l->first==null) l->first=l->last=n; else{ insertbefore(l->first,n); l->first=n; l->size++; // 末尾に追加 void add(list *l,void *d){ ListNode *n=makelistnode(d); if(l->last==null) l->first=l->last=n; else{ insertafter(l->last,n); l->last=n; l->size++; データは void* データは void* 続く

List.cc // データ d のノードを取り出す ( 線形探索 ) 内部使用のみ ListNode *find(list *l,void *d){ for(listnode *n=l->first;n;n=n->next) if(get(n)==d) return n; return NULL; // リストから取り外す void remove(list *l,void *d){ ListNode *n=find(l,d); if(n==l->first) l->first=l->first->next; if(n==l->last) l->last=l->last->prev; if(n) remove(n); l->size--; データは void* データは void* // i 番目の要素 void *get(list *l,int i){ ListNode *n=l->first; for(int j=0;j<i && n;j++) n=n->next; return (n)?get(n):null; // 要素数 int getsize(list *l){ return l->size;

ListIterator.h #ifndef ListIterator h #define ListIterator h /*** *** リストの反復子 ***/ #include "List.h" // 反復子型 typedef struct { List *list; ListNode *next; ListIterator; // 反復対象のリスト // 次に返すノード // プロトタイプ宣言 ListIterator *makelistiterator(list*); void free(listiterator*); ListNode *hasnext(listiterator*); void *next(listiterator*); データは void* #endif // ListIterator h

ListIterator.cc /*** *** ListIterator の実装 ***/ #include "ListIterator.h" // 生成 ListIterator *makelistiterator(list *l){ ListIterator *it=(listiterator*)malloc(sizeof(listiterator)); it->list=l; it->next=null; // 反復未開始状態 return it; // 破棄 void free(listiterator *it){ free((void*)it); 続く

ListIterator.cc // 次の要素があるか // 次の要素がないときはNULLが返る ListNode *hasnext(listiterator *it){ if(it->next==null) // 反復未開始なら return it->next=it->list->first; // 先頭要素 return it->next=it->next->next; // そうでないなら次の要素 // 次の要素 void *next(listiterator *it){ return get(it->next);

PD.h #ifndef PD h #define PD h /*** *** 個人情報 ***/ #include <stdio.h> #include <stdlib.h> #include <string.h> // 個人情報型 typedef struct { char *name; int age; PD; 前後の腕がない! // プロトタイプ宣言 PD *makepd(const char*,int); PD *makepd(char*,int); void free(pd*); void print(pd*); #endif // PD h

PD.cc /*** *** PD の実装 ***/ #include "PD.h" // 生成 PD *makepd(const char *n,int a){ return makepd((char*)n,a); PD *makepd(char *n,int a){ PD *pd=(pd*)malloc(sizeof(pd)); int l=strlen(n); pd->name=(char*)malloc(l+1); strcpy(pd->name,n); pd->age=a; return pd; 続く

PD.cc // 破棄 void free(pd *pd){ free(pd->name); free((void*)pd); // 表示 void print(pd *pd){ printf("%s(%d)",pd->name,pd->age);

TestList.cc /*** List のテスト ***/ #include "PD.h" #include "List.h" #include "ListIterator.h" // 全部のデータを表示する void print(list *list){ printf("list(%d): n",getsize(list)); int i=1; for(listiterator *it=makelistiterator(list);hasnext(it);i++){ PD *pd=(pd*)next(it); printf("%d:",i); print(pd); printf("-"); printf(" n"); 続く

TestList.cc int main(void){ List *list=makelist(); PD *pd; add(list,makepd(" 山田 ",21)); add(list,pd=makepd(" 斎藤 ",34)); add(list,makepd(" 森 ",50)); addtop(list,makepd(" 近藤 ",18)); add(list,makepd(" 山下 ",33)); printf("*** Before *** n"); print(list); remove(list,pd); printf("*** After *** n"); print(list); pd=(pd*)get(list,2); printf("2 番は ");print(pd);printf(" です "); free(list);

TestList の実行結果 $ TestList *** Before *** List(5): 1: 近藤 (18)-2: 山田 (21)-3: 斎藤 (34)-4: 森 (50)-5: 山下 (33)- *** After *** List(4): 1: 近藤 (18)-2: 山田 (21)-3: 森 (50)-4: 山下 (33)- 2 番は森 (50) です

課題 171120 次ページは 20 人分の名前と 4 科目の点数である 名前と 4 科目の点数を持つデータ型 PScore を作り それを List に入れて 科目ごとの上位 3 名の名前と点数を出力するプログラム PScoreTop3.cc を示せ (PScore は PD を参考に作ること ) 作成方法 : 作成した 3 つのコード PScore.h,PScore.cc,PScoreTop3.cc をワードに添付して示すこと 実行結果も示すこと 提出方法 : メールで メールの本文中にも学籍番号を氏名を明記すること 提出先 :fuchida@ibe.kagoshima-u.ac.jp メールタイトル : アルゴリズム課題 171120 厳守! 期限 :2017 年 11 月 26 日 ( 日 ) 24:00

成績データ (CSV 形式 ) pscore-data.csv Luke,79,80,91,67 Conrad,60,88,89,97 Cecil,74,70,72,60 Percival,60,64,99,96 Nicholas,71,79,61,65 Andy,60,82,62,84 Ernest,77,80,75,70 Le Roy,98,78,77,60 Marcus,89,63,65,65 Lew,78,89,87,69 Boniface,84,70,63,69 Robert,76,94,98,92 Ewan,82,90,71,84 Guinnens,82,62,84,72 Rex,77,84,80,78 Duke,60,66,76,83 Stephan,67,62,60,87 Clifton,84,85,82,75 Tecwen,74,73,79,67 Adele,81,74,96,85