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

第五回 (2014年10月17日)

ヒープとヒープソート

http://www.sw.it.aoyama.ac.jp/2014/DA/lecture5.html

Martin J. Dürst

AGU

© 2009-14 Martin J. Dürst 青山学院大学

目次

調査: 授業の時間的配置

来年度、金曜日一限から木曜日一限への方向が検討中

前回のまとめ

前回の宿題 (1)

次の関数をオーダの順にならべ、理由を付けなさい。

O(n2), O(n!), O(n log log n), O(n log n), O(20n)

[都合により削除]

前回の宿題 (3)

順位キュー (priority queue) という ADT を実装しなさい
(Ruby でも他言語でもよい)

[都合により削除]

順位キュー

(priority queue, 優先順位キュー、優先順位付き待ち行列)

IT の例
プロセス管理など
操作
作成 (new, init)、空かどうかのテスト (empty?)

insert (add,...): 項目の追加、getNext/delMax/...: 最優先項目の返しと削除

findMax/peekAtNext/...: 最優先項目を返すだけ

単純な実装

各操作の計算量
実装 配列 (整列済み) 配列 (探索) 連結リスト (整列済み) 連結リスト (探索)
insert O(n) O(1) O(n) O(1)
getNext O(1) O(n) O(1) O(n)
findMax O(1) O(n) O(1) O(n)

実装によって操作の計算量が違うが、必ずどちらかの操作が O(n)

改善は可能でしょうか

 

順位キューの改善のための発想

 

 

 

完全二分木

(complete binary tree)

木構造に基づく定義:

完全二分木の配列による実装

 

ヒープ

(heap)

⇒ ルートは常に一番優先

各操作の実現:

普遍条件

(英語: invariant)

ヒープの普遍条件の修復

ある場所で、優先度が高かすぎる可能性の場合: heapify_up
親と比較、必要であれば交換、交換されたら親で続く

ある場所で、優先度が低くすぎる可能性の場合: heapify_down
子と比較、必要であれば優先度の高い子と交換、交換された子で続く

実装: 5heap.rb

ヒープによる順位キューの実装

各操作の計算量
実装 Heap (Array による実装)
insert O(log n)
findMax O(1)
getNext O(log n)

ヒープソート

(heap sort)

irb の使い方

irb: Interactive Ruby, Ruby 用のコマンドプロンプト

使用例:

C:\Algorithms>irb
irb(main):001:0> require './5heap'
=> true
irb(main):002:0> h = Heap.new
=> #<Heap:0x2833d60 @array=[nil], @size=0>
irb(main):003:0> h.insert 3
=> #<Heap:0x2833d60 @array=[nil, 3], @size=1>
irb(main):004:0> h.insert(5).insert(7)
=> #<Heap:0x2833d60 @array=[nil, 7, 3, 5], @size=3>
 ...

その他のヒープ

順位キューの改善のための発想

概念層

今回のまとめ

次回のための準備

  1. (普通の) ヒープの合併を実装しましょう
  2. ヒープの作成の計算量について考えましょう:
    heapify_allO(n/2 · log n) で O(n log n) に見えるが、細かく分析すると違う結果になる
  3. 情報テクノロジーでの整列 (sort) の応用を五つ考えましょう