---
# System prepended metadata

title: Min-Max Heap
tags: [Data Structure]

---

---
title: 'Min-Max Heap'
disqus: hackmd
---
[TOC]

## Min-Max Heap
> [color=#34d2db] **Def：**
>   1. 是 Complete Binary Tree
>   2. Level 依序由 Min/Max Heap 交互出現
>   3. Root 在 Min Level
>   4. 某 Node x 在 Min Level，代表以 x 為 Root 的 Tree 中，x 是最小值
>   (同理 Max Level)

![](https://i.imgur.com/AQpzCXa.png)

* 此樹就是由 Min Heap 與 Max Heap 互相交疊形成
* 再次提醒，定義 3 有提到 Root 必須為 Min Level 的值


---

### Insertion - 插入

* 依照 Complete Binary Tree 性質，插入 Node 2

![](https://i.imgur.com/Q6A3t29.png =300x)

* 此時 Node 2 你不知道他是否符合 Min-Max Heap 的定義，所以我們要與他的 Parent Node 1 比較
![](https://i.imgur.com/NIe2Uf6.png =300x)

* 根據定義 3 ，Root = Node 1 = Min Level，相當於此顆 Tree 是 Min Heap
所以當 Node 2 < Node 1 ，則要進行交換

![](https://i.imgur.com/LNSEwxt.png =600x)

:::danger
根據插入位置的 Parent Level 判斷
:::

* Parent 於 Min Level 使用 Min - Heap 判斷
![](https://i.imgur.com/EASyq1T.png)
* Parent 於 Max Level 使用 Max - Heap 判斷
![](https://i.imgur.com/Y930Yo8.png)
若新節點與父節點符合定義，要再檢查祖先節點

---

### Deletion - 刪除

* 五步驟


    * 移除 Root Data ( 也可以想像成對此 Tree 使用 GetData() )
    * 將 Last Node Data 存至變數 x 
    * 移除 Last Node
    * 將 x 存至  Root Data
    * "判斷" 新 Root 是否符合定義

**判斷方法：** (語法關係，圖若有單個 Child 請自行想像為 Left Child)

**Case 1：孕育新生命 - Root 無 Child**
```graphviz
graph graphname{
1[label=""]
x[label="x = 5" shape=s style=dashed]
}
```
* 將 Data 存至 Root 後即可
```graphviz
graph graphname{
1[label="5"]
}
```

**Case 2：含飴弄孫 - Root 有 Grandchild**
* 請想想，這裡使用到 Grandchild 原因為何
 

> [color=#34d2db]**在定義中有提到：**
>此樹就是由 Min Heap 與 Max Heap 互相交疊形成

<br><br>

* 所以當我們從某 Max/Min Level Node 往 Grandchild 的級距 (也就是 index * 2) 持續下去，相當於在搜尋一顆 Max/Min Heap

![](https://i.imgur.com/IXFygSu.png)

<br><br><br>

* 當然這兩顆 "分裂" 出來的 Tree 不完全稱得上是一顆完整的 Max/Min Heap
但是它仍然保留了 Max/Min Heap 最重要的特性，就是 Parent 與 Child 的關係
![](https://i.imgur.com/sN0DHBL.png)


* 千萬別忘了 Parent 與 Child 的關係是這樣
![](https://i.imgur.com/a2oOZld.png)
<br><br><br>

* 回過頭，我們從 Min-Max Heap 移除了 Root Data
![](https://i.imgur.com/HcipOYp.png)
<br><br><br>

* 那麼第二小的 Data 莫過於在下一層裡的其中一個 Node

![](https://i.imgur.com/qKsyxyp.png)
<br><br><br>

* 而我們把這個 Level 放回去 Min-Max Heap 來觀察，不就是 Root 的 Grandchild！

![](https://i.imgur.com/gH5jhII.png)
所以我們將 "優先" 搜尋 Root 的 Grandchild


---

* 使用以下 Tree 演示

```graphviz
graph graphname{
    
    1 [label="7"]
    2 [label="70"]
    3 [label="40"]
    4 [label="30"]
    5 [label="9"]
    6 [label="10"]
    7 [label="45"]
    
    
    1--2
    1--3
    2--4
    2--5
    3--6
    3--7
}
```

* 移除 Root Data：7
```graphviz
graph graphname{
    
    1 [label=""]
    2 [label="70"]
    3 [label="40"]
    4 [label="30"]
    5 [label="9"]
    6 [label="10"]
    7 [label="45"]
    
    
    1--2
    1--3
    2--4
    2--5
    3--6
    3--7
}
```
* 儲存 Last Node Data 至 x
```graphviz
graph graphname{
    
    1 [label=""]
    2 [label="70"]
    3 [label="40"]
    4 [label="30"]
    5 [label="9"]
    6 [label="10"]
    7 [label="45"]
    45[label="x = 45" shape=s style=dashed]
    
    1--2
    1--3
    2--4
    2--5
    3--6
    3--7
}
```

* 移除 Last Node
```graphviz
graph graphname{
    
    1 [label=""]
    2 [label="70"]
    3 [label="40"]
    4 [label="30"]
    5 [label="9"]
    6 [label="10"]
    45[label="x = 45" shape=s style=dashed]
    
    1--2
    1--3
    2--4
    2--5
    3--6
}
```

* 將 x 放入 Root Data
```graphviz
graph graphname{
    
    1 [label="45"]
    2 [label="70"]
    3 [label="40"]
    4 [label="30"]
    5 [label="9"]
    6 [label="10"]
    
    1--2
    1--3
    2--4
    2--5
    3--6
}
```
* 使用 case 2
```graphviz
graph graphname{
    
    1 [label="45" color=red]
    2 [label="70"]
    3 [label="40"]
    4 [label="30" color=blue]
    5 [label="9" color=blue]
    6 [label="10" color=blue]
    
    1--2
    1--3
    2--4
    2--5
    3--6
}
```

* 交換完成，且符合 Min-Max Heap 定義
```graphviz
graph graphname{
    
    1 [label="9"]
    2 [label="70"]
    3 [label="40"]
    4 [label="30"]
    5 [label="45" color=red]
    6 [label="10"]
    
    1--2
    1--3
    2--4
    2--5
    3--6
}
```


---

:::danger
**if (爸爸可能不知情)**
:::
* 以上述例子來說，更新完 Tree 之後雖然 Min Level 中的 Node 符合定義了
但切記 <font color=red> Min Level 是與 Max Level 互相交疊的</font>，所以還是需要考慮到另一個 Level 的 Parent 與新 Node 之間的關係

```graphviz
graph graphname{
    
    1 [label=""]
    2 [label="你還要先問問我" color=blue]
    3 [label=""]
    4 [label=""]
    5 [label="新 Node" color=red]
    6 [label=""]
    
    1--2
    1--3
    2--4
    2--5
    3--6
}
```

* 舉例說明，刪除一次

```graphviz
graph graphname{
    
    1 [label="7"]
    2 [label="100"]
    3 [label="500"]
    4 [label="50"]
    5 [label="90"]
    6 [label="300"]
    7 [label="400"]
    
    
    1--2
    1--3
    2--4
    2--5
    3--6
    3--7
}
```

* 移除 Root Data 並將 Last Node Data 存入 x ，移除 Last Node
```graphviz
graph graphname{
    
    1 [label="400" color=red]
    2 [label="100"]
    3 [label="500"]
    4 [label="50"]
    5 [label="90"]
    6 [label="300"]

    
    1--2
    1--3
    2--4
    2--5
    3--6
}
```

* 搜尋 Grandchild 並替換最小值：50
```graphviz
graph graphname{
    
    1 [label="50"]
    2 [label="100"]
    3 [label="500"]
    4 [label="400" color=red]
    5 [label="90"]
    6 [label="300"]

    
    1--2
    1--3
    2--4
    2--5
    3--6
}
```

* 檢查 Data 100 的 Root (位於 Max Level) 是否符合定義 (Parent 應當 $>$ Child)
```graphviz
graph graphname{
    
    1 [label="50"]
    2 [label="100" color=green]
    3 [label="500"]
    4 [label="400" color=red]
    5 [label="90"]
    6 [label="300"]
    
    1--2
    1--3
    2--4
    2--5
    3--6
}
```

* 不符合定義，進行交換
```graphviz
graph graphname{
    
    1 [label="50"]
    2 [label="400" color=red]
    3 [label="500"]
    4 [label="100" color=green]
    5 [label="90"]
    6 [label="300"]
    
    1--2
    1--3
    2--4
    2--5
    3--6
}
```
* 而如果 100 又有兒子則繼續操作
<br><br><br>


---

**Case 3：含飴弄不到孫 - Root 無合適 Grandchild**
* 考慮以下情況，進行刪除
```graphviz
graph graphname{
    
    1 [label="1"]
    2 [label="100"]
    3 [label="2"]
    4 [label="90"]
    5 [label="10"]
    
    1--2
    1--3
    2--4
    2--5

}
```
* 我們發現 10 的 Grandchild 是符合定義的，不須更動
```graphviz
graph graphname{
    
    1 [label="10"]
    2 [label="100"]
    3 [label="2"]
    4 [label="90" color=red]
    
    1--2
    1--3
    2--4

}
```
* 但是 10 的 Child 卻不符合定義 (因為 Parent 已經換人了)
```graphviz
graph graphname{
    
    1 [label="10"]
    2 [label="100"]
    3 [label="2 (嘿嘿)" color=blue]
    4 [label="90"]
    
    1--2
    1--3
    2--4

}
```
* 所以當沒有與 Grandchild 互動時，還是要記得檢查 Child
```graphviz
graph graphname{
    
    1 [label="2" color=blue]
    2 [label="100"]
    3 [label="10" ]
    4 [label="90"]
    
    1--2
    1--3
    2--4

}
```
> [color=#]其實 Case 2, 3 是差不多的，不論是 Parent 或 Child 更換，都要再去拜訪彼此是否符合定義

:::warning
**Time Complexity：**$O( log_2n )$
:::


---

## Deap

> [color=#d62234] **Def：**
>   1. 本身是 Complete Binary Tree
>   1. Root 不存 Data
>   2. Root 的 Left Subtree (左子樹) 為 Min-Heap
>   3. Root 的 Right Subtree (右子樹) 為 Max-Heap
>   4. 假設兩顆子樹各自的 Node 編號 (Index) 排列方式一樣，
>   則在相同編號下：左子樹的 Data $\leq$ 右子樹的 Data 
* 左子樹的 6 號 = 33 $\leq$ 右子樹的 6 號 = 60
![](https://i.imgur.com/TTQ3TQL.png)
<br><br>
* 填上編號觀看很容易，但在程式裡若要比較兩 Index ，這兩個對稱的 Index 相對於整棵 Tree 來說彼此有甚麼關係

![](https://i.imgur.com/tRed2KG.png)
<br><br>
* **Def：樹起始 Level 1**
我們知道每層的 Level Node 最大值 = $2^{k-1} , k = Level$

![](https://i.imgur.com/2qiHrFp.png)
<br><br><br>
* 想像每一層 Level Nodes 都是上一層 Level Nodes 數量 "複製" 兩次而來

![](https://i.imgur.com/9hG57Bh.png)
<br><br><br>
* 上一層的數量若為 1 個單位 (2 個 Nodes)，下一層的數量就是 2 個單位 
而左右 Heap 中 Node 彼此的間距就是 1 單位

![](https://i.imgur.com/9IhUHlI.png)

* 一個單位 = 上一層的最大 Nodes = $2^{k-2}$

* 所以只要將某個 Index ± $2^{k-2}$，就可以找到隔壁相同位置的 Node，( 加往右，減往左 )

* $Tree[4] = 10 \leq Tree[4+2^{3-2}] = Tree[6] = 70$
![](https://i.imgur.com/r9YuGvL.png)


---

### Insertion - 插入

* 根據 Complete Binary Tree 特性插入至第 n+1 的位置 (n = Nodes)
則插入的 Node 不是在 Min - Heap 就是在 Max - Heap

* 分為兩種 Case
    1. 插入 Min-Heap
        * 比較對應 Max-Heap 位置的父節點
        ![](https://i.imgur.com/aiP4o1e.png)

    2. 插入 Max-Heap
        * 比較對應 Min-Heap 位置的節點

交換完之後在做 Insertion (Heapify)




---

### Deletion - 刪除

* 我們可以選擇做最小 (綠Node) 或是最大 (紅Node) 刪除，

```graphviz
graph graphname{
    
    1 [label=""]
    2 [label="1" color=green]
    3 [label="100" color=red]
    4 [label="10"]
    5 [label="7"]
    6 [label="70"]
    7 [label="88"]
    8 [label="13"]
    9 [label="22"]
    10 [label="33"]
    11 [label="60"]
    12 [label="33"]
    13 [label="22"]
    14 [label="60"]
    15 [label="55"]
    
    1--2
    1--3
    2--4
    2--5
    3--6
    3--7
    4--8
    4--9
    5--10
    5--11
    6--12
    6--13
    7--14
    7--15

    
}
```
<br>

#### Minimal Deletion - 最小刪除
* 依照 Min - Heap Deletion 的步驟，將 Root 值 替換成 Last Node 值、並刪除 Last Node
```graphviz
graph graphname{
    
    1 [label=""]
    2 [label="55" color=green]
    3 [label="100"]
    4 [label="10"]
    5 [label="7"]
    6 [label="70"]
    7 [label="88"]
    8 [label="13"]
    9 [label="22"]
    10 [label="33"]
    11 [label="60"]
    12 [label="33"]
    13 [label="22"]
    14 [label="60"]
    
    
    1--2
    1--3
    2--4
    2--5
    3--6
    3--7
    4--8
    4--9
    5--10
    5--11
    6--12
    6--13
    7--14

}
```

* 確認完 Child 關係後，記得要在判斷與右子樹相對位 Node 的關係
```graphviz
graph graphname{
    
    1 [label=""]
    2 [label="7"]
    3 [label="100"]
    4 [label="10"]
    5 [label="33"]
    6 [label="70"]
    7 [label="88"]
    8 [label="13"]
    9 [label="22"]
    10 [label="55" color=green]
    11 [label="60"]
    12 [label="33" color=red]
    13 [label="22"]
    14 [label="60"]
    
    1--2
    1--3
    2--4
    2--5
    3--6
    3--7
    4--8
    4--9
    5--10
    5--11
    6--12
    6--13
    7--14

}
```

* 
```graphviz
graph graphname{
    
    1 [label=""]
    2 [label="7"]
    3 [label="100"]
    4 [label="10"]
    5 [label="33"]
    6 [label="70"]
    7 [label="88"]
    8 [label="13"]
    9 [label="22"]
    10 [label="33" ]
    11 [label="60"]
    12 [label="55" color=green ]
    13 [label="22"]
    14 [label="60"]
    
    1--2
    1--3
    2--4
    2--5
    3--6
    3--7
    4--8
    4--9
    5--10
    5--11
    6--12
    6--13
    7--14
}
```


###### tags: `Data Structure`