mirror of
https://github.com/hlccd/goSTL.git
synced 2025-01-18 22:09:33 +08:00
276 lines
7.2 KiB
Go
276 lines
7.2 KiB
Go
package radix
|
|
|
|
//@Title radix
|
|
//@Description
|
|
// 前缀基数树-radix
|
|
// 以多叉树的形式实现,根据'/'进行string分割,将分割后的string数组进行段存储
|
|
// 不存储其他元素,仅对string进行分段存储和模糊匹配
|
|
// 使用互斥锁实现并发控制
|
|
|
|
import (
|
|
"github.com/hlccd/goSTL/utils/iterator"
|
|
"sync"
|
|
)
|
|
|
|
//radix前缀基数树结构体
|
|
//该实例存储前缀基数树的根节点
|
|
//同时保存该树已经存储了多少个元素
|
|
type radix struct {
|
|
root *node //前缀基数树的根节点指针
|
|
size int //当前已存放的元素数量
|
|
mutex sync.Mutex //并发控制锁
|
|
}
|
|
|
|
//radix前缀基数树容器接口
|
|
//存放了radix前缀基数树可使用的函数
|
|
//对应函数介绍见下方
|
|
type radixer interface {
|
|
Iterator() (i *Iterator.Iterator) //返回包含该radix的所有string
|
|
Size() (num int) //返回该radix中保存的元素个数
|
|
Clear() //清空该radix
|
|
Empty() (b bool) //判断该radix是否为空
|
|
Insert(s string) (b bool) //向radix中插入string
|
|
Erase(s string) (b bool) //从radix中删除string
|
|
Delete(s string) (num int) //从radix中删除以s为前缀的所有string
|
|
Count(s string) (num int) //从radix中寻找以s为前缀的string单词数
|
|
Mate(s string) (m map[string]string, ok bool) //利用radix树中的string对s进行模糊匹配,':'可模糊匹配该层,'*'可模糊匹配后面所有
|
|
}
|
|
|
|
//@title New
|
|
//@description
|
|
// 新建一个radix前缀基数树容器并返回
|
|
// 初始根节点为nil
|
|
//@receiver nil
|
|
//@param nil
|
|
//@return r *radix 新建的radix指针
|
|
func New() (r *radix) {
|
|
return &radix{
|
|
root: newNode(""),
|
|
size: 0,
|
|
mutex: sync.Mutex{},
|
|
}
|
|
}
|
|
|
|
//@title Iterator
|
|
//@description
|
|
// 以radix前缀基数树做接收者
|
|
// 将该radix中所有存放的string放入迭代器中并返回
|
|
//@receiver r *radix 接受者radix的指针
|
|
//@param nil
|
|
//@return i *iterator.Iterator 新建的Iterator迭代器指针
|
|
func (r *radix) Iterator() (i *Iterator.Iterator) {
|
|
if r == nil {
|
|
return nil
|
|
}
|
|
r.mutex.Lock()
|
|
es := r.root.inOrder("")
|
|
i = Iterator.New(&es)
|
|
r.mutex.Unlock()
|
|
return i
|
|
}
|
|
|
|
//@title Size
|
|
//@description
|
|
// 以radix前缀基数树做接收者
|
|
// 返回该容器当前含有元素的数量
|
|
// 如果容器为nil返回0
|
|
//@receiver r *radix 接受者radix的指针
|
|
//@param nil
|
|
//@return num int 容器中实际使用元素所占空间大小
|
|
func (r *radix) Size() (num int) {
|
|
if r == nil {
|
|
return 0
|
|
}
|
|
if r.root == nil {
|
|
return 0
|
|
}
|
|
return r.size
|
|
}
|
|
|
|
//@title Clear
|
|
//@description
|
|
// 以radix前缀基数树做接收者
|
|
// 将该容器中所承载的元素清空
|
|
// 将该容器的size置0
|
|
//@receiver r *radix 接受者radix的指针
|
|
//@param nil
|
|
//@return nil
|
|
func (r *radix) Clear() {
|
|
if r == nil {
|
|
return
|
|
}
|
|
r.mutex.Lock()
|
|
r.root = newNode("")
|
|
r.size = 0
|
|
r.mutex.Unlock()
|
|
}
|
|
|
|
//@title Empty
|
|
//@description
|
|
// 以radix前缀基数树做接收者
|
|
// 判断该radix是否含有元素
|
|
// 如果含有元素则不为空,返回false
|
|
// 如果不含有元素则说明为空,返回true
|
|
// 如果容器不存在,返回true
|
|
//@receiver r *radix 接受者radix的指针
|
|
//@param nil
|
|
//@return b bool 该容器是空的吗?
|
|
func (r *radix) Empty() (b bool) {
|
|
if r == nil {
|
|
return true
|
|
}
|
|
return r.size == 0
|
|
}
|
|
|
|
//@title Insert
|
|
//@description
|
|
// 以radix前缀基数树做接收者
|
|
// 向radix插入string
|
|
// 将对string进行解析,按'/'进行分层,':'为首则为模糊匹配该层,'*'为首则为模糊匹配后面所有
|
|
// 已经存在则无法重复插入
|
|
//@receiver r *radix 接受者radix的指针
|
|
//@param s string 待插入string
|
|
//@return b bool 添加成功?
|
|
func (r *radix) Insert(s string) (b bool) {
|
|
if r == nil {
|
|
return false
|
|
}
|
|
//解析s并按规则重构s
|
|
ss, s := analysis(s)
|
|
r.mutex.Lock()
|
|
if r.root == nil {
|
|
//避免根节点为nil
|
|
r.root = newNode("")
|
|
}
|
|
//从根节点开始插入
|
|
b = r.root.insert(s, ss, 0)
|
|
if b {
|
|
//插入成功,size+1
|
|
r.size++
|
|
}
|
|
r.mutex.Unlock()
|
|
return b
|
|
}
|
|
|
|
//@title Erase
|
|
//@description
|
|
// 以radix前缀基数树做接收者
|
|
// 从radix树中删除元素string
|
|
//@receiver r *radix 接受者radix的指针
|
|
//@param s string 待删除的string
|
|
//@return b bool 删除成功?
|
|
func (r *radix) Erase(s string) (b bool) {
|
|
if r.Empty() {
|
|
return false
|
|
}
|
|
if len(s) == 0 {
|
|
return false
|
|
}
|
|
if r.root == nil {
|
|
//根节点为nil即无法删除
|
|
return false
|
|
}
|
|
//解析s并按规则重构s
|
|
ss, _ := analysis(s)
|
|
r.mutex.Lock()
|
|
//从根节点开始删除
|
|
b = r.root.erase(ss, 0)
|
|
if b {
|
|
//删除成功,size-1
|
|
r.size--
|
|
if r.size == 0 {
|
|
//所有string都被删除,根节点置为nil
|
|
r.root = nil
|
|
}
|
|
}
|
|
r.mutex.Unlock()
|
|
return b
|
|
}
|
|
|
|
//@title Delete
|
|
//@description
|
|
// 以radix前缀基数树做接收者
|
|
// 从radix树中删除以s为前缀的所有string
|
|
//@receiver r *radix 接受者radix的指针
|
|
//@param s string 待删除string的前缀
|
|
//@return num int 被删除的元素的数量
|
|
func (r *radix) Delete(s string) (num int) {
|
|
if r.Empty() {
|
|
return 0
|
|
}
|
|
if len(s) == 0 {
|
|
return 0
|
|
}
|
|
if r.root == nil {
|
|
return 0
|
|
}
|
|
//解析s并按规则重构s
|
|
ss, _ := analysis(s)
|
|
r.mutex.Lock()
|
|
//从根节点开始删除
|
|
num = r.root.delete(ss, 0)
|
|
if num > 0 {
|
|
//删除成功
|
|
r.size -= num
|
|
if r.size <= 0 {
|
|
//所有string都被删除,根节点置为nil
|
|
r.root = nil
|
|
}
|
|
}
|
|
r.mutex.Unlock()
|
|
return num
|
|
}
|
|
|
|
//@title Count
|
|
//@description
|
|
// 以radix前缀基数树做接收者
|
|
// 从radix中查找以s为前缀的所有string的个数
|
|
// 如果存在以s为前缀的则返回大于0的值即其数量
|
|
// 如果未找到则返回0
|
|
//@receiver r *radix 接受者radix的指针
|
|
//@param s string 待查找的前缀s
|
|
//@return num int 待查找前缀在radix树中存在的数量
|
|
func (r *radix) Count(s string) (num int) {
|
|
if r.Empty() {
|
|
return 0
|
|
}
|
|
if r.root == nil {
|
|
return 0
|
|
}
|
|
if len(s) == 0 {
|
|
return 0
|
|
}
|
|
//解析s并按规则重构s
|
|
ss, _ := analysis(s)
|
|
r.mutex.Lock()
|
|
num = r.root.count(ss, 0)
|
|
r.mutex.Unlock()
|
|
return num
|
|
}
|
|
|
|
//@title Mate
|
|
//@description
|
|
// 以radix前缀基数树做接收者
|
|
// 从radix中查找以s为信息的第一个可以模糊匹配到的key和value的映射表
|
|
// key是radix树中的段名,value是s中的段名
|
|
// 如果未找到则返回nil和false
|
|
// 否则返回一个映射表和true
|
|
//@receiver r *radix 接受者radix的指针
|
|
//@param s string 待查找的信息s
|
|
//@return m map[string]string s从前缀基数树中利用模糊匹配到的所有key和value的映射
|
|
//@return ok bool 匹配成功?
|
|
func (r *radix) Mate(s string) (m map[string]string, ok bool) {
|
|
if r.Empty() {
|
|
return nil, false
|
|
}
|
|
if len(s) == 0 {
|
|
return nil, false
|
|
}
|
|
if r.root == nil {
|
|
return nil, false
|
|
}
|
|
//将s按'/'进行分割,并去掉第一个即去掉"",随后一次按照分层结果进行查找
|
|
m, ok = r.root.mate(s, 0)
|
|
return m, ok
|
|
}
|