二分木ヒープ (binary heap) - saga uaoba.cc.saga-u.ac.jp/.../pdf.2018/binaryheap.pdf(binary...

32
二分木ヒープ (Binary Heap) 2018年度 担当:只木進一(工学系研究科)

Upload: others

Post on 04-Jan-2020

4 views

Category:

Documents


0 download

TRANSCRIPT

  • 二分木ヒープ(Binary Heap)2018年度担当:只木進一(工学系研究科)

  • 二分木ヒープとは

    集合・リストから「最小」要素を取り出す二分木ヒープは、そのための標準的データ構造

    二分木ヒープを保存するデータ構造二分木ヒープの操作のメソッド

    対象となるデータクラス識別のためのlabelフィールド値を保持するvalueフィールド

    2

  • 二分木ヒープとは、どういう二分木かある頂点の要素𝑝𝑝のvalueは、その子𝑐𝑐の要素のvalueより大きくないp.value ≤ c.value半順序木になっている

    完全二分木である最下層以外の第𝑘𝑘層には、2𝑘𝑘ー1個の頂点がある。

    最下層は、左から詰めて頂点がある。3

  • 半順序集合(partially ordered set)または順序集合(ordered set)

    集合𝑃𝑃とその上の関係≤に対して、以下の法則が常になりたつとき、𝑃𝑃を半順序集合と呼ぶ。ここで、𝑎𝑎, 𝑏𝑏, 𝑐𝑐∈𝑃𝑃となる任意の要素とする。反射律 (reflectivity):𝑎𝑎 ≤ 𝑎𝑎推移律 (transitivity): 𝑎𝑎 ≤ 𝑏𝑏 ∧ (𝑏𝑏 ≤ 𝑐𝑐) ⇒ 𝑎𝑎 ≤ 𝑐𝑐反対照律 (antisymmetry): 𝑎𝑎 ≤ 𝑏𝑏 ∧ 𝑏𝑏 ≤ 𝑎𝑎 ⇒𝑎𝑎 = 𝑏𝑏

    任意の元の組𝑎𝑎, 𝑏𝑏∈𝑃𝑃に対して𝑎𝑎 ≤ 𝑏𝑏または𝑏𝑏 ≤𝑎𝑎の何れかが必ず成り立つとき、𝑃𝑃を全順序集合(totally ordered set)と呼ぶ。

    4

  • 20.9

    80.4

    50.4

    110.8

    60.5

    70.3

    100.3

    40.2

    120.2

    30.1

    90.1

    10.6

    1

    2 3

    4 5 6 7

    8 9 10 11 12

    label

    value位置

    5

  • 20.9

    80.4

    50.4

    110.8

    60.5

    70.3

    100.3

    40.2

    120.2

    30.1

    90.1

    10.6

    データの保持形式

    リストで保持 0番:空(リストのインデクスが1から始まるプログラミング言語では不要)

    1番:根の要素 2k番:第k層の左端の要素

    6

  • 親子の番号の関係

    親の番号 子の番号

    7

    i

    / 2i

    2i

    i

    2 1i +

  • 要素の追加

    リストの終端に要素を追加する木の最下層の一番右に追加、または新たな層を作って、その左端に追加

    8

    void add (O 𝑜𝑜){int 𝑛𝑛 = 𝐿𝐿 ;𝐿𝐿.append(𝑜𝑜);𝑛𝑛 + +;shiftUp(𝑛𝑛);//要素を正しい位置へ移動

    }

  • 要素の追加:シフトアップ

    追加した新要素を正しい位置へ移動

    位置𝑘𝑘の要素が、親の位置𝑘𝑘/2 の要素よりも小さいならば、二つの要素を入れ替える

    isLess(𝑖𝑖, 𝑗𝑗) 𝑜𝑜𝑖𝑖 .𝑣𝑣𝑎𝑎𝑣𝑣𝑣𝑣𝑣𝑣 < 𝑜𝑜𝑗𝑗 .𝑣𝑣𝑎𝑎𝑣𝑣𝑣𝑣𝑣𝑣のとき真

    swap(𝑖𝑖, 𝑗𝑗):要素入れ替え

    9

    void shiftUp(int 𝑘𝑘){if ( 𝑘𝑘 > 1 && isLess(𝑘𝑘, 𝑘𝑘/2 )){

    swap(𝑘𝑘, 𝑘𝑘/2 );𝑘𝑘 = 𝑘𝑘/2 ;shiftUp(k);

    }}

  • 7

    130.2

    13

    新要素を末尾に追加2

    0.98

    0.45

    0.4110.8

    60.5

    70.3

    100.3

    40.2

    120.2

    30.1

    90.1

    10.6

    1

    2 3

    4 5 6 7

    8 9 10 11 12

    10要素追加の例

  • 7

    70.3

    13

    20.9

    80.4

    50.4

    110.8

    60.5

    130.2

    100.3

    40.2

    120.2

    30.1

    90.1

    10.6

    1

    2 3

    4 5 6 7

    8 9 10 11 12

    要素入れ替え

    11

  • 10.6

    10.6

    20.9

    2

    12 最初から木を構築

  • 30.1

    10.6

    20.9

    10.6

    30.1

    20.9

    13

  • 40.2

    10.6

    30.1

    20.9

    20.9

    10.6

    30.1

    40.2

    Swap

    14

  • 20.9

    10.6

    30.1

    40.2

    50.4

    15

  • 20.9

    10.6

    30.1

    40.2

    50.4

    60.5 Swap

    50.5

    10.6

    16

  • 20.9

    60.5

    30.1

    40.2

    50.4

    10.6

    70.3

    Swap7

    0.3

    60.5

    17

  • 20.9

    30.1

    40.2

    50.4

    10.6

    Swap

    70.3

    60.5

    70.3

    80.4

    80.4

    20.9

    18

  • 最小要素の取出し

    最小要素は木の根として保存されている

    最小要素を取り除き、再構築する 最小要素の取り除き:リスト中の1番が空く

    最後尾の要素を取り除き、リストの1番に入れる

    適切な位置へシフトダウンする

    19

    O poll(){O 𝑡𝑡 = 𝐿𝐿.get(1);O 𝑥𝑥 = 𝐿𝐿.removeLast();𝐿𝐿.set(1, 𝑥𝑥);shiftDown(1);return 𝑡𝑡;

    }

  • 要素の取出し:シフトダウン

    追加した新要素を正しい位置へ移動位置𝑘𝑘の要素が、子の要素の位置2𝑘𝑘と2𝑘𝑘 + 1の小さいほうの値より大きい場合、その小さい値の子を入れ替える

    20

  • 要素の取出し:シフトダウン

    21

    void shiftDown(int 𝑘𝑘){int 𝑛𝑛 = 𝐿𝐿 ;if (2 × 𝑘𝑘 ≤ 𝑛𝑛 ){

    int 𝑗𝑗 = 2 × 𝑘𝑘;if (𝑗𝑗 < 𝑛𝑛 && isLess(𝑗𝑗 + 1, 𝑗𝑗))𝑗𝑗 + +;if (isLess(𝑘𝑘, 𝑗𝑗))return;swap(𝑘𝑘, 𝑗𝑗);shiftDown(𝑗𝑗);

    }}

  • 70.3

    20.9

    80.4

    50.4

    110.8

    60.5

    130.2

    100.3

    40.2

    120.2

    30.1

    90.1

    10.6

    Rootの取出し22

  • 70.3

    20.9

    80.4

    50.4

    110.8

    60.5

    130.2

    100.3

    40.2

    120.2

    90.1

    10.6

    70.3

    Rootへ移動

    23

  • 20.9

    80.4

    50.4

    110.8

    60.5

    130.2

    100.3

    40.2

    120.2

    90.1

    10.6

    70.3

    Swap

    24

  • 20.9

    80.4

    50.4

    110.8

    60.5

    130.2

    100.3

    40.2

    120.2

    70.3

    10.6

    90.1

    Swap

    25

  • 20.9

    80.4

    50.4

    110.8

    60.5

    130.2

    100.3

    70.3

    120.2

    40.2

    10.6

    90.1

    26

  • 特定の要素の値を小さくする

    その要素のインデクス𝑘𝑘shiftUpを𝑘𝑘を起点に実施

    27

    void reduceValue(O o){ k = o のリスト中のインデクス shiftUp(k) }

    void reduceValue(O o){

    k = o のリスト中のインデクス

    shiftUp(k)

    }

  • 20.9

    80.4

    50.4

    110.2

    60.5

    130.2

    100.3

    70.3

    120.2

    40.2

    10.6

    90.1

    28 Label 11の値を0.2に

    Swap

  • 20.9

    80.4

    50.4

    110.2

    60.5

    130.2

    100.3

    70.3

    120.2

    40.2

    10.6

    90.1

    29 Label 11の値を0.2に

  • 特定の要素の値を大きくする

    その要素のインデクス𝑘𝑘shiftDownを𝑘𝑘を起点に実施

    30

    void raiseValue(O o){ k = o のリスト中のインデクス shiftDown(k) }

    void raiseValue(O o){

    k = o のリスト中のインデクス

    shiftDown(k)

    }

  • 20.9

    80.4

    50.4

    110.8

    60.5

    130.2

    100.3

    70.3

    120.2

    40.4

    10.6

    90.1

    31 Label 4の値を0.4に

    Swap

  • 20.9

    80.4

    50.4

    110.8

    60.5

    130.2

    100.3

    70.3

    120.2

    40.4

    10.6

    90.1

    32 Label 4の値を0.4に

    Swap

    二分木ヒープ�(Binary Heap)二分木ヒープとは二分木ヒープとは、どういう二分木か半順序集合(partially ordered set)または順序集合(ordered set)スライド番号 5データの保持形式親子の番号の関係要素の追加要素の追加:シフトアップスライド番号 10スライド番号 11スライド番号 12スライド番号 13スライド番号 14スライド番号 15スライド番号 16スライド番号 17スライド番号 18最小要素の取出し要素の取出し:シフトダウン要素の取出し:シフトダウンスライド番号 22スライド番号 23スライド番号 24スライド番号 25スライド番号 26特定の要素の値を小さくするスライド番号 28スライド番号 29特定の要素の値を大きくするスライド番号 31スライド番号 32