情報工学概論 (アルゴリズムとデータ構造)

Slides:



Advertisements
Similar presentations
1 T HE U NIVERSITY OF T OKYO D EPARTMENT OF M ATHEMATICAL I NFORMATICS 数理情報工学演習第一C プログラミング演習 ( 第 6 回 ) 2014/05/19.
Advertisements

Generic programming と STL
プログラミング演習II 2004年11月 30日(第6回) 理学部数学科・木村巌.
5.データ構造入門 5-1.連結リスト(Linked List) 5-2.スタック(Stack) 5-3.キュー(Queue)
第11回 整列 ~ シェルソート,クイックソート ~
データ構造とアルゴリズム 第10回 mallocとfree
基本情報技術概論(第4回) 埼玉大学 理工学研究科 堀山 貴史
2章 データ構造.
情報システム基盤学 基礎1 アルゴリズムとデータ構造
オペレーティングシステムJ/K 2004年11月4日
情報工学概論 (アルゴリズムとデータ構造)
アルゴリズムとデータ構造 第3回基本的なデータ構造(リスト) 2015/10/28 アルゴリズムとデータ構造 2015.
データ構造とアルゴリズム 第4回 リスト ~ データ構造(1)~.
第5回 ポインタによるリスト、 循環・重連結リスト
プログラミング論 II 電卓,逆ポーランド記法電卓
データ構造とアルゴリズム 第13回 スタックとキュー
データ構造とアルゴリズム 第5回 スタック ~ データ構造(2)~.
Stack & Queue & List 3.
アルゴリズムと データ構造 第4回 スタック・キュー.
エージェントを管理するボスの苦悩 問題 n人のエージェントを部下に持つボスがいる. エージェントは出張・帰還を頻繁に繰り返す.
アルゴリズムとデータ構造 第2回 線形リスト(復習その2).
アルゴリズムとデータ構造 第4回 配列によるスタックとキュー.
①データ構造 ②アルゴリズム ③プログラム言語 ④マークアップ言語
データ構造と アルゴリズム 第八回 知能情報学部 新田直也.
データ構造と アルゴリズム 第十一回 理工学部 情報システム工学科 新田直也.
データ構造と アルゴリズム 第四回 知能情報学部 新田直也.
第11回 整列 ~ シェルソート,クイックソート ~
第13回 ハッシュテーブルを使ったプログラム ~高速に検索するには?~.
データ構造とプログラミング技法 (第2回) ー線形構造ー.
2009/10/16 いろいろなデータ構造 第3講: 平成21年10月16日 (金) 4限 E252教室 コンピュータアルゴリズム.
茨城大学 工学部 知能システム工学科 井上 康介 E2棟801号室
算法数理工学 第3回 定兼 邦彦.
データ構造とアルゴリズム 第4回 リスト ~ データ構造(1)~.
データ構造とアルゴリズム 第5回 スタック ~ データ構造(2)~.
データ構造とアルゴリズム (第2回) ー線形構造ー.
データ構造とアルゴリズム 第6回 キュー ~ データ構造(2)~.
情報工学概論 (アルゴリズムとデータ構造)
データ構造と アルゴリズム第4回 知能情報学メジャー 和田俊和.
プログラミング言語論 第13回 オブジェクト指向 情報工学科 篠埜 功.
第9回 優先度つき待ち行列,ヒープ,二分探索木
アルゴリズムとデータ構造1 2005年7月1日
アルゴリズムとデータ構造1 2009年6月29日
データ構造と アルゴリズム 第六回 知能情報学部 新田直也.
データ構造と アルゴリズム 第五回 知能情報学部 新田直也.
Cプログラミング演習 第10回 二分探索木.
アルゴリズムとデータ構造1 2005年7月5日
プログラミング 4 木構造とヒープ.
プログラミング 3 スタックとキュー.
算法数理工学 第8回 定兼 邦彦.
明星大学 情報学科 2012年度 後期   情報技術Ⅱ   第8回
アルゴリズムとデータ構造 2011年7月8日課題の復習
簡易データベース 情報画像工学実験 I : 実験2 担当:関屋大雄(工学部1号棟515室)
スタックとキュー データ構造とプログラミング (第5回).
基本情報技術概論I (第4回) 埼玉大学 理工学研究科 堀山 貴史
6.データ構造入門 6-1.連結リスト(Linked List) 6-2.スタック(Stack) 6-3.キュー(Queue)
算法数理工学 第7回 定兼 邦彦.
情報数理Ⅱ 第11章 データ構造 平成29年1月18日.
データ構造とアルゴリズム (第3回) 静岡大学工学部 安藤和敏
第9回 優先度つき待ち行列,ヒープ,二分探索木
アルゴリズムからプログラムへ GRAPH-SEARCH
オペレーティングシステムJ/K (管理のためのデータ構造)
アルゴリズムとデータ構造1 2006年6月23日
情報工学概論 (アルゴリズムとデータ構造)
第11回放送授業.
アルゴリズムとデータ構造1 2009年6月15日
アルゴリズムとデータ構造 補足資料11-3 「線形リストのオペレータ」
アルゴリズムとデータ構造 2010年6月17日
データ構造と アルゴリズム 第四回 知能情報学部 新田直也.
データ構造と アルゴリズムI 第三回 知能情報学部 新田直也.
TList リスト構造とは? 複数のデータを扱うために、 データの内容と、次のデータへのポインタを持つ構造体を使う。
Presentation transcript:

情報工学概論 (アルゴリズムとデータ構造) 第5回

11.1 スタックとキュー 動的集合,挿入と削除をサポートする スタック (stack) では,DELETEでは最後に挿入された要素が取り除かれる 後入れ先出し (last-in, first-out; LIFO) という キュー (queue) では,最初に挿入された要素が取り除かれる 先入れ先出し (first-in, first-out; FIFO) という

スタック (Stack) INSERT, DELETEの代わりにPUSH, POPと呼ぶ 9 2 6 15 PUSH(S,x): 集合 S に要素 x を加える. POP(S): S から最後に PUSH された要素を削除し, その要素を返す PUSH(S,15) POP(S) 15 6 9 2 9 2 6 15

配列によるスタックの実装 最大 MAX 要素を格納できるスタックを実装 スタックを表す構造体 要素は S[1..top] に格納される S: 要素を格納するサイズMAXの配列(へのポインタ) MAX: 配列 S のサイズ 要素は S[1..top] に格納される S[1]: スタックの底 S[top]: スタックの最上部 top  MAX typedef int data; typedef struct { int top; int MAX; data *S; } stack;

実装例 PUSH(S,x) POP(S) topを1増やし,x を配列に入れる topがMAXを超えたらエラー O(1) 時間 スタックが空ならエラー サイズを1減らし,最上部の要素を返す O(1) 時間 void PUSH(stack *s,data x) { if (s->top == s->MAX) { printf("オーバーフロー\n"); exit(1); } s->top = s->top + 1; s->S[s->top] = x; data POP(stack *s) { if (STACK_EMPTY(s)) { printf("アンダーフロー\n"); exit(1); } s->top = s->top - 1; return s->S[s->top + 1];

その他の関数 STACK_EMPTY(S) MAKE_STACK(size) スタックが空なら1を返す O(1) 時間 int STACK_EMPTY(stack *S) { if (S->top == 0) return 1; else return 0; } stack *MAKE_STACK(int size) { stack *s; data *S; s = malloc(sizeof(stack)); S = malloc((size+1)*sizeof(data)); s->top = 0; s->MAX = size; s->S = S; return s; }

キュー (Queue) INSERT, DELETEの代わりにENQUEUE, DEQUEUEと呼ぶ 人の並んだ列と同じ 15 6 2 9 DEQUEUE(Q) Q ENQUEUE(Q,x) 15 6 2 9

配列によるキューの実装 最大 MAX1 要素を格納できるキュー キューを表す構造体 Q: 要素を格納する配列 MAX: 配列 Q のサイズ head: キューの先頭の位置 tail: 次に追加される位置 typedef struct { int head; int tail; int MAX; data *Q; } queue; 1 2 3 4 5 6 7 8 9 10 11 12 15 6 9 8 4 head tail

環状バッファ (Ring Buffer) 配列 Q の右端と左端はつながって輪になっていると考える Q[MAX] の右は Q[1] だとみなす 要素は Q[head..MAX] Q[1..tail1] に格納される DEQUEUEの際に全要素を左にずらす必要がない 1 2 3 4 5 6 7 8 9 10 11 12 3 5 15 6 9 8 4 17 tail head

空のキューの作成 MAKE_QUEUE(size) size 個の要素を格納できる空のキューを作成 queue *MAKE_QUEUE(int size) { queue *q; data *Q; size = size+1; q = (queue *)malloc(sizeof(queue)); Q = (data *)malloc((size+1)*sizeof(data)); q->head = 1; q->tail = 1; q->MAX = size; q->Q = Q; return q; }

実装例 ENQUEUE(Q,x) DEQUEUE(Q) x をQ[tail]に入れる tailを1増やす O(1) 時間 Q[head]を取り出す headを1増やす O(1) 時間 void ENQUEUE(queue *q,data x) { q->Q[q->tail] = x; if (q->tail == q->MAX) q->tail = 1; else q->tail = q->tail + 1; } data DEQUEUE(queue *q) { data x; x = q->Q[q->head]; if (q->head == q->MAX) q->head = 1; else q->head = q->head + 1; return x; } 注: オーバーフロー, アンダーフロー 処理は省略してある

11.2 連結リスト (Linked Lists) オブジェクトをある線形順序に並べて格納するデータ構造 連結リストでの線形順序は,オブジェクトが含むポインタで決定される 双方向連結リスト (doubly linked list) L の要素 キーフィールド key ポインタフィールド prev, next (付属データ) key next NIL head(L) 9 16 4 prev

next(x): リスト中の x の直後の要素のポインタ prev(x): x の直前の要素のポインタ next(x) = NIL のとき,x は最後の要素 prev(x): x の直前の要素のポインタ prev(x) = NIL のとき,x はリストの最初の要素 head(L): リストの先頭の要素のポインタ head(L) = NIL のとき,リストは空 NIL head(L) 9 16 4 prev

リストの種類 一方向 (singly linked) と双方向 (doubly linked) 既ソート (sorted) と未ソート 一方向のとき,各要素は prev を持たない 既ソート (sorted) と未ソート 既ソート: リストの線形順序はキーの線形順序に対応 未ソート: 任意の順序 循環 (circular list) と非循環 循環: リストの先頭要素の prev はリストの末尾を指し,末尾の next はリストの先頭を指す 以下では未ソート双方向(連結)リストを扱う

双方向リストの構造体 リストの要素 双方向リスト typedef struct lobj { struct lobj *prev; // 前の要素へのポインタ struct lobj *next; // 後の要素へのポインタ data key; // キー } lobj; typedef struct { lobj *head; // 先頭要素のポインタ } dllist;

省略記法 #define HEAD(L) (L->head) #define KEY(x) (x->key) #define NEXT(x) (x->next) #define PREV(x) (x->prev) #define NIL NULL

連結リストの探索 LIST_SEARCH(L, k): リスト L に属する,キー k を持つ最初の要素のポインタを返す キー k を持つ要素が存在しなければ NIL を返す (n) 時間 lobj *LIST_SEARCH(dllist *L, data k) { lobj *x; x = HEAD(L); while (x != NIL && KEY(x) != k) { x = NEXT(x); } return x; 9 16 4 head(L)

連結リストへの挿入 LIST_INSERT(L, x): x を L の先頭に挿入 O(1) 時間 x のキーは既にセットされているとする void LIST_INSERT(dllist *L, lobj *x) { NEXT(x) = HEAD(L); if (HEAD(L) != NIL) PREV(HEAD(L)) = x; HEAD(L) = x; PREV(x) = NIL; } 9 16 4 head(L) x 9 16 4 head(L)

連結リストからの削除 LIST_DELETE(L, x): L から x を削除 O(1) 時間 head(L) head(L) void LIST_DELETE(dllist *L, lobj *x) { if (PREV(x) != NIL) NEXT(PREV(x)) = NEXT(x); else HEAD(L) = NEXT(x); if (NEXT(x) != NIL) PREV(NEXT(x)) = PREV(x); } 9 16 4 head(L) x head(L) 9 4

双方向リストによる辞書の計算量 挿入 削除 キーの検索 常にリストの先頭に入れるので O(1) 時間 リストの要素を1つずつ見ていくので最悪 O(n) 時間 n: リスト長 (要素数) 既ソートリストでもリストの先頭から見ていくしか ないので O(n) 時間

一方向リストによる辞書の計算量 挿入 削除 キーの検索 常にリストの先頭に入れるので O(1) 時間 削除する要素のポインタが与えられても,リストの 1つ前の要素が分からないので O(n) 時間 キーの検索の際に,目的の要素の1つ前の要素を 求めるようにしておけば,削除は O(1) 時間 キーの検索 O(n) 時間