THE UNIVERSITY OF TOKYO 数理情報工学演習第一C プログラミング演習 (第4回 ) 2014/04/28 DEPARTMENT OF MATHEMATICAL INFORMATICS 1 THE UNIVERSITY OF TOKYO 今日の内容: リスト 疎行列の演算 課題:リスト,疎行列 2 THE UNIVERSITY OF TOKYO mallocを簡単に エラーチェックを毎回書くのは面倒なので… double *p; p = malloc(sizeof(double)); if (p == NULL) { printf("not enough memory.∖n"); exit(1); } プログラムの最初の方でマクロを定義 #define mymalloc(p,n) {p = malloc((n)*sizeof(*p)); if ((p)==NULL) {printf("not enough memory∖n"); exit(1);};} 注: 改行は入れない 使うときは double *p; mymalloc(p,n); // doubleで n 個分の領域を確保し,ポインタを p に入れる 3 THE UNIVERSITY OF TOKYO 連結リスト (Linked Lists) オブジェクトをある線形順序に並べて格納するデータ構造 単方向連結リスト (signly linked list) L の要素 x キーフィールド key ポインタフィールド next x->next: リスト中の x の直後の要素のポインタ x->next = NIL のとき,x は最後の要素 L->head: リストの先頭の要素のポインタ L->head = NIL のとき,リストは空 key L 4 9 16 next NIL 4 THE UNIVERSITY OF TOKYO 単方向リストの構造体 リストの要素 typedef struct slobj { struct slobj *next; // 後の要素へのポインタ data key; // キー } slobj; 単方向リスト typedef struct { lobj *head; } slist; 5 // 先頭要素のポインタ THE UNIVERSITY OF TOKYO 連結リストの探索 slist_search(L, k): リスト L に属する,キー k を持つ最初の要素の ポインタを返す キー k を持つ要素が存在しなければ NULL を返す slobj *slist_search(slist *L, data k) { slobj *p; p = L->head; while (p != NULL && p->key != k) { p = p->next; } return p; } key next L 6 9 16 NIL 4 THE UNIVERSITY OF TOKYO 連結リストの先頭への挿入 slist_insert_head(L, p): p を L の先頭に挿入 p のキーは既にセットされているとする void slist_insert_head(slist *L, slobj *p) { p->next = L->head; L->head = p; } p 9 L 7 L 9 16 4 16 4 THE UNIVERSITY OF TOKYO 連結リストの中間への挿入 slist_insert(L, r): r を L に挿入 挿入場所は (p->key) < (r->key) となる最初の p の直後 つまり,リストの要素は常に key の小さい順に並んでいる r 2 8 L 1 3 L 1 2 3 THE UNIVERSITY OF TOKYO リストを先頭から探索し,挿入場所を決める 挿入場所がリストの先頭かそれ以外かで処理を変える必要あり r 2 9 L 1 3 L 1 2 3 THE UNIVERSITY OF TOKYO 課題(初級) x を含むリストの要素を作成 slobj *make_slobj(data x); 空のリストの作成 slist *make_slist(void); リストの中身を画面に表示する void slist_print(slist *L) リストから,k を含む要素を探索 slobj *slist_search(slist *L, data k) リストに r を挿入.ソート順を保つ void slist_insert(slist *L, slobj *r) 10 THE UNIVERSITY OF TOKYO リストを用いた疎行列の表現 R • 密行列の表現 1 3 2 6 – 各行は,1次元配列 8 5 4 1 – 行列は,(行へのポインタ)の1次元配列 R 9 2 3 1 • 疎行列の表現 – 各行は,非零要素のリスト – 行列は,(行を表すリスト)の1次元配列 R R 1, 3.0 5, 1.0 2, 1.0 3, 1.0 11 4, 2.0 THE UNIVERSITY OF TOKYO • 行の配列 R の実現方法は2つある 1. (slistのポインタ)の配列 • slist **R; slistの配列: slist R[10]; // サイズ固定 slist *R; // サイズ可変 slistのポインタの配列: slist *R[10]; slist **R; 2. (slobjのポインタ)の配列 • 12 slobj **R; • 1. の方が楽(これまでのプログラムをそのまま使える)だが, 2. の方が多少効率がよい. • 2. では,i 行目のリストの先頭要素は R[i]->head ではなく R[i] になる THE UNIVERSITY OF TOKYO リストと行列の要素を変更 typedef struct slobj { struct slobj *next; // 後の要素へのポインタ int j; // j 列目 data v; // 値 } slobj; リストに挿入する際は,値の小さい順ではなく,j の小さい順にする typedef struct { int n,m; slist **R; } smatrix; 13 THE UNIVERSITY OF TOKYO 課題(中級) 零行列を作る smatrix *smatrix_new(int n, int m) 行列 S の (i,j) 要素を x にする void smatrix_insert(smatrix *S, int i, int j, data x) 挿入前の (i,j) 要素は 0 と仮定してよい 行列 S の (i,j) 要素を求める data smatrix_access(smatrix *S, int i, int j) (i,j) 要素がリストになければ 0 を返す 14 THE UNIVERSITY OF TOKYO 課題(上級) 疎行列をファイルから読み込み,新たに確保した疎行列に代入 smatrix *smatrix_read(char *filename); 疎行列を入力と同じ形式でファイルに出力 void smatrix_write(char *filename, smatrix *a); 2つの疎行列 A, B の積を計算し,新たに確保した疎行列 C に代入 smatrix *product(smatrix *A, smatrix *B); 行列のサイズが合わないときは C は確保せずに NULL を返す 演算の効率も考慮する 疎行列のメモリを開放する void smatrix_free(smatrix *A); 15 THE UNIVERSITY OF TOKYO 行列のファイル形式 5 1 1 2 4 5 5 1.0 2.0 2.0 1.0 1.0 2 2.0 -1 2 1.0 3 2.0 -1 3 1.0 -1 -1 -1 行数 列数 1行目 2行目 3行目 4行目 5行目 0 0 1.0 2.0 0 0 2.0 1.0 2.0 0 0 2.0 1.0 0 0 0 0 1.0 0 0 0 0 0 0 1 . 0 各要素は 列の位置と要素の値で表現される 行の最後には -1 を書く 16 THE UNIVERSITY OF TOKYO 課題の提出: 初級:本日(4/28)の18時までに提出 • 宛先:[email protected] – 中級:5/7までに提出 • 宛先:[email protected] – 上級:5/7まで(できる人だけ) • 宛先:中級と同じ 17 THE UNIVERSITY OF TOKYO
© Copyright 2025 ExpyDoc