跳到主要内容
版本:2.10.x(Latest)

基本使用

package main

import (
"fmt"
"github.com/gogf/gf/v2/container/gtree"
"github.com/gogf/gf/v2/util/gutil"
)

func main() {
m := gtree.NewRedBlackTree(gutil.ComparatorInt)

// 设置键值对
for i := 0; i < 10; i++ {
m.Set(i, i*10)
}
// 查询大小
fmt.Println(m.Size())
// 批量设置键值对(不同的数据类型对象参数不同)
m.Sets(map[interface{}]interface{}{
10: 10,
11: 11,
})
fmt.Println(m.Size())

// 查询是否存在
fmt.Println(m.Contains(1))

// 查询键值
fmt.Println(m.Get(1))

// 删除数据项
m.Remove(9)
fmt.Println(m.Size())

// 批量删除
m.Removes([]interface{}{10, 11})
fmt.Println(m.Size())

// 当前键名列表(随机排序)
fmt.Println(m.Keys())
// 当前键值列表(随机排序)
fmt.Println(m.Values())

// 查询键名,当键值不存在时,写入给定的默认值
fmt.Println(m.GetOrSet(100, 100))

// 删除键值对,并返回对应的键值
fmt.Println(m.Remove(100))

// 遍历map
m.IteratorAsc(func(k interface{}, v interface{}) bool {
fmt.Printf("%v:%v ", k, v)
return true
})
fmt.Println()

// 清空map
m.Clear()

// 判断map是否为空
fmt.Println(m.IsEmpty())
}

执行后,输出结果为:

10
12
true
10
11
9
[0 1 2 3 4 5 6 7 8]
[0 10 20 30 40 50 60 70 80]
100
100
0:0 1:10 2:20 3:30 4:40 5:50 6:60 7:70 8:80
true

前序/后续遍历

package main

import (
"fmt"
"github.com/gogf/gf/v2/container/gtree"
"github.com/gogf/gf/v2/util/gutil"
)

func main() {
tree := gtree.NewAVLTree(gutil.ComparatorInt)
for i := 0; i < 10; i++ {
tree.Set(i, i*10)
}
// 打印树形
tree.Print()
// 前序遍历
fmt.Println("ASC:")
tree.IteratorAsc(func(key, value interface{}) bool {
fmt.Println(key, value)
return true
})
// 后续遍历
fmt.Println("DESC:")
tree.IteratorDesc(func(key, value interface{}) bool {
fmt.Println(key, value)
return true
})
}

执行后,输出结果为:

AVLTree
│ ┌── 9
│ ┌── 8
│ ┌── 7
│ │ │ ┌── 6
│ │ └── 5
│ │ └── 4
└── 3
│ ┌── 2
└── 1
└── 0

ASC:
0 0
1 10
2 20
3 30
4 40
5 50
6 60
7 70
8 80
9 90
DESC:
9 90
8 80
7 70
6 60
5 50
4 40
3 30
2 20
1 10
0 0

泛型使用示例

提示

版本要求:v2.10.0

v2.10.0 版本开始,gtree 提供了泛型版本,无需类型断言,更加类型安全。

泛型红黑树

package main

import (
"fmt"
"github.com/gogf/gf/v2/container/gtree"
"github.com/gogf/gf/v2/util/gutil"
)

func main() {
// 创建泛型红黑树
tree := gtree.NewRedBlackKVTree[int, int](gutil.ComparatorInt)

// 设置键值对
for i := 0; i < 10; i++ {
tree.Set(i, i*10)
}

// 查询大小
fmt.Println(tree.Size())

// 批量设置键值对
tree.SetMap(map[int]int{
10: 100,
11: 110,
})
fmt.Println(tree.Size())

// 查询是否存在
fmt.Println(tree.Contains(1))

// 查询键值(无需类型断言)
value, found := tree.Get(1)
if found {
fmt.Println(value) // 直接使用,value 是 int 类型
}

// 删除数据项
tree.Remove(9)
fmt.Println(tree.Size())

// 当前键名列表
fmt.Println(tree.Keys())
// 当前键值列表
fmt.Println(tree.Values())

// 查询键名,当键值不存在时,写入给定的默认值
fmt.Println(tree.GetOrSet(100, 1000))

// 遍历树(升序)
tree.IteratorAsc(func(key int, value int) bool {
fmt.Printf("%v:%v ", key, value)
return true
})
fmt.Println()

// 清空树
tree.Clear()

// 判断树是否为空
fmt.Println(tree.IsEmpty())
}

泛型 AVL 树

package main

import (
"fmt"
"github.com/gogf/gf/v2/container/gtree"
"github.com/gogf/gf/v2/util/gutil"
)

func main() {
// 创建泛型 AVL 树
tree := gtree.NewAVLKVTree[string, int](gutil.ComparatorString)

// 添加数据
tree.Set("apple", 1)
tree.Set("banana", 2)
tree.Set("cherry", 3)
tree.Set("date", 4)

// 获取值(类型安全)
if value, found := tree.Get("banana"); found {
fmt.Printf("banana的值: %d\n", value)
}

// 按序遍历
tree.IteratorAsc(func(key string, value int) bool {
fmt.Printf("%s: %d\n", key, value)
return true
})

// 获取最小和最大键
if left := tree.Left(); left != nil {
fmt.Printf("最小键: %s, 值: %d\n", left.Key, left.Value)
}
if right := tree.Right(); right != nil {
fmt.Printf("最大键: %s, 值: %d\n", right.Key, right.Value)
}
}

自定义类型示例

package main

import (
"fmt"
"github.com/gogf/gf/v2/container/gtree"
)

type User struct {
ID int
Name string
Age int
}

func main() {
// 创建以 int 为键,*User 为值的红黑树
// NilChecker 是可选的,用于解决 typed nil 问题和提升性能
// 不使用 NilChecker 时,组件会使用反射判断 nil
tree := gtree.NewRedBlackKVTreeWithChecker[int, *User](
func(a, b int) int {
if a < b {
return -1
} else if a > b {
return 1
}
return 0
},
func(user *User) bool {
// 自定义 nil 检查:user 为 nil 或 ID 为 0 视为 nil
return user == nil || user.ID == 0
},
)

// 添加用户
tree.Set(1, &User{ID: 1, Name: "张三", Age: 20})
tree.Set(2, &User{ID: 2, Name: "李四", Age: 25})
tree.Set(3, &User{ID: 3, Name: "王五", Age: 30})

// 查询用户(无需类型断言)
if user, found := tree.Get(2); found {
fmt.Printf("用户ID: %d, 姓名: %s, 年龄: %d\n", user.ID, user.Name, user.Age)
}

// 遍历所有用户
tree.IteratorAsc(func(id int, user *User) bool {
fmt.Printf("ID: %d, 姓名: %s, 年龄: %d\n", id, user.Name, user.Age)
return true
})

// 测试 nil checker
tree.Set(4, &User{ID: 0, Name: "无效用户", Age: 0})
_, found := tree.Get(4)
fmt.Printf("ID=0 的用户是否存在: %v\n", found) // false,因为被视为 nil
}