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

Microsoft PowerPoint - IntroAlgDs ppt [互換モード]

N/A
N/A
Protected

Academic year: 2021

シェア "Microsoft PowerPoint - IntroAlgDs ppt [互換モード]"

Copied!
18
0
0

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

全文

(1)

アルゴリズムとデータ構造入門-14 2008年1月15日

奥 乃 博

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

Sorting(整列)

Hashing(ハッシュ法)

1

祝 成人の日

12年前の17日

阪神・淡路大震災

犠牲者死者だけで6434人

天災は忘れた頃にやってくる

(寺田寅彦)

天才は忘れた頃にやってくる

(奥乃博) (Asahi.comより転載)

1月15日・本日のメニュー

1.

vector (ベクタ)

2.

Sorting (整列)

3.

hashing(ハッシュ法)

4

アンケート(最後の

15分)

2

4.

アンケート(最後の

15分)

„

配布する用紙に名前を記入して下さい。

„

回収は学生同士で。

„

教員は一切タッチしません。(退場!)

„

内部整列(

internal sorting)

データはすべて主記憶上に置いて整列

1.

作業領域を極力減らす。

2

比較回数を極力減らす

Sorting (整列)

3

2.

比較回数を極力減らす。

„

外部整列(

external sorting)

外部の記憶装置を用いて整列

3.

主記憶と補助記憶との間でのデータ転

送回数を極力減らす。

(2)

„

逐次入力型

挿入ソート(insertion sort)

ヒープソート(

heap sort)

„

バッチ型

Internal Sorting(内部整列)

4 „

バッチ型

クイックソート(quick sort)

バブルソート(

bubble sort)

„

その他(外部整列と共通)

マージソート(

merge sort、併合ソート)

„

pivotのとり方は工夫が必要

„

すでに並んでいる場合には、最小あるい

は最大要素を

pivot に取ると最悪。

„

適切な

pivot を取れば

クイックソートの補足

5 „

適切な

pivot を取れば、

„

リスト使用の場合は、

pivot 選択がリスト

辿りが必要。コストが重い。

„

ベクタ使用の場合には、コストが軽い。

)

log

(

n

n

Θ

新しいデータ型:ベクタ(

vector)

„

データの並びを表現するデータ型

„

#(《要素

0

… 《要素

n-1

》)

„

インデックス(

index)は0から始まる(

0-origin

)

„

《要素 》 は任意のデータ

6

„

いわゆる

1次元配列(

array

„

Constructor(構築子)

(

make-vector

〈サイズ〉 [〈データ〉])

(

vector

〈データ

0

〉 ・・・ 〈データ

n-1

〉)

(

list->vector

〈リスト〉)

(3)

新しいデータ型:ベクタ(

vector)(続)

„

Selectors(選択子)

(

vector-ref

〈ベクタ〉 〈インデックス〉)

„

その他

(

vector-length

〈ベクタ〉)

7

サイズを返す

(

vector-set!

〈ベクタ〉 〈インデックス〉〈データ〉)

(

vector->list

〈ベクタ〉)

入出力は

#(1 2 3 4 5)

ベクタ(

vector)の例

„

(define y (make-vector 5))

#(() () () () ())

„

(define x #(1 2 3 4 5))

#(1 2 3 4 5)

„

(vector-length x)

5

8

„

(vector length x)

5

„

(vector-ref x 2) 3

„

(vector-set! x 3 128)

#(1 2 3 128 5)

„

x

#(1 2 3 128 5)

„

(vector-set! x 0 'foo)

#(foo 2 3 128 5)

1月15日・本日のメニュー

„

ベクターというデータ構造

„

Sorting (整列)

1.

ヒープソート(heap sort)

2.

バブルソート(

bubble sort)

9

3.

マージソート(merge sort)

„

hashing(ハッシュ法)

„

アンケート(最後の

15分)

配布する用紙に名前を記入して下さい。

回収は学生同士で。

教員は一切タッチしません。

(4)

ピープ(

heap)というデータ構造

„

ヒープとは2分木の特殊形

„

ヒープの高さをhとすると

1.

高さh-1 までは完全2分木

2.

高さh

の葉は左詰

h

h-1

10

3.

親ノードの値 v

p

子ノードの値 v

c

とすると

v

p

pred v

c

が成立。 pred は比較

„

ベクタで実現する

ピープ(

heap)のベクタ表現

„

ヒープの高さをhとすると

高さh-1 までは完全2分木

高さh の葉は左詰

„

ベクタ利用の利点

h

h-1

i

2i 2i+1

11

2

i

+1

2i

i

クタ利用の利点

親のインデックスを

i

子のインデックスは

2i, 2i+1

2i 2i+1

サイ

0

ピープの諸演算・手続き

(define (make-heap maxsize)

(let ((heap (make-vector (+ maxsize 1)))) (vector-set! heap 0 0)

heap )))

(define (heap-size heap) (vector-ref heap 0)) (define (heap-left-child n) (* n 2))

(define (heap-right-child n) (+ (* n 2) 1))

12

(define (heap-parent n) (quotient n 2)) (define (heap-top heap) (vector-ref heap 1)) (define (heap-size-set! heap n)

(vector-set! heap 0 n) )

2i+1

2i

i

サイ

0

(5)

insert-heap (ピープに要素挿入)

(define (insert-heap heap element pred) (let ((n (+ (heap-size heap) 1)))

(vector-set! heap n element) (heap-size-set! heap n) (sift-up heap n element pred) element )) 13

sift-upでは、

高さが1つずつ

減少。

sift-up(heap修復)

(define (sift-up heap from element pred) (if (<= from 1)

element

(let ((parent (heap-parent from))) (let ((value (vector-ref heap parent)))

(cond

14

((pred value element) element) (else

(vector-set! heap from value) (vector-set! heap parent element) (sift-up heap parent element

pred )))))))

„

1回繰り返すと高さが1減少

„

要素数を n とすると計算量は

Θ

(log n

)

最大要素の抽出と

heap 修復

(define (heap-extract-top heap pred) (let* ((value (heap-top heap))

(n (heap-size heap))

(element (vector-ref heap n)) )

(heap-size-set! heap (- n 1)) (vector-set! heap 1 element)

(sift-down heap 1 (- n 1) element pred)

value )) 15 value ))

sift-downで

は、高さが1つ

ずつ増加。

(6)

sift-down(heap修復)

(define (sift-down heap from to element pred)

(let ((left-child (heap-left-child from)) (right-child (heap-right-child from)) ) (if (or (>= from to) (> left-child to))

element

(let ((max-child

(if (> right-child to) left-child (if (pred

(vector-ref heap left-child) ( t f h i ht hild) )

16 (vector-ref heap right-child) ) left-child

right-child )))) (let ((max-child-value

(vector-ref heap max-child))) (cond ((pred element max-child-value)

element) (else

(vector-set! heap from

max-child-value) (vector-set! heap max-child element) (sift-down heap max-child to

element pred ))))))))

heap-sort の計算量

„

1回繰り返すと高さが1増加

„

要素数を

とすると計算量は

)

(log n

Θ

17 heapify-downward では、高さが1ずつ増加。

ヒープソート(

heap-sort)

(define (heap-sort records . args)

(let ((pred (if (null? args) >= (car args))) (heap (make-heap 100))

(result ()) ) (for-each

(lambda (i) (insert-heap heap i pred)) records)

18

)

(do ((i (length records) (- i 1)) (result nil) )

((<= i 0) (reverse result)) (set! result

(cons (heap-extract-top heap pred) result )))))

(7)

ヒープソート(

heap-sort)の正しさ

„

ベクタ x のヒープ成立条件 heap(m,n)

„

sift-down では

実行前

h

(1 ) の成立は?

[

m

n

] [ ] [ ]

x

i

x

i

i

+

1

,

2

19

実行前: heap(1,n) の成立は?

実行後: heap(1,3) が成立。

„

k回目の

sift-down では

実行前:heap(1,k)は成立, heap(k,n) ?

実行後:heap(k,2k+1) が成立。

つまり, heap(1,2k+1) が成立。

ヒープソート(

heap-sort)の正しさ

(2)

„

ベクタ x のヒープ成立条件 heap(m,n)

„

sift-up では

実行前 h

(1 ) 成立

[

m

n

] [ ] [ ]

x

i

x

i

i

+

1

,

2

20

実行前:heap(1,n) 成立,

heap((n+1)/2,n+1) だけが?

実行後:heap((n+1)/4,(n+1)/2) は?

„

k回目の

sift-up では

実行前:heap(k/2,k)? 他は成立。

実行後:heap(k/2,n) 成立, heap(k/4,k/2) ?

1月15日・本日のメニュー

„

ベクターというデータ構造

„

Sorting (整列)

1.

ヒープソート(heap sort)

2.

バブルソート

21

3.

マージソート

„

hashing(ハッシュ法)

„

アンケート(最後の

15分)

配布する用紙に名前を記入して下さい。

回収は学生同士で。

教員は一切タッチしません。

(8)

バブルソート(

bubble sort)

(define (bubble-sort records . args)

(let ((pred (if (null? args) >= (car args))) (size (vector-length records)) ) (do ((i 0 (+ i 1))) ((>= i size) records) (do ((j (- size 1) (- j 1)) (data nil) ) 22 (data nil) ) ((<= j i))

(set! data (vector-ref records j)) (cond ((pred data

(vector-ref records (- j 1)) ) (vector-set! records j (vector-ref records (- j 1)) ) (vector-set! records (- j 1) data) ))))))

1 9 2 5 3 0 8 7 4

9 1 8 2 5 3 0 7 4

9 8 1 7 2 5 3 0 4

バブルソート(

bubble sort)実行トレース

8 0

8 3

8 5

8 2

9 1

7 0

7 3

7 5

7 2

4 0

8 1

4 3

5 2

7 1

23

9 8 7 1 5 2 4 3 0

9 8 7 5 1 4 2 3 0

9 8 7 5 4 1 3 2 0

9 8 7 5 4 3 1 2 0

9 8 7 5 4 3 2 1 0

1回ごとに敷居( )が1つずつ減る

バブルソート(

bubble sort)の計算量

)

1

(

2

1

)

1

(

1

=

=

n

n

i

n i 24 1 = i

)

(

n

2

Θ

(9)

シェルソート(

Shell sort)

„

バブルソート: 隣接データを比較

h=1

„

飛び飛び(h)に比較

25

h

k

= 3h

k-1

+ 1, …, 1 の時

e.g., 40, 13, 4, 1

)

(

n

1

.

25

Θ

1.

最悪の場合(worst case) (predが≧とする)

„

小さいものから順に入ってくる

„

比較回数は

2

最良の場合(best case)

挿入ソート(

insert sort)の計算量

) 1 ( 2 1 ) 1 ( 1 − = −

= n n i n i

(

)

2

n

Θ

26

2.

最良の場合(best case)

„

大きなものから順に入ってくる

„

比較回数は

3.

平均の場合(average case)

„

すでに入っているデータの半分だけ比較

„

比較回数は

) 1 ( 1 2 − =

= n n i

)

(n

Θ

) 1 ( 4 1 ) 1 ( 2 1 1 − = −

= n n i n i

(

)

2

n

Θ

1月15日・本日のメニュー

„

ベクターというデータ構造

„

Sorting (整列)

1.

ヒープソート(heap sort)

2.

バブルソート(

bubble sort)

27

3.

マージソート(

merge sort)

„

hashing(ハッシュ法)

„

アンケート(最後の

15分)

配布する用紙に名前を記入して下さい。

回収は学生同士で。

教員は一切タッチしません。

(10)

„

ソート済みのデータを前からマージ(併合)

„

リスト版

„

ベクタ版

„

計算量は両方のデータのスキャンのみ

デ タと

デ タとすると

マージソート(併合ソート、

merge sort)

28

„

m 個のデータと n 個のデータとすると

„

空間計算量も

余分に

)

(

m

+

n

Θ

)

(

m

+

n

Θ

„

分割統治型

内部マージソート(

In-place merge sort)

29

)

log

(

n

n

Θ

ラン(

run)と言う

„

分割統治型(ベクタの場合)

内部マージソート(

In-place merge sort)

30

)

log

(

n

n

(11)

„

選択ソート

(selection sort)

„

挿入ソート

(insertion sort) 定数小

„

シェルソート

(Shell sort)

h

k

= 3h

k-1

+ 1, …, 1 の時

Sorting(整列)のまとめ

)

(

n

2

Θ

)

(

n

1.25

Θ

)

(

n

2

Θ

31 k k-1

,

,

„

クイックソート

(quick sort), 分割統治法

(devide and conquer)

平均

最悪

„

ヒープソート

(heap sort) 常時

„

マージソート

(merge sort) 常時

)

log

(

n

n

Θ

(

2

)

n

Θ

)

log

(

n

n

Θ

)

log

(

n

n

Θ

„

Java のデモプログラム

„

http://winnie.kuis.kyoto-u.ac.jp/

~okuno/Lecture/05/IntroAlgDs/

Sorting(整列)のデモ

32 „

2分探索(binary search)

Sort(整列)済ベクタの探索

>

>

>

<

<

<

=

=

=

比較 34

)

(log n

Θ

„

2分探索の計算量

(12)

1月15日・本日のメニュー

„

ベクターというデータ構造

„

Sorting (整列)

1.

ヒープソート(

heap sort)

2.

バブルソート(

bubble sort)

37

3.

マージソート(merge sort)

„

hashing(ハッシュ法)

„

アンケート(最後の

15分)

配布する用紙に名前を記入して下さい。

回収は学生同士で。

教員は一切タッチしません。

„

探したいデータの範囲膨大

„

例: 最大10文字の単語

„

50文字とすると組合わせの数は

ハッシュ法(

hashing)

10

50

17

)

2

log

2

(

10

)

50

log(

10

=

17

10

38

„

ところが実際の単語数は高々

„

ベクタ(配列)で単語を管理すると

すかすかの配列

„

ハッシュ法(

hasing)

を使用

)

g

(

)

g(

0

6

10

辞書とハッシュ表

ハッシュ エントリ ハ ッ シ ュ 値 apocalypse → 黙示 apocope → 語尾消失

apocrypha → 聖書外典 apocalypse →2 apogee 遠地点

apocope →6

empty(空)

39 apodosis → 帰結節 apogee → 遠地点 apocope 6 apocrypha →4 apocalypse apodosis →5 apogee →0 apocrypha apodosis apocope

direct-access

table

(13)

„

hashed beaf

„

語源は同じ

ハヤシライスを知っていますか

40

„

キーの値の探索なしにアクセス

„

ハッシュ関数(

hash function)

キー ⇒ ハッシュ値(整数)

„

ハッシュ表(

hash table)、サイズ M

ハッシュ法(

hashing)

41

ッシ 表(

)、サイ

„

占有率(

load factor)α、データ量 N

„

異なるキーに対してハッシュ値が同じ

ハッシュ値の衝突(

collision)

M

N

=

α

„

設計の指針:

ランダム性

を有するもの。

„

キー:

„

例1:キーから

„

例2: 文字列から整数への写像

ハッシュ関数(

hash function)

n

a

a

a

x

=

1 2

L

key

(

x

)

=

m

M

m

x

h

1

(

)

mod

42

„

例2: 文字列から整数への写像

„

例3: m

2

の中央部分の

logM 桁分を使用

M a code x h n i i) mod ( ) ( 1 2

= ≡

⎣ ⎦

2 2 2 3

such that

constant

where

mod

)

(

N

MK

K

M

K

m

x

h

(14)

„

挿入(

insert)

hash表にkeyを持つデータを挿入

„

検索(

member)

ハッシュ法の基本手続き

43

hash表からkeyでデータを検索

„

削除(

delete)

hash表からkeyを持つデータを削除

„

チェイン法

chaining, separate

chaining, 連鎖法、内部ハッシュ法)

„

開番地法

open addressing, オープン法、

外部ハッシュ法)

ハッシュ値衝突(

collision)対処法

44

1.

線形走査法

linear probing)

2.

万能ハッシュ法

universal hashing)

3.

2重ハッシュ法

double hashing)

h, g

とすると、

h(x), h(x)+g(x), h(x)+2g(x), h(x)+3g(x),

チェイン法

empty empty empty empty dog curb curb dog

ハッシュ値の衝突

Backet(バケツ)を作り、

つないで行く。

45 empty bird empty empty empty bird

„ チェイン法の

平均最悪計算量

1. 挿入

2. 検索

3. 削除

)

(N

Θ

)

(N

Θ

)

(N

Θ

(15)

内部ハッシュ法(

internal hashing)

empty empty empty empty deleted empty empty

„

ハッシュ関数 h

i

„

占有率

α

„

エントリに

状態

を導入

empty

/

deleted

/

key

データ)

1

<

=

M

N

α

46 empty キー1 データ1 empty empty empty キー2 データ2 empty empty empty empty

1.

挿入:

empty/deleted というフ

ラグのあるエントリに入れる

2.

検索:

empty/deletedまで探す。

3.

削除:

deletedというフラグを立てる。

線形走査法(

linear probing)

empty empty empty empty empty empty empty

„

ハッシュ関数 h

„

衝突発生時

h

i

≡h+i mod M

„

挿入

47 empty empty empty empty empty empty empty empty empty empty

empty/deleted というフラグ

のあるエントリに入れる

„

検索

empty/deletedまで探す。

„

削除

deletedというフラグを立てる。

万能ハッシュ法(

universal hashing)

empty empty empty empty empty empty empty

„

ハッシュ関数 h,

・・・

„

ハッシュ関数をランダムに選択

„

挿入

empty/deleted というフラグ

48 empty empty empty empty empty empty empty empty empty empty

のあるエントリに入れる

„

検索

empty/deletedまで探す。

„

削除

deletedというフラグを立てる。

(16)

2重ハッシュ法(double hashing)

empty empty empty empty empty empty empty

„

ハッシュ関数 h, g

„

衝突発生時

h

i

≡h+ig mod M

„

挿入

49 empty empty empty empty empty empty empty empty empty empty

empty/deleted というフラグ

のあるエントリに入れる

„

検索

empty/deletedまで探す。

„

削除

deletedというフラグを立てる。

線形走査法(

linear probing)の例

0 empty 1 empty 2 empty 3 empty

1.

h(dog)=2

2.

h(Kyoto)=4

3.

h(Univ)=0

dog

Kyoto

Univ

50 4 empty 5 empty 6 empty 7 empty 8 empty 9 empty

4.

h(Informatics)=2

5.

h(SICP)=3

6.

h(test)=8

Informatics

SICP

test

1.

n個のデータが格納済、n+1個目のデータ挿入時

にh

i

(x)がi-1回目まですべて詰まっている確率

2

空きセルを見つけるまでの比較回数

線形走査法の挿入の計算量

1

1

2

2

1

1

+

+

i

M

i

n

M

n

M

n

M

n

L

51

2.

空きセルを見つけるまでの比較回数

3.

ハッシュ表にN個のデータを挿入する手間は

n

M

M

M

n

i

M

M

M

i

n

n

n

i i M i

=

+

+

+

+

∞ = − = 1 1 1

1

)

1

(

)

1

(

)

1

(

)

1

(

1

L

L

1

log

0 0

+

=

=

M

N

M

M

dx

x

M

M

n

M

M

e N N n

(17)

| 0.0 | 0.1 | 0.2 | 0.3 | 0.4 | 0.5 | 0.6 | 0.7 | 0.8 | 0.9 | 1.0 | 1.0 | 2.0 | 3.0 | 4.0 | 5.0 | 6.0 | 7.0 | 8.0 | 9.0 | 10.0 | | | | | | | | | | | |||||||||| Load Factor Computational Complexity 1/(1-α) -1/α log (1-α) load factor α          

4.

1回あたりの平均の挿入の手間は

線形走査法の挿入の計算量(続)

)

1

(

log

1

1

log

α

α

+

e e

N

M

M

N

M

1

52   | 0.0 | 0.1 | 0.2 | 0.3 | 0.4 | 0.5 | 0.6 | 0.7 | 0.8 | 0.9 | 1.0 | 1.0 | 2.0 | 3.0 | 4.0 | 5.0 | 6.0 | 7.0 | 8.0 | 9.0 | 10.0 | | | | | | | | | | | |||||||||| Load Factor Computational Complexity 1/(1-α) -1/α log (1-α) load factor α          

)

1

(

log

1

α

α

e

α

1

1.

deleted はないものと仮定

2.

表にキーがない時は、n=N の挿入と同じ

表にキ がある時

線形走査法の検索の計算量

α

=

1

1

N

M

M

53

3.

表にキーがある時

4.

削除も検索と同じ

5.

上記の解析は、

一様ハッシュ(

uniform

hashing)

を仮定: キーの探索列ランダム

)

1

(

log

1

1

log

α

α

+

e e

N

M

M

N

M

  | 0.0 | 0.1 | 0.2 | 0.3 | 0.4 | 0.5 | 0.6 | 0.7 | 0.8 | 0.9 | 1.0 | 1.0 | 2.0 | 3.0 | 4.0 | 5.0 | 6.0 | 7.0 | 8.0 | 9.0 | 10.0 | | | | | | | | | | | |||||||||| Load Factor Computational Complexity 1/(1-α) -1/α log (1-α) load factor α          

)

1

(

l

1

α

1

1

54 | 0.0 | 0.1 | 0.2 | 0.3 | 0.4 | 0.5 | 0.6 | 0.7 | 0.8 | 0.9 | 1.0 | 1.0 | 2.0 | 3.0 | 4.0 | 5.0 | 6.0 | 7.0 | 8.0 | 9.0 | 10.0 | | | | | | | | | | | |||||||||| Load Factor Computational Complexity 1/(1-α) -1/α log (1-α) load factor α          

)

1

(

log

α

α

e

(18)

1.

deleted はないものと仮定

2.

表にキーがない時は、n=N の挿入と同じ

線形走査法の削除の計算量

α

=

1

1

N

M

M

55

3.

表にキーがある時

)

1

(

log

1

1

log

α

α

+

e e

N

M

M

N

M

α

1

N

M

„

期末テスト、健闘を期待します。

„

必修課題3もお忘れなく。

„

随意課題の提出でランクアップを。

宿題はありません

57

テスト:

2月5日3限

参照

関連したドキュメント

口腔の持つ,種々の働き ( 機能)が障害された場 合,これらの働きがより健全に機能するよう手当

)から我が国に移入されたものといえる。 von Gierke, Das deutsche Genossenschaftsrecht,

のうちいずれかに加入している世帯の平均加入金額であるため、平均金額の低い機関の世帯加入金額にひ

ERROR  -00002 認証失敗または 圏外   クラウドへの接続設定及びア ンテ ナ 接続を確認して ください。. ERROR  -00044 回線未登録または

国際仲裁に類似する制度を取り入れている点に特徴があるといえる(例えば、 SICC

 「フロン排出抑制法の 改正で、フロンが使え なくなるので、フロン から別のガスに入れ替 えたほうがいい」と偽

長期入院されている方など、病院という枠組みにいること自体が適切な治療とはいえないと思う。福祉サービスが整備されていれば

   遠くに住んでいる、家に入られることに抵抗感があるなどの 療養中の子どもへの直接支援の難しさを、 IT という手段を使えば