• 検索結果がありません。

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

N/A
N/A
Protected

Academic year: 2021

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

Copied!
33
0
0

読み込み中.... (全文を見る)

全文

(1)

1

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

第3回基本的なデータ構造

(リスト、スタック、キュー)

(2)

2

今年度の授業計画

日付 曜日 時間 担当者 内容

1 2019年4月4日 木曜日 2 喜田 ガイダンス

2 2019年4月9日 火曜日 4 喜田 アルゴリズムと計算量

3 2019年4月11日 木曜日 2 有村 基本的なデータ構造(1) リスト・スタック・キュー 4 2019年4月16日 火曜日 4 有村 基本的なデータ構造(2) ヒープ

5 2019年4月18日 木曜日 2 有村 基本的なデータ構造(3) 再帰アルゴリズム

6 2019年4月23日 火曜日 4 喜田 探索のためのデータ構造(1) 二分探索木・AVL木 7 2019年4月25日 木曜日 2 喜田 探索のためのデータ構造(2) 木の巡回

2019年4月30日 火曜日 祝日

2019年5月2日 木曜日 祝日

8 2019年5月7日 火曜日 4 有村 探索のためのデータ構造(3) 最適二分探索木 9 2019年5月9日 木曜日 2 有村 探索のためのデータ構造(4) ハッシュ

10 2019年5月14日 火曜日 4 喜田 整列のアルゴリズム(1)

11 2019年5月16日 木曜日 2 喜田 整列のアルゴリズム(2)

12 2019年5月21日 火曜日 4 喜田 グラフとネットワークのアルゴリズム(1)

13 2019年5月23日 木曜日 2 喜田 グラフとネットワークのアルゴリズム(2)

(3)

出席・試験・成績について

出席

毎回出席簿を付けます

欠席する場合は欠席届を提出してください

様式は工学部学生便覧の最終ページにあります 欠席届の無い場合は無断欠席とみなします

試験

科目最終回(16回目)に行う予定です 持ち込みは不可です

成績

シラバスの通りです

(授業への参加態度 10 %,レポート 20 %,学期末試験 70 %)

3

(4)

ビッグデータ,人工知能,・・・,アルゴリズム

ワトソン君

• IBM

リサーチ

(2011/02/16)

クイズ番組で人間に勝利!

• 100

万冊の本を読んで回答

人工知能と自然言語,

アルゴリズム,検索の技術で

米国の人気クイズ番組「ジョパディ!」のワトソン君 クイズ王に挑戦中

AlphaGo

• Google DeepMind

が開発したコンピ ュータ囲碁プログラム

• 2015

10

月にプロ囲碁棋士をハン ディなしで破った

• 2017

5

月には世界トップ棋士であ る柯潔(コ・ジェ)に勝利

• DNN

とモンテカルロ木探索

4

screenshot: DeepMind/YouTube

(5)

授業で学ぶデータ構造の範囲

機械語のデータ型

 レジスタ値とその番地

基本データ型

char, int, large int, double,

構造データ型

 配列( array ),構造体( struct

基本的データ構造

 リスト( linked list ),スタック( stack ),待ち行列

queue

先進的データ構造

 二分探索木( binary search tree ),平衡探索木

balanced search tree ),ハッシュ表( hash table

昔の言語も持って いる型( C ,

Pascal ) 機械語

(型がない)

最近の言語

( C++ , Java, etc. )

この「アルゴリズムとデー タ構造」で学ぶところ

「プログラミング」

5

(6)

データ構造

データ構造とは

セル (cell) の集合にある構造を与えたもの

データを格納する基本単位

Algorithms + Data Structures = Programs

Niklaus Wirth

(二クラウス・ビルト)が書いた本の題名

Niklaus Wirth(1934-)

はスイスの計算機科学者。

コンピュータ言語

Pascal

の設計者。

1984年にチューリング賞受賞。

(7)

抽象 データ型 (Abstruct Data Type) とは?

データ型を,それに適用される一組の操作で抽象的に 定めたもの.

データ 操作

Linked List

CREATE INSERT DELETE . . .

データ構造(の

API

)を「抽象データ型」ともいう.

データ構造には,「それは何か(

What

)」と「それをどのように実現す るか?(

How

)」の二つの面がある.

現代的なプログラム言語やライブラリーはこの考え方に基づく.(例:

C++

Java

Ruby, Python

などなど)

7 重要

(8)

前回の内容 : 第2回 アルゴリズムと計算量

(9)

よいアルゴリズムとは?

いろいろな性能

 計算時間

 メモリサイズ

 外部記憶への入出力数

 ネットワークの通信量

ほかの要素

 モジュラリティ Modularity

 再利用可能性 Reusability

 読みやすさ Readability

 移植しやすさ Portability

... ここでは,計算時間とメモリサイズで測る

計算時間 メモリサイズ

2016/04/07

9

(10)

第 3 回基本データ構造

 今日の内容:

リスト

配列/連結リスト/双連結リストによる実装

スタック

スタックの応用(再帰呼び出し)

キュー

 ポイント

ポインタを用いたデータ構造

抽象データ型とその実装

(11)

リストとは? (抽象データ型として)

 0個以上の要素を一列にならべたもの A

12

空リスト:要素を含まないリストのこと

リストの長さ:要素数 n

A

i

: 最初から i 番目の要素(1 ≦ i ≦ n )

リスト中の場所を指示するための「位置」をも つ

太 郎

二 郎

花 子

道 子

A

1

A

2

A

3

A

n

リストA

重要

(12)

リストに対する操作

 INSERT(x,p,L) : リスト L (要素数 n )の位置 p の次

の位置に要素 x を挿入

 DELETE(p,L) : リスト L の位置 p の次の位置の次

の要素を削除

 FIND(i,L) : リスト L i 番目のセルの内容を返す

 LAST(L) : リスト L の最後のセルの位置を返す

 PREVIOUS(p,L) : リスト L において、位置 p の1つ

前のセルの位置を返す

(13)

14

リスト

リストとは

要素を0個以上1列に並べたもの

(注意)リストは連結リストを指すことが多い

[

リスト

a0,a1,…,an-1

の実現法

] 1.

配列

(array)

2.

連結リスト

(linked list)

3.

双方向連結リスト

(doubly linked list)

a0 a1

・・・

an-1

n

個の連続領域に格納

an-1 null a1

a0

init

・・・

ポインタで次の要素の格納領域を指す

an-1 null a1

a0

init null

・・・ ・・・

final

ポインタで前後の要素の格納領域を指す

太 郎

二 郎

花 子

道 子

重要

(14)

復習:ポインタとは?

ポインタ ( pointer

 セルの位置を示すデータ

 機械語レベルでは、セルの番地そのもの

 プログラミングにおいては、その値を具体的に

知る必要はない。

(15)

ポインタは番地

16

ポインタ p

132 x

5

C 言語の場合

 ポインタ p が指す変数

の値 x を、 x = *p で表す。

 変数 x を指すポインタ p を p = &x で取り出せ る。

レジスタレベルでみた計算機

(16)

リスト

リストとは

要素を0個以上1列に並べたもの

(注意)リストは連結リストを指すことが多い

[

リスト

a0,a1,…,an-1

の実現法

] 1.

配列

(array)

2.

連結リスト

(linked list)

3.

双方向連結リスト

(doubly linked list)

a0 a1

・・・

an-1

n

個の連続領域に格納

an-1 null a1

a0

init

・・・

ポインタで次の要素の格納領域を指す

ポインタで前後の要素の格納領域を指す

太 郎

二 郎

花 子

(17)

リスト:

 配列 (array) による実装

18

a

1

a

2

a

3

a

4

配列

int a[100]; % 100

個の整数

a[0],a[1],…,a[99]

からなる配列

1.

配列

(array) n

個の連続領域に格納

a

0

a

1

・・・ a

n-1

0 1

・・・

n-1

n=4

(18)

リスト:連結リスト (linked list) による実装

要素を保持する「セル」をポインタでつないで,リストを表す.

途中への挿入削除を効率よくで行える

an null a1

head -1

・・・

ai-1 ai

・・・

a

1

a

2

a

3

a

4 n=4

セル

*

の構造体(

C

言語のコード)

typedef struct _cell { int element;

struct cell *next;

ダミーの セル

(head)

先頭

ai

cell

element next

セル

*

(箱図)

(19)

20

C 言語によるリストの定義 (1/3)

連結リスト

typedef struct cell { int element;

struct cell *next;

} cell;

cell *init=NULL; %

空のリスト

void list_add(int x)

{ %

整数要素

x

を先頭へ追加

cell *new=(cell *)malloc(sizeof(cell));

new->element=x;

new->next=init;

init=new;

}

struct cell {

・・・

}

: 構造体

cell

を・・・と定義

typedef

・・・

cell

: ・・・をデータタイプ

cell

として定義

init

cell

型データを指すポインタ型

sizeof(cell)

cell

型のデータサイズ(バイト)

malloc(n)

n

バイトのメモリーを確保

(cell *)malloc(n)

: 確保した

n

バイトの領域を

cell

型データ格納領域とみなす。

重要

ai

cell

要素

element cellnext

へのポインタ

(20)

C 言語によるリストの定義 (2/3)

typedef struct cell { int element;

struct cell *next;

} cell;

cell *init=NULL; %

空のリスト

void list_add(int x)

{ %

整数要素

x

を先頭へ追加

cell *new=(cell *)malloc(sizeof(cell));

new->element=x;

new->next=init;

init=new;

}

init

3 6

NULL

element

領域

next

領域

list_add(5)

を実行すると

new

①メモリの確保

new

5

element

の代入

init

3 6

next

init

ポインタ

new

をコピー

5 init

init

new

ポインタ

をコピー

(21)

23

C 言語によるリストの定義 (3/3)

双方向連結リスト

typedef struct cell {

int element;

struct cell *prev;

struct cell *next;

} cell;

cell *init=NULL; %

空のリスト

cell *final=NULL;

void list_add(int x)

{ %

整数要素

x

を先頭へ追加

cell *new=(cell *)malloc(sizeof(cell));

new->element=x;

new->next=init;

new->prev=NULL;

if(init==NULL) final=new;

else init->prev=new;

init=new;

}

cell

型は1つ前のデータを指す ポインタ

prev

ももつ

最後尾のデータを指す ポインタ

final

も必要

先頭に追加する場合は1つ前の データはなし

最初に格納されたデータが最後尾の データ(

final

が指すデータ

)

となる 2つ目以降に格納されたデータは

prev

ポインタを新しい先頭データを 指すように更新する

重要

(22)

連結リストが得意な処理(挿入)

INSERT(x,p,L) :

リスト

L

(要素数

n

)の位置

p

の次の位置に要素

x

を挿入

a0 a1

・・・

ai-1 ai

・・・

an-1 p

a0 a1

・・・

ai-1 x ai

・・・

an-1

最悪

/

平均

時間計算量は

Θ(n)

配列の場合

p

x

an-1 null a1

a0

init

・・・

ai-1 ai

・・・

an-1 null a1

a0

init

・・・

ai-1 ai

・・・

連結リスト の場合

最悪

/

平均時間計算量は

Θ(1)

an-1 null a0

init

null

・・・ ・・・

final

ai-1 ai

・・・ ・・・

a null a

init

null

・・・

final

a a

・・・

双方向連結リストの場合

p

重要

考えて みよう

(23)

25

連結リストが得意な処理(削除)

DELETE(p,L) :

リスト

L

(要素数

n

)の位置

p

の次の位置の次の要素を削除

a0 a1

・・・

ai-1 ai

・・・

an-1 p

a0 a1

・・・

ai-1 ai+1

・・・

an-1

最悪

/

平均

時間計算量は

Θ(n)

配列の場合

an-1 null ai-1

a0

init

・・・

ai ai+1

・・・

連結リスト

p

の場合

最悪

/

平均時間計算量は

Θ(1)

ai-1 ai ai+1

・・・ ・・・

双方向連結リストの場合

p

最悪

/

平均時間計算量は

Θ(1)

ai+1

an-1 null ai-1

a0

init

・・・

ai+1

・・・

・・・ ・・・

ai-1 ai+1

・・・ ・・・

・・・ ・・・

(24)

配列が得意な処理( i 番目の要素へのアクセス)

FIND(i,L) :

リスト

L

(要素数

n

)の

i

番目のセルの内容を返す

LAST(L) :

リスト

L

(要素数

n

)の最後のセルの位置を返す

PREVIOUS(p,L) :

リスト

L

(要素数

n

)において、位置

p

の1つ前のセルの位置を返す

a0 a1

・・・

ai-1 ai

・・・

an-1

配列の場合

an-1 null ai-1

a0

init

・・・

ai ai+1

・・・

連結リスト の場合

双方向連結リストの場合

ai+1

FIND(i,L) : Θ(1) a LAST(L) : Θ(1)

PREVIOUS(p,L) : Θ(1)

p

FIND(i,L) LAST(L) PREVIOUS(p,L)

FIND(i,L) : Θ(n), LAST(L) : Θ(n), PREVIOUS(p,L) : Θ(n)

p

連続領域であるため

i

番目の要素や前後の要素に1ステップでアクセス可能

PREVIOUS(p,L) LAST(L)

FIND(i,L)

an-1 null a0

init

null

・・・ ・・・

final

ai-1 ai

・・・ ・・・

p

(25)

27

配列による連結リストの実現

a1 a0 a2 an-1

・・・

an-2

2 4 6 1 9 -1 7

・・・

m-1 5 -1

0 1 2 3 4 5 6 m-3 m-2 m-1

free_init 0 init 3

メリット

メモリー確保、解放の時間を節約できる。

メモリー使用量を制御できる。

ガベージコレクションの必要がない。

ちょっとむずか しい!

(26)

スタックとキュー

特別な(制限された)リストのいろいろ

28

(27)

29

スタック (stack)

スタックとは

要素の挿入、削除がいつも先頭からなされるリスト

LIFO(last-in-fast-out) [

基本操作

]

TOP(S)

スタック

S

の先頭の位置を返す

POP(S)

スタック

S

の先頭の要素を削除

PUSH(x,S)

スタック

S

の先頭に要素

x

を挿入

a0 a1

a2 PUSH(a

2,S)

a0 a1 a2

a0 a1

a2

POP(S) TOP(S)

重要

(28)

スタックの実現法

a0 a1

・・・

ai

・・・

i

すべての操作の 時間計算量は

Θ(1)

配列による実現

a0 null ai

top

・・・

連結リストによる実現

すべての操作の 時間計算量は

Θ(1)

top

S

=TOP(S)

a0 a1

・・・

ai

・・・

i+1 top

S ai+1

PUSH(ai+1,S) POP(S)

ai-1 TOP(S)=

a0 null ai

top ai-1

・・・

PUSH(ai+1,S) POP(S)

重要

(29)

31

スタックの応用例(関数呼び出し)

プログラム(階乗

n!

の計算)

int factorial(int n) { if(n==1) return 1;

else return n*factorial(n-1);

}

実行コードシークエンス

1: if n≠1 then goto 3 2: return 1

3: r=factorial(n-1) 4: return n*r

局所変数

n 3

実行コード

1:

2:3:

4:

実行アドレス

3

n 2

1:2:

3:4:

n=3,

戻り

:4

スタック

n 1:2:

3:4:

n=3,

戻り

:4 n=2,

戻り

:4

n=3,

戻り

:4

スタック

3

3 1:2:

3:4: 4

1

2

n 2

1:2:

3:4: 4

n

factorial(3) factorial(2)

factorial(1)

3

6

(30)

待ち行列(キュー)とは?

要素の挿入は最後尾、削除は先頭からなされるリスト

FIFO(fast-in-fast-out) ともいう

[ 基本操作 ]

TOP(Q) キュー Q の先頭の位置を返す

ENQUEUE(x,Q) 要素 x をキュー Q の最後尾に入れる

A 1 , A 2 , . . . , A n

C D E F A B

G H I

重要

(31)

33

待ち行列 ( キュー , queue)

待ち行列 ( キュー)とは

要素の挿入は最後尾、削除は先頭からなされるリスト

FIFO(fast-in-fast-out) [

基本操作

]

TOP(Q)

キュー

Q

の先頭の位置を返す

ENQUEUE(x,Q)

要素

x

をキュー

Q

の最後尾に入れる

DEQUEUE(Q)

先頭の要素をキュー

Q

から除く

a0 a1 ENQUEUE(aa2 2,Q)

a0 a1 a2 TOP(Q)

a0 a1 a2

DEQUEUE(Q)

(32)

キューの実現法

・・・

a0

・・・

j

すべての操作の 時間計算量は

Θ(1)

配列による実現

ai null a0

front

・・・

連結リスト による実現

front

Q

TOP(Q)

ENQUEUE(ai+1,Q)

a1 TOP(Q)=

ai a0

front a1

・・・

ai+1

ENQUEUE(ai+1,S)

ai

・・・

=

(j+i)%n

0 rear n-1

DEQUEUE(Q)

a1

・・・

a0

・・・

front

Q ai

・・・

(j+i+1)%n

0 rear n-1

a1 ai+1

・・・ ・・・

(j+1)%n front

ai

・・・

(j+i+1)%n

0 rear n-1

a1 ai+1

j

rear

null rear

DEQUEUE(Q)

すべての操作の

時間計算量は

(33)

A

4

A

5

A

1

A

2

A

3

0 1 2 3 4 5

front rear

配列で巡回リストを表わす.

キューの長さ

n

が限定された場合

先頭と末尾がつながって,輪になったリスト

要素の位置を,

n

の剰余演算で決定.

配列によるキューの実現

front から i 番目の要素 = Element[ (front + i) mod n ]

Element

ex. Elem[(head + 5) mod n] (head = 1 and n = 6)

= Elem[7 mod 6] = E[1]

35 考えて

みよう

参照

関連したドキュメント

l 「指定したスキャン速度以下でデータを要求」 : このモード では、 最大スキャン速度として設定されている値を指 定します。 有効な範囲は 10 から 99999990

WAV/AIFF ファイルから BR シリーズのデータへの変換(Import)において、サンプリング周波 数が 44.1kHz 以外の WAV ファイルが選択されました。.

【通常のぞうきんの様子】

データなし データなし データなし データなし

[r]

試用期間 1週間 1ヶ月間 1回/週 10 分間. 使用場所 通常学級

最終的な認定データおよび特性データは最終製品 / プロセス変更通知 (FPCN) に含まれます。この IPCN は、変 更実施から少なくとも 90

a.と同一の事故シナリオであるが,事象開始から約 38 時間後に D/W ベン トを実施する。ベント時に格納容器から放出され,格納容器圧力逃がし装置 に流入する