Skip to content

Commit

Permalink
add doc for heap (#76)
Browse files Browse the repository at this point in the history
  • Loading branch information
chen3feng authored Aug 28, 2022
1 parent 3b87e2f commit f6dd5d7
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 1 deletion.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ See C++ STL.

#### heap

Heap provides basic min heap algorithms:
[Heap](heap.md) provides basic min heap algorithms:

- `MakeMinHeap` Convert a slice to a min heap
- `IsMinHeap` Check whether a slice is a min heap
Expand All @@ -198,6 +198,8 @@ and variants with custome comparasion function:

both of them are mush faster and easier to use than [container/heap](https://pkg.go.dev/container/heap).

See detailed usage and benchmark report in the [document of heap](heap.md)

### Interface Design and Naming

The design leart much from the C++ STL. The `T` here represents `template`. Yes, Go's generic is not template. but who made C++ so influential and STL so famous?
Expand Down
2 changes: 2 additions & 0 deletions README_zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,8 @@ func TestSkipList_ForEachMutable(t *testing.T) {

都比 go 标准库 [container/heap](https://pkg.go.dev/container/heap) 更容易使用且更快。

用法和测试详情参见[heap的文档](heap.md)

### 接口设计和命名

较多地参考了 C++ STL。T 表示模板。是的,Go 的范型不是模板,但是谁让 C++ 那么影响力,而 STL 又那么有名呢。
Expand Down
84 changes: 84 additions & 0 deletions heap.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
# Heap

## Easy to use

For ordered types, you can easily use the heap algorithms, for example, with `int` type:

```go
func Example() {
heap := []int {5, 4, 3, 2, 1}
stlgo.MakeHeap(heap)
stl4go.PushMinHeap(&heap, 6)
stl4go.PopMinHeap(&heap)
}
```

Please compare with [container/heap](https://pkg.go.dev/container/heap#example-package-IntHeap):

```go
// This example demonstrates an integer heap built using the heap interface.
package main

import (
"container/heap"
"fmt"
)

// An IntHeap is a min-heap of ints.
type IntHeap []int

func (h IntHeap) Len() int { return len(h) }
func (h IntHeap) Less(i, j int) bool { return h[i] < h[j] }
func (h IntHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i] }

func (h *IntHeap) Push(x any) {
// Push and Pop use pointer receivers because they modify the slice's length,
// not just its contents.
*h = append(*h, x.(int))
}

func (h *IntHeap) Pop() any {
old := *h
n := len(old)
x := old[n-1]
*h = old[0 : n-1]
return x
}

// This example inserts several ints into an IntHeap, checks the minimum,
// and removes them in order of priority.
func main() {
h := &IntHeap{2, 1, 5}
heap.Init(h)
heap.Push(h, 3)
fmt.Printf("minimum: %d\n", (*h)[0])
for h.Len() > 0 {
fmt.Printf("%d ", heap.Pop(h))
}
}
```

You must define a new type `IntHeap` and five methods before to use the library,
these boilerplate codes are verbose, tedious, and boring.

## Benchmark

The heap algorithms are also much faster than `container/heap`, even for the `Func` version.:

```console
% go test -bench BenchmarkHeap
goos: darwin
goarch: arm64
pkg: github.com/chen3feng/stl4go
BenchmarkHeapInit/container/heap.Init-10 362450 3172 ns/op
BenchmarkHeapInit/stlgo.MakeMinHeap-10 960280 1136 ns/op
BenchmarkHeapInit/stlgo.MakeHeapFunc-10 483109 2336 ns/op
BenchmarkHeapPush/container/heap.Push-10 101822 11639 ns/op
BenchmarkHeapPush/stlgo.PushMinHeap-10 501031 2283 ns/op
BenchmarkHeapPush/stlgo.PushHeapFunc-10 437288 2634 ns/op
BenchmarkHeapPop/container/heap.Pop-10 14550 82170 ns/op
BenchmarkHeapPop/stlgo.PopMinHeap-10 62139 19782 ns/op
BenchmarkHeapPop/stlgo.PopHeapFunc-10 22693 52900 ns/op
PASS
ok github.com/chen3feng/stl4go 17.670s
```

0 comments on commit f6dd5d7

Please sign in to comment.