Skip to content

Commit

Permalink
HashHeap (#13)
Browse files Browse the repository at this point in the history
* hash heap
  • Loading branch information
lxzan authored Aug 27, 2024
1 parent 1758f2d commit bf2c5b2
Show file tree
Hide file tree
Showing 8 changed files with 387 additions and 455 deletions.
29 changes: 16 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ data containers and algorithms to simplify business development.
- [Filter](#filter)
- [Heap](#heap)
- [N-Way Heap](#n-way-heap)
- [N-Way Indexed Heap](#n-way-indexed-heap)
- [HashHeap](#hashheap)
- [Stack](#stack)
- [Queue](#queue)
- [Deque](#deque)
Expand Down Expand Up @@ -128,9 +128,9 @@ func main() {

```

#### N-Way Indexed Heap
#### HashHeap

Extends the normal heap with update and delete functions, often used in time heap algorithms.
Heap structure with hash index.

```go
package main
Expand All @@ -140,17 +140,20 @@ import (
)

func main() {
var h = heap.NewIndexedHeap[int, struct{}](heap.Quadratic, func(a, b int) bool { return a > b })
h.Push(1, struct{}{})
h.Push(3, struct{}{})
h.Push(5, struct{}{})
h.Push(2, struct{}{})
h.Push(4, struct{}{})
h.Push(6, struct{}{})
h.DeleteByIndex(5)
h.UpdateKeyByIndex(3, 7)
var h = heap.NewHashHeap[string, int](func(a, b int) bool { return a < b })
h.Set("a", 1)
h.Set("b", 2)
h.Set("c", 3)
h.Set("d", 4)
h.Set("e", 5)
h.Set("f", 6)

h.Delete("c")
h.Set("d", 0)
h.Set("g", 3)
for h.Len() > 0 {
println(h.Pop().Key())
ele := h.Pop()
println(ele.Key(), ele.Value())
}
}

Expand Down
37 changes: 20 additions & 17 deletions README_CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@
- [简介](#简介)
- [目录](#目录)
- [动态数组](#动态数组)
- [去重](#去重)
- [排序](#排序)
- [过滤](#过滤)
- [去重](#去重)
- [排序](#排序)
- [过滤](#过滤)
- [](#堆)
- [N叉堆](#n叉堆)
- [N叉索引堆](#n叉索引堆)
- [N叉堆](#n叉堆)
- [哈希堆](#哈希堆)
- [](#栈)
- [队列](#队列)
- [双端队列](#双端队列)
Expand Down Expand Up @@ -123,9 +123,9 @@ func main() {

```

#### N叉索引堆
#### 哈希堆

在普通堆的基础上拓展了更新和删除功能, 常用于时间堆算法.
带哈希索引的堆结构.

```go
package main
Expand All @@ -135,17 +135,20 @@ import (
)

func main() {
var h = heap.NewIndexedHeap[int, struct{}](heap.Quadratic, func(a, b int) bool { return a > b })
h.Push(1, struct{}{})
h.Push(3, struct{}{})
h.Push(5, struct{}{})
h.Push(2, struct{}{})
h.Push(4, struct{}{})
h.Push(6, struct{}{})
h.DeleteByIndex(5)
h.UpdateKeyByIndex(3, 7)
var h = heap.NewHashHeap[string, int](func(a, b int) bool { return a < b })
h.Set("a", 1)
h.Set("b", 2)
h.Set("c", 3)
h.Set("d", 4)
h.Set("e", 5)
h.Set("f", 6)

h.Delete("c")
h.Set("d", 0)
h.Set("g", 3)
for h.Len() > 0 {
println(h.Pop().Key())
ele := h.Pop()
println(ele.Key(), ele.Value())
}
}

Expand Down
25 changes: 21 additions & 4 deletions algo/algorithm.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"github.com/lxzan/dao/types/cmp"
"reflect"
"strconv"
"strings"
)

// ToString 数字转字符串
Expand Down Expand Up @@ -135,13 +136,14 @@ func Map[A any, B any](arr []A, transfer func(i int, v A) B) []B {

// Filter 过滤器
func Filter[T any, A ~[]T](arr A, check func(i int, v T) bool) A {
var results = make([]T, 0, len(arr))
var j = 0
for i, v := range arr {
if check(i, v) {
results = append(results, arr[i])
arr[j] = arr[i]
j++
}
}
return results
return arr[:j]
}

// IsZero 零值判断
Expand Down Expand Up @@ -171,11 +173,26 @@ func NotNil(v any) bool {
}

// GroupBy 分组
func GroupBy[T any, A ~[]T, K cmp.Ordered](arr A, transfer func(i int, v T) K) map[K]A {
func GroupBy[T any, K cmp.Ordered, A ~[]T](arr A, transfer func(i int, v T) K) map[K]A {
var m = make(map[K]A, len(arr))
for index, value := range arr {
key := transfer(index, value)
m[key] = append(m[key], value)
}
return m
}

func SplitWithCallback(s string, sep string, cb func(index int, item string) bool) {
var n = len(sep)
var index = 0
for i := strings.Index(s, sep); i != -1; i = strings.Index(s, sep) {
if !cb(index, s[:i]) {
return
}
index++
if i+n <= len(s) {
s = s[i+n:]
}
}
cb(index, s)
}
56 changes: 52 additions & 4 deletions algo/algorithm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -171,11 +171,23 @@ func TestContains(t *testing.T) {
}

func TestFilter(t *testing.T) {
var arr = []int{1, 2, 3, 4}
arr = Filter(arr, func(i int, item int) bool {
return item%2 == 0
t.Run("", func(t *testing.T) {
var arr = []int{1, 2, 3, 4}
arr = Filter(arr, func(i int, item int) bool { return item%2 == 0 })
assert.ElementsMatch(t, arr, []int{2, 4})
})

t.Run("", func(t *testing.T) {
var arr = []int{1, 2, 3, 4}
arr = Filter(arr, func(i int, item int) bool { return item%2 == 1 })
assert.ElementsMatch(t, arr, []int{1, 3})
})

t.Run("", func(t *testing.T) {
var arr = []int{}
arr = Filter(arr, func(i int, item int) bool { return item%2 == 0 })
assert.ElementsMatch(t, arr, []int{})
})
assert.ElementsMatch(t, arr, []int{2, 4})
}

func TestIsZero(t *testing.T) {
Expand Down Expand Up @@ -240,6 +252,10 @@ func TestIsNil(t *testing.T) {
assert.True(t, IsNil(conn1))
assert.True(t, IsNil(conn2))
assert.False(t, IsNil(conn3))

assert.False(t, NotNil(conn1))
assert.False(t, NotNil(conn2))
assert.True(t, NotNil(conn3))
}

func TestNotNil(t *testing.T) {
Expand All @@ -253,3 +269,35 @@ func TestWithDefault(t *testing.T) {
assert.Equal(t, WithDefault("", "1"), "1")
assert.Equal(t, WithDefault("2", "1"), "2")
}

func TestSplitWithCallback(t *testing.T) {
t.Run("", func(t *testing.T) {
var path = "/api/v1/greet"
var values []string
SplitWithCallback(path, "/", func(index int, item string) bool {
values = append(values, item)
return true
})
assert.ElementsMatch(t, values, []string{"", "api", "v1", "greet"})
})

t.Run("", func(t *testing.T) {
var path = "/api/v1/greet/"
var values []string
SplitWithCallback(path, "/", func(index int, item string) bool {
values = append(values, item)
return true
})
assert.ElementsMatch(t, values, []string{"", "api", "v1", "greet", ""})
})

t.Run("", func(t *testing.T) {
var path = "/api/v1/greet"
var values []string
SplitWithCallback(path, "/", func(index int, item string) bool {
values = append(values, item)
return len(values) < 2
})
assert.ElementsMatch(t, values, []string{"", "api"})
})
}
Loading

0 comments on commit bf2c5b2

Please sign in to comment.