Skip to content

Commit 0b89e82

Browse files
committedNov 30, 2023
docs: heap
1 parent 795516e commit 0b89e82

File tree

3 files changed

+245
-1
lines changed

3 files changed

+245
-1
lines changed
 

‎Leetcode/0703.Kth-Largest-Element-in-a-Stream/README.md

+3-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ description: "0703.Kth-Largest-Element-in-a-Stream"
1010
license: ""
1111
images: []
1212

13-
tags: [LeetCode, Go, Easy, Kth Largest Element in a Stream]
13+
tags: [LeetCode, Go, Easy, Kth Largest Element in a Stream, Heap, Priority Queue]
1414
categories: [LeetCode]
1515

1616
featuredImage: ""
@@ -109,6 +109,8 @@ Acceptance Rate
109109
## 解題思路
110110
這題考察優先順序佇列的使用,可以先做下這道類似的題目 [215.陣列中的第 K 個最大元素](../0215.Kth-Largest-Element-in-an-Array/README.md)
111111

112+
[golang container/heap](../../structures/heap/index.en.md)
113+
112114
## Big O
113115
時間複雜 : ``
114116
空間複雜 : ``

‎structures/heap/FullBT_CompleteBT.jpg

19.6 KB
Loading

‎structures/heap/index.en.md

+242
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,242 @@
1+
---
2+
title: "Golang: container/heap"
3+
subtitle: "https://leetcode.com/problems/kth-largest-element-in-a-stream/"
4+
date: 2023-01-22T21:20:00+08:00
5+
lastmod: 2023-01-22T21:20:00+08:00
6+
draft: false
7+
author: "Kimi.Tsai"
8+
authorLink: "https://kimi0230.github.io/"
9+
description: "0703.Kth-Largest-Element-in-a-Stream"
10+
license: ""
11+
images: []
12+
13+
tags: [Go, container/heap]
14+
categories: [Structure]
15+
16+
featuredImage: ""
17+
featuredImagePreview: ""
18+
19+
hiddenFromHomePage: false
20+
hiddenFromSearch: false
21+
twemoji: false
22+
lightgallery: true
23+
ruby: true
24+
fraction: true
25+
fontawesome: true
26+
linkToMarkdown: false
27+
rssFullText: false
28+
29+
toc:
30+
enable: true
31+
auto: true
32+
code:
33+
copy: true
34+
maxShownLines: 200
35+
math:
36+
enable: false
37+
# ...
38+
mapbox:
39+
# ...
40+
share:
41+
enable: true
42+
# ...
43+
comment:
44+
enable: true
45+
# ...
46+
library:
47+
css:
48+
# someCSS = "some.css"
49+
# located in "assets/"
50+
# Or
51+
# someCSS = "https://cdn.example.com/some.css"
52+
js:
53+
# someJS = "some.js"
54+
# located in "assets/"
55+
# Or
56+
# someJS = "https://cdn.example.com/some.js"
57+
seo:
58+
images: []
59+
# ...
60+
---
61+
62+
# Golang : container/heap
63+
64+
## Heap是什麼
65+
Wiki: https://zh.wikipedia.org/wiki/%E5%A0%86%E7%A9%8D
66+
67+
堆積(Heap)是電腦科學中的一種特別的**完全二元樹**
68+
若是滿足以下特性,即可稱為堆積:「給定堆積中任意節點P和C,若P是C的母節點,那麼P的值會小於等於(或大於等於)C的值」。
69+
若母節點的值恆小於等於子節點的值,此堆積稱為最小堆積(min heap);
70+
反之,若母節點的值恆大於等於子節點的值,此堆積稱為最大堆積(max heap)。
71+
在堆積中最頂端的那一個節點,稱作根節點(root node),根節點本身沒有母節點(parent node)。
72+
73+
![](FullBT_CompleteBT.jpg)
74+
75+
## container/heap 提供的方法
76+
heap包為實現了 `heap.Interface` 的類型提供了堆方法:Init/Push/Pop/Remove/Fix。 `container/heap` 為最小堆,
77+
即每個節點的值都小於它的子樹的所有元素的值(A heap is a tree with the property that each node is the minimum-valued node in its subtree)。
78+
79+
**heap:**
80+
```go
81+
package heap
82+
// ...
83+
// Note that Push and Pop in this interface are for package heap's
84+
// implementation to call. To add and remove things from the heap,
85+
// use heap.Push and heap.Pop.
86+
type Interface interface {
87+
sort.Interface
88+
Push(x any) // add x as element Len()
89+
Pop() any // remove and return element Len() - 1.
90+
}
91+
```
92+
93+
**sort:**
94+
```go
95+
package sort
96+
97+
// An implementation of Interface can be sorted by the routines in this package.
98+
// The methods refer to elements of the underlying collection by integer index.
99+
type Interface interface {
100+
// Len is the number of elements in the collection.
101+
Len() int
102+
103+
// Less reports whether the element with index i
104+
// must sort before the element with index j.
105+
//
106+
// If both Less(i, j) and Less(j, i) are false,
107+
// then the elements at index i and j are considered equal.
108+
// Sort may place equal elements in any order in the final result,
109+
// while Stable preserves the original input order of equal elements.
110+
//
111+
// Less must describe a transitive ordering:
112+
// - if both Less(i, j) and Less(j, k) are true, then Less(i, k) must be true as well.
113+
// - if both Less(i, j) and Less(j, k) are false, then Less(i, k) must be false as well.
114+
//
115+
// Note that floating-point comparison (the < operator on float32 or float64 values)
116+
// is not a transitive ordering when not-a-number (NaN) values are involved.
117+
// See Float64Slice.Less for a correct implementation for floating-point values.
118+
Less(i, j int) bool
119+
120+
// Swap swaps the elements with indexes i and j.
121+
Swap(i, j int)
122+
}
123+
```
124+
125+
由於 heap.Interface 包含了 sort.Interface ,所以,目標類型需要包含如下方法:`Len`/`Less`/`Swap` ,`Push`/`Pop。`
126+
127+
## container/heap 可用在哪
128+
129+
container/heap包可以用來構造優先順序佇列。
130+
131+
https://go.dev/play/p/77zrF3PurO4
132+
```go
133+
// This example demonstrates a priority queue built using the heap interface.
134+
package main
135+
136+
import (
137+
"container/heap"
138+
"fmt"
139+
)
140+
141+
// An Item is something we manage in a priority queue.
142+
type Item struct {
143+
value string // The value of the item; arbitrary.
144+
priority int // The priority of the item in the queue.
145+
// The index is needed by update and is maintained by the heap.Interface methods.
146+
index int // The index of the item in the heap.
147+
}
148+
149+
// A PriorityQueue implements heap.Interface and holds Items.
150+
type PriorityQueue []*Item
151+
152+
func (pq PriorityQueue) Len() int { return len(pq) }
153+
154+
func (pq PriorityQueue) Less(i, j int) bool {
155+
// We want Pop to give us the highest, not lowest, priority so we use greater than here.
156+
return pq[i].priority > pq[j].priority
157+
}
158+
159+
func (pq PriorityQueue) Swap(i, j int) {
160+
pq[i], pq[j] = pq[j], pq[i]
161+
pq[i].index = i
162+
pq[j].index = j
163+
}
164+
165+
func (pq *PriorityQueue) Push(x interface{}) {
166+
n := len(*pq)
167+
item := x.(*Item)
168+
item.index = n
169+
*pq = append(*pq, item)
170+
}
171+
172+
func (pq *PriorityQueue) Pop() interface{} {
173+
old := *pq
174+
n := len(old)
175+
item := old[n-1]
176+
item.index = -1 // for safety
177+
*pq = old[0 : n-1]
178+
return item
179+
}
180+
181+
// update modifies the priority and value of an Item in the queue.
182+
func (pq *PriorityQueue) update(item *Item, value string, priority int) {
183+
item.value = value
184+
item.priority = priority
185+
heap.Fix(pq, item.index)
186+
}
187+
```
188+
189+
PriorityQueue 本質上是個 *Item 陣列,其Len/Less/Swap是比較常見的陣列用來sort需要定義的函數,而Push、Pop則是使用數位來插入、的方法。 PriorityQueue 還提供了update方法。 注意由於通常希望優先順序佇列Pop出來的是優先順序最高的元素,所以Less方法是反著寫的。
190+
191+
定義了以上方法以後, PriorityQueue 就具備了使用 container/heap 包的條件。
192+
193+
194+
如下代碼,先從items map出發定義了一個pq陣列,長度為hash的size,並調用 heap.Init 初始化pq;
195+
之後向佇列中增加了一個優先順序為1的元素,並更新該元素的佇列; 最後從佇列中依此Pop,可見元素在Pop時是依照優先順序排序的。
196+
```go
197+
// This example creates a PriorityQueue with some items, adds and manipulates an item,
198+
// and then removes the items in priority order.
199+
func main() {
200+
// Some items and their priorities.
201+
items := map[string]int{
202+
"banana": 3, "apple": 2, "pear": 4,
203+
}
204+
205+
// Create a priority queue, put the items in it, and
206+
// establish the priority queue (heap) invariants.
207+
pq := make(PriorityQueue, len(items))
208+
i := 0
209+
for value, priority := range items {
210+
pq[i] = &Item{
211+
value: value,
212+
priority: priority,
213+
index: i,
214+
}
215+
i++
216+
}
217+
heap.Init(&pq)
218+
219+
// Insert a new item and then modify its priority.
220+
item := &Item{
221+
value: "orange",
222+
priority: 1,
223+
}
224+
heap.Push(&pq, item)
225+
pq.update(item, item.value, 5)
226+
227+
// Take the items out; they arrive in decreasing priority order.
228+
for pq.Len() > 0 {
229+
item := heap.Pop(&pq).(*Item)
230+
fmt.Printf("%.2d:%s index:%d \n", item.priority, item.value, item.index)
231+
}
232+
}
233+
// Output:
234+
// 05:orange index:-1
235+
// 04:pear index:-1
236+
// 03:banana index:-1
237+
// 02:apple index:-1
238+
239+
```
240+
241+
## Reference
242+
* [Golang: 详解container/heap](https://ieevee.com/tech/2018/01/29/go-heap.html#3-containerheap%E5%8F%AF%E4%BB%A5%E7%94%A8%E6%9D%A5%E5%81%9A%E4%BB%80%E4%B9%88)

0 commit comments

Comments
 (0)
Please sign in to comment.