http://www.sw.it.aoyama.ac.jp/2011/DA/lecture4.html
© 2008-11 Martin J. Dürst 青山学院大学
次の関数をオーダの順にならべ、理由を付けなさい。
O(n2), O(n!), O(n log log n), O(n log n), O(20n)
正解: O(n log log n), O(n log n), O(n2), O(20n), O(n!)
f(n) | g(n) | n0 (正解例) | c (正解例) |
n log log n | n log n | 2 | 1 |
n log n | n2 | 2 | 1 |
n2 | 20n | 1 | 1 |
20n | n! | 52 | 1 |
20n | n! | 20 | 2020/20! |
ヒント: Ruby は Bignum
がある為に馬鹿でかい数字の計算に便利
順位キュー (priority queue) という ADT を実装しなさい
(Ruby でも他言語でもよい)
順位キューは各要素ごとに優先度 (整数など) が付く。一番簡単な場合にデータ項目は優先度だけ。優先度の高いものが先にキューから出る。実装は配列でも連結リストでもよい。
正解例: 4prioQ.rb
(priority queue, 優先順位キュー、優先順位付き待ち行列)
insert (add,...): 項目の追加、getNext/delMax/...: 最優先項目の返しと削除
実装 | Array (常順) |
Array (探索) |
LinearList (常順) |
LinearList (探索) |
新規作成 | O(1) | O(1) | O(1) | O(1) |
項目追加 | O(n) | O(1) | O(n) | O(1) |
最優先項目 | O(1) | O(n) | O(1) | O(n) |
項目削除 | O(1) | O(n) | O(1) | O(n) |
empty? |
O(1) | O(1) | O(1) | O(1) |
長さ | O(1) | O(1) | O(n) | O(n) |
実装によって操作が違うが、必ずどこかで O(n) の計算量になる
改善は可能でしょうか
木構造に基づく定義:
別の定義 (Knuth):
(heap)
⇒ ルートは常に一番優先
各操作の実現:
(英語: invariant)
現在の場所にして優先度が高い可能性の場合:
heapify_up
親と比較、必要であれば交換、交換されたら親で続く
現在の場所にして優先度が低い可能性の場合:
heapify_down
子と比較、必要であれば優先度の高い子と交換、交換されたら子で続く
実装: 4heap.rb
実装 | Heap (Array による実装) |
新規作成 | O(1) |
項目追加 | O(log n) |
最優先項目 | O(1) |
項目削除 | O(log n) |
empty? |
O(1) |
長さ | O(1) |
(heap sort)
irb
の使い方irb
: Interactive Ruby, Ruby
用のコマンドプロンプト
使用例:
C:\Algorithms>irb irb(main):001:0> require './4heap' => true irb(main):002:0> h = Heap.new => #<Heap:0x2833d60 @array=[nil], @size=0> irb(main):003:0> h.add 3 => #<Heap:0x2833d60 @array=[nil, 3], @size=1> irb(main):004:0> h.add(5).add(7) => #<Heap:0x2833d60 @array=[nil, 7, 3, 5], @size=3> ...