Tools + Simulatorsnanase.cc / tools

二分ヒープ

二分ヒープ

比較移動条件違反格納済み待機中ソート済み
0 / 0 手順
速さ 速さ

回/秒

n = 要素数 * 償却

バー
要素数 要素数

個

格納の方法

根の値

実行内容計算量n = 31 の平均

比較と移動
0回
比較
0
移動
0
要素数
0
木の段数
–
条件違反の枝
–
最大値
–
格納の合計
0
ソートの合計
0
合計
0
1 要素のメモリ
値のみ(配列)
利用例
タイマーの待ち行列・ダイクストラ法・ヒープソート
1 要素のメモリ
値のみ(配列)
利用例
追加が多い待ち行列・ダイクストラ法
1 要素のメモリ
値と子へのポインタ
利用例
ヒープどうしのマージが多いとき
1 要素のメモリ
値と子へのポインタ
利用例
ヒープどうしのマージが多いとき
1 要素のメモリ
値と子へのポインタ
利用例
ヒープどうしのマージが多いとき
1 要素のメモリ
値と子へのポインタ
利用例
実装が簡単で速い優先度付きキュー
1 要素のメモリ
値と子へのポインタ
利用例
値の変更が多いグラフのアルゴリズム
1 要素のメモリ
値のみ(配列)
利用例
要素が少ないときの待ち行列

音量 音量

dB

動作原理と式

ヒープの条件

最大ヒープは、どの親の値も子の値以上になっている木です。最大値はいつも根にあります。左右の子のどちらが大きいかは決めません。上の段から左詰めで埋めるので、段数は要素数の対数で済みます [1]。

A[parent(i)]≥A[i]

木を配列に入れる

上の段から順に配列へ並べると、親と子の位置は添字の計算で求まります。子へのポインタは要りません [3]。

parent(i)=⌊(i−1)/2⌋left(i)=2i+1right(i)=2i+2

記号: i は 0 から数える添字です。

格納

  • 1 個ずつ追加: 末尾に入れ、親より大きい間は親と交換する。1 個あたり最大で段数ぶん上がるので O(logn) [1]
  • まとめて構築: 全部を配列へ入れてから、子を持つ要素を下の段から順に直す [2]

まとめて構築では、大半の要素が下の段にあって短い距離しか動きません。高さ h の要素は約 n/2h+1 個で、それぞれ最大 h 回下がります。合計は要素数に比例し、全体で O(n) です [3]。

∑h=0∞n2h+1h=n

ソート

根を取り出すと最大値が得られます。空いた根へ末尾の要素を移し、大きいほうの子と交換しながら下げると、条件が元に戻ります。これを全要素に行うと値の大きい順に出て、全体で O(nlogn) です [1]。図の配列のように、取り出した値を末尾から順に置けば、追加の領域なしで並べ替えられます。これがヒープソートです。

d 分ヒープ

子の数を d 個に増やすと段数が減り、追加は速くなります。取り出しでは 1 段ごとに子をすべて比べるので、比較は増えます [4]。計算量の記号はどちらも O(logn) です。

parent(i)=⌊(i−1)/d⌋child(i,k)=di+k(1≤k≤d)

ポインタでつなぐヒープ

配列に入れず、子へのポインタで木をつなぐヒープです。木どうしのマージが速いので、追加も取り出しもマージで作れます。

  • 左傾ヒープ: どの要素でも左の子のほうが右の子より高い。右の枝が短いので、右の枝どうしをマージする [5]
  • スキューヒープ: 高さを覚えず、マージのたびに左右の子を入れ替える。1 回は遅くても、続けると対数に収まる [6]
  • 二項ヒープ: 大きさが 2 のべきの木を、大きさごとに 1 本ずつ持つ。追加は 2 進数の繰り上がりと同じ動きになる [7]
  • ペアリングヒープ: 根どうしを比べて負けたほうを子にするだけ。取り出しのときに、子を 2 個ずつつないでまとめる [8]
  • フィボナッチヒープ: 追加は根の列に足すだけで、つなぐ作業を取り出しまで遅らせる。値の変更は切り離すだけで済む [10]

計算量

配列は追加が速く取り出しが遅い構造です。ヒープは追加と取り出しの両方を対数以下に抑えます [3]。* は償却で、操作を続けたときの 1 回あたりを表します。ペアリングヒープの値の変更は厳密な増え方がまだ定まっておらず、上限だけがわかっています [9]。

追加確認取り出し値の変更まとめて構築
二分ヒープO(log 𝑛)O(1)O(log 𝑛)O(log 𝑛)O(𝑛)
4 分ヒープO(log 𝑛)O(1)O(log 𝑛)O(log 𝑛)O(𝑛)
左傾ヒープO(log 𝑛)O(1)O(log 𝑛)O(log 𝑛)O(𝑛)
スキューヒープO(log 𝑛)*O(1)O(log 𝑛)*O(log 𝑛)*O(𝑛)*
二項ヒープO(1)*O(log 𝑛)O(log 𝑛)O(log 𝑛)O(𝑛)
ペアリングヒープO(1)O(1)O(log 𝑛)*o(log 𝑛)*O(𝑛)
フィボナッチヒープO(1)O(1)O(log 𝑛)*O(1)*O(𝑛)
配列(参考)O(1)O(𝑛)O(𝑛)O(1)O(𝑛)

音

音の高さはバーの高さで決めます。v はバーの値(1〜99)です。

f=110×24(v−1)/98Hz

出典

  1. ヒープとヒープソートJ. W. J. Williams, Algorithm 232: Heapsort, Communications of the ACM, Vol. 7, No. 6, pp. 347–348, 1964
  2. 下の段から直す構築R. W. Floyd, Algorithm 245: Treesort, Communications of the ACM, Vol. 7, No. 12, p. 701, 1964
  3. ヒープの性質、構築の計算量、優先度付きキューT. H. Cormen, C. E. Leiserson, R. L. Rivest, C. Stein, Introduction to Algorithms, 4th ed., MIT Press, 2022, Chapter 6
  4. d 分ヒープD. B. Johnson, Priority queues with update and finding minimum spanning trees, Information Processing Letters, Vol. 4, No. 3, pp. 53–57, 1975
  5. 左傾ヒープC. A. Crane, Linear Lists and Priority Queues as Balanced Binary Trees, Ph.D. thesis, Stanford University, 1972, STAN-CS-72-259
  6. スキューヒープD. D. Sleator, R. E. Tarjan, Self-Adjusting Heaps, SIAM Journal on Computing, Vol. 15, No. 1, pp. 52–69, 1986
  7. 二項ヒープJ. Vuillemin, A data structure for manipulating priority queues, Communications of the ACM, Vol. 21, No. 4, pp. 309–315, 1978
  8. ペアリングヒープM. L. Fredman, R. Sedgewick, D. D. Sleator, R. E. Tarjan, The pairing heap: A new form of self-adjusting heap, Algorithmica, Vol. 1, pp. 111–129, 1986
  9. ペアリングヒープの値の変更の計算量S. Pettie, Towards a Final Analysis of Pairing Heaps, 46th Annual IEEE Symposium on Foundations of Computer Science (FOCS'05), pp. 174–183, 2005
  10. フィボナッチヒープM. L. Fredman, R. E. Tarjan, Fibonacci heaps and their uses in improved network optimization algorithms, Journal of the ACM, Vol. 34, No. 3, pp. 596–615, 1987

このツールで決めたこと

  • 比較は値を比べた回数で、子の中から選ぶ比較も数える
  • 移動は要素かポインタを書き込んだ回数で、交換は 1 回と数える
  • 確認は根か末尾を読む 1 回を比較に含める
  • 値の変更は根に近づく向きに変える。変える場所はわかっているものとし、探す回数は数えない
  • 二項ヒープの確認は最良の根を覚えず、根を全部見る
  • 格納とソートの回数は工程ごとに 0 から数える
  • 二項・ペアリング・フィボナッチヒープのまとめて構築は 1 個ずつ追加と同じ手順にする
  • 操作の表の回数は、31 要素の状態から 1 回実行したときの 24 通りのデータの平均。償却の操作は 31 回続けた 1 回あたり
  • 一覧の表から操作を選ぶと、要素数の 2/3 を追加した状態から始める
  • 配列の図では、取り出した値を末尾から順に置く

関連ツール