mirror of
https://github.com/hlccd/goSTL.git
synced 2025-01-18 22:09:33 +08:00
新增单词查找树Trie的实现,修改了一些之前实现的数据结构的注释
This commit is contained in:
parent
e432cf42e5
commit
8c4ffc8f0f
@ -1,5 +1,13 @@
|
|||||||
package algorithm
|
package algorithm
|
||||||
|
|
||||||
|
//@Title algorithm
|
||||||
|
//@Description
|
||||||
|
// hash函数
|
||||||
|
// 定义了一个hash函数类型,该类型可传入一个key并返回其hash值
|
||||||
|
// 该包内定义了一些自带类型的hash函数
|
||||||
|
// 当使用自定义的数据结构时若不传入hash函数则使用默认的hash函数
|
||||||
|
// 若传入类型非系统自带类型,则返回nil同时对数据的插入失败
|
||||||
|
|
||||||
type Hasher func(key interface{}) uint64
|
type Hasher func(key interface{}) uint64
|
||||||
|
|
||||||
func GetHash(e interface{}) (hash Hasher) {
|
func GetHash(e interface{}) (hash Hasher) {
|
||||||
@ -47,37 +55,37 @@ func boolHash(key interface{}) uint64 {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
func intHash(key interface{}) uint64 {
|
func intHash(key interface{}) uint64 {
|
||||||
return uint64(key.(int) * key.(int)/2)
|
return uint64(key.(int) * key.(int) / 2)
|
||||||
}
|
}
|
||||||
func int8Hash(key interface{}) uint64 {
|
func int8Hash(key interface{}) uint64 {
|
||||||
return uint64(key.(int8) * key.(int8)/2)
|
return uint64(key.(int8) * key.(int8) / 2)
|
||||||
}
|
}
|
||||||
func uint8Hash(key interface{}) uint64 {
|
func uint8Hash(key interface{}) uint64 {
|
||||||
return uint64(key.(uint8) * key.(uint8)/2)
|
return uint64(key.(uint8) * key.(uint8) / 2)
|
||||||
}
|
}
|
||||||
func int16Hash(key interface{}) uint64 {
|
func int16Hash(key interface{}) uint64 {
|
||||||
return uint64(key.(int16) * key.(int16)/2)
|
return uint64(key.(int16) * key.(int16) / 2)
|
||||||
}
|
}
|
||||||
func uint16Hash(key interface{}) uint64 {
|
func uint16Hash(key interface{}) uint64 {
|
||||||
return uint64(key.(uint16) * key.(uint16)/2)
|
return uint64(key.(uint16) * key.(uint16) / 2)
|
||||||
}
|
}
|
||||||
func int32Hash(key interface{}) uint64 {
|
func int32Hash(key interface{}) uint64 {
|
||||||
return uint64(key.(int32) * key.(int32)/2)
|
return uint64(key.(int32) * key.(int32) / 2)
|
||||||
}
|
}
|
||||||
func uint32Hash(key interface{}) uint64 {
|
func uint32Hash(key interface{}) uint64 {
|
||||||
return uint64(key.(uint32) * key.(uint32)/2)
|
return uint64(key.(uint32) * key.(uint32) / 2)
|
||||||
}
|
}
|
||||||
func int64Hash(key interface{}) uint64 {
|
func int64Hash(key interface{}) uint64 {
|
||||||
return uint64(key.(int64) * key.(int64)/2)
|
return uint64(key.(int64) * key.(int64) / 2)
|
||||||
}
|
}
|
||||||
func uint64Hash(key interface{}) uint64 {
|
func uint64Hash(key interface{}) uint64 {
|
||||||
return uint64(key.(uint64) * key.(uint64)/2)
|
return uint64(key.(uint64) * key.(uint64) / 2)
|
||||||
}
|
}
|
||||||
func float32Hash(key interface{}) uint64 {
|
func float32Hash(key interface{}) uint64 {
|
||||||
return uint64(key.(float32) * key.(float32)/2)
|
return uint64(key.(float32) * key.(float32) / 2)
|
||||||
}
|
}
|
||||||
func float64Hash(key interface{}) uint64 {
|
func float64Hash(key interface{}) uint64 {
|
||||||
return uint64(key.(float64) * key.(float64)/2)
|
return uint64(key.(float64) * key.(float64) / 2)
|
||||||
}
|
}
|
||||||
func complex64Hash(key interface{}) uint64 {
|
func complex64Hash(key interface{}) uint64 {
|
||||||
r := uint64(real(key.(complex64)))
|
r := uint64(real(key.(complex64)))
|
||||||
|
@ -37,7 +37,7 @@ type avlTreer interface {
|
|||||||
Size() (num int) //返回该二叉树中保存的元素个数
|
Size() (num int) //返回该二叉树中保存的元素个数
|
||||||
Clear() //清空该二叉树
|
Clear() //清空该二叉树
|
||||||
Empty() (b bool) //判断该二叉树是否为空
|
Empty() (b bool) //判断该二叉树是否为空
|
||||||
Insert(e interface{}) (b bool) //向二叉树中插入元素e
|
Insert(e interface{}) (b bool) //向二叉树中插入元素e
|
||||||
Erase(e interface{}) (b bool) //从二叉树中删除元素e
|
Erase(e interface{}) (b bool) //从二叉树中删除元素e
|
||||||
Count(e interface{}) (num int) //从二叉树中寻找元素e并返回其个数
|
Count(e interface{}) (num int) //从二叉树中寻找元素e并返回其个数
|
||||||
}
|
}
|
||||||
@ -149,7 +149,7 @@ func (avl *AvlTree) Empty() (b bool) {
|
|||||||
//@receiver avl *avlTree 接受者avlTree的指针
|
//@receiver avl *avlTree 接受者avlTree的指针
|
||||||
//@param e interface{} 待插入元素
|
//@param e interface{} 待插入元素
|
||||||
//@return b bool 添加成功?
|
//@return b bool 添加成功?
|
||||||
func (avl *AvlTree) Insert(e interface{}) (b bool){
|
func (avl *AvlTree) Insert(e interface{}) (b bool) {
|
||||||
if avl == nil {
|
if avl == nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -186,7 +186,7 @@ func (avl *AvlTree) Insert(e interface{}) (b bool){
|
|||||||
// 如果该二叉树仅持有一个元素且根节点等价于待删除元素,则将二叉树根节点置为nil
|
// 如果该二叉树仅持有一个元素且根节点等价于待删除元素,则将二叉树根节点置为nil
|
||||||
//@receiver avl *avlTree 接受者avlTree的指针
|
//@receiver avl *avlTree 接受者avlTree的指针
|
||||||
//@param e interface{} 待删除元素
|
//@param e interface{} 待删除元素
|
||||||
//@return b bool 删除成功
|
//@return b bool 删除成功?
|
||||||
func (avl *AvlTree) Erase(e interface{}) (b bool) {
|
func (avl *AvlTree) Erase(e interface{}) (b bool) {
|
||||||
if avl == nil {
|
if avl == nil {
|
||||||
return false
|
return false
|
||||||
|
204
goSTL/data_structure/trie/node.go
Normal file
204
goSTL/data_structure/trie/node.go
Normal file
@ -0,0 +1,204 @@
|
|||||||
|
package trie
|
||||||
|
|
||||||
|
//@Title trie
|
||||||
|
//@Description
|
||||||
|
// 单词查找树的节点
|
||||||
|
// 可通过节点的分叉对string进行查找
|
||||||
|
// 增添string时候只需要增删结点即可
|
||||||
|
// 当string到终点时存储元素
|
||||||
|
|
||||||
|
//node树节点结构体
|
||||||
|
//该节点是trie的树节点
|
||||||
|
//结点存储到此时的string的前缀数量
|
||||||
|
//以son为分叉存储下属的string
|
||||||
|
//该节点同时存储其元素
|
||||||
|
type node struct {
|
||||||
|
num int
|
||||||
|
son [64]*node
|
||||||
|
value interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
//@title newNode
|
||||||
|
//@description
|
||||||
|
// 新建一个单词查找树节点并返回
|
||||||
|
// 将传入的元素e作为该节点的承载元素
|
||||||
|
//@receiver nil
|
||||||
|
//@param e interface{} 承载元素e
|
||||||
|
//@return n *node 新建的单词查找树节点的指针
|
||||||
|
func newNode(e interface{}) (n *node) {
|
||||||
|
return &node{
|
||||||
|
num: 0,
|
||||||
|
value: e,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//@title inOrder
|
||||||
|
//@description
|
||||||
|
// 以node单词查找树节点做接收者
|
||||||
|
// 遍历其分叉以找到其存储的所有string
|
||||||
|
//@receiver n *node 接受者node的指针
|
||||||
|
//@param s string 到该结点时的前缀string
|
||||||
|
//@return es []interface{} 以该前缀s为前缀的所有string的集合
|
||||||
|
func (n *node) inOrder(s string) (es []interface{}) {
|
||||||
|
if n == nil {
|
||||||
|
return es
|
||||||
|
}
|
||||||
|
if n.value != nil {
|
||||||
|
es = append(es, s)
|
||||||
|
}
|
||||||
|
for i, p := 0, 0; i < 62 && p < n.num; i++ {
|
||||||
|
if n.son[i] != nil {
|
||||||
|
if i < 26 {
|
||||||
|
es = append(es, n.son[i].inOrder(s+string(i+'a'))...)
|
||||||
|
} else if i < 52 {
|
||||||
|
es = append(es, n.son[i].inOrder(s+string(i-26+'A'))...)
|
||||||
|
} else {
|
||||||
|
es = append(es, n.son[i].inOrder(s+string(i-52+'0'))...)
|
||||||
|
}
|
||||||
|
p++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return es
|
||||||
|
}
|
||||||
|
|
||||||
|
//@title getIdx
|
||||||
|
//@description
|
||||||
|
// 传入一个byte并根据其值返回其映射到分叉的值
|
||||||
|
// 当不属于'a'~'z','A'~'Z','0'~'9','+','/'时返回-1
|
||||||
|
//@receiver nil
|
||||||
|
//@param c byte 待映射的ASCII码
|
||||||
|
//@return idx int 以c映射出的分叉下标
|
||||||
|
func getIdx(c byte) (idx int) {
|
||||||
|
if c >= 'a' && c <= 'z' {
|
||||||
|
idx = int(c - 'a')
|
||||||
|
} else if c >= 'A' && c <= 'Z' {
|
||||||
|
idx = int(c-'A') + 26
|
||||||
|
} else if c >= '0' && c <= '9' {
|
||||||
|
idx = int(c-'0') + 52
|
||||||
|
} else if c == '+' {
|
||||||
|
idx = 62
|
||||||
|
} else if c == '/' {
|
||||||
|
idx = 63
|
||||||
|
} else {
|
||||||
|
idx = -1
|
||||||
|
}
|
||||||
|
return idx
|
||||||
|
}
|
||||||
|
|
||||||
|
//@title insert
|
||||||
|
//@description
|
||||||
|
// 以node单词查找树节点做接收者
|
||||||
|
// 从n节点中继续插入以s为索引的元素e,且当前抵达的string位置为p
|
||||||
|
// 当到达s终点时进行插入,如果此时node承载了元素则插入失败,否则成功
|
||||||
|
// 当未到达终点时,根据当前抵达的位置去寻找其子结点继续遍历即可
|
||||||
|
//@receiver n *node 接受者node的指针
|
||||||
|
//@param s string 待插入元素的索引s
|
||||||
|
//@param p int 索引当前抵达的位置
|
||||||
|
//@param e interface{} 待插入元素e
|
||||||
|
//@return b bool 是否插入成功?
|
||||||
|
func (n *node) insert(s string, p int, e interface{}) (b bool) {
|
||||||
|
if p == len(s) {
|
||||||
|
if n.value != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
n.value = e
|
||||||
|
n.num++
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
idx := getIdx(s[p])
|
||||||
|
if idx == -1 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if n.son[idx] == nil {
|
||||||
|
n.son[idx] = newNode(nil)
|
||||||
|
}
|
||||||
|
b = n.son[idx].insert(s, p+1, e)
|
||||||
|
if b {
|
||||||
|
n.num++
|
||||||
|
}
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
//@title erase
|
||||||
|
//@description
|
||||||
|
// 以node单词查找树节点做接收者
|
||||||
|
// 从n节点中继续删除以s为索引的元素e,且当前抵达的string位置为p
|
||||||
|
// 当到达s终点时进行删除,如果此时node未承载元素则删除失败,否则成功
|
||||||
|
// 当未到达终点时,根据当前抵达的位置去寻找其子结点继续遍历即可,若其分叉为nil则直接失败
|
||||||
|
//@receiver n *node 接受者node的指针
|
||||||
|
//@param s string 待删除元素的索引s
|
||||||
|
//@param p int 索引当前抵达的位置
|
||||||
|
//@return b bool 是否删除成功?
|
||||||
|
func (n *node) erase(s string, p int) (b bool) {
|
||||||
|
if p == len(s) {
|
||||||
|
if n.value != nil {
|
||||||
|
n.value = nil
|
||||||
|
n.num--
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
idx := getIdx(s[p])
|
||||||
|
if idx == -1 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if n.son[idx] == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
b = n.son[idx].erase(s, p+1)
|
||||||
|
if b {
|
||||||
|
n.num--
|
||||||
|
if n.son[idx].num == 0 {
|
||||||
|
n.son[idx] = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
//@title count
|
||||||
|
//@description
|
||||||
|
// 以node单词查找树节点做接收者
|
||||||
|
// 从n节点中继续查找以s为前缀索引的元素e,且当前抵达的string位置为p
|
||||||
|
// 当到达s终点时返回其值即可
|
||||||
|
// 当未到达终点时,根据当前抵达的位置去寻找其子结点继续遍历即可,当其分叉为nil则直接返回0
|
||||||
|
//@receiver n *node 接受者node的指针
|
||||||
|
//@param s string 待查找元素的前缀索引
|
||||||
|
//@param p int 索引当前抵达的位置
|
||||||
|
//@return num int 以该s为前缀的string的数量
|
||||||
|
func (n *node) count(s string, p int) (num int) {
|
||||||
|
if p == len(s) {
|
||||||
|
return n.num
|
||||||
|
}
|
||||||
|
idx := getIdx(s[p])
|
||||||
|
if idx == -1 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
if n.son[idx] == nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return n.son[idx].count(s, p+1)
|
||||||
|
}
|
||||||
|
|
||||||
|
//@title find
|
||||||
|
//@description
|
||||||
|
// 以node单词查找树节点做接收者
|
||||||
|
// 从n节点中继续查找以s为前缀索引的元素e,且当前抵达的string位置为p
|
||||||
|
// 当到达s终点时返回其承载的元素即可
|
||||||
|
// 当未到达终点时,根据当前抵达的位置去寻找其子结点继续遍历即可,当其分叉为nil则直接返回nil
|
||||||
|
//@receiver n *node 接受者node的指针
|
||||||
|
//@param s string 待查找元素的前缀索引
|
||||||
|
//@param p int 索引当前抵达的位置
|
||||||
|
//@return e interface{} 该索引所指向的元素e
|
||||||
|
func (n *node) find(s string, p int) (e interface{}) {
|
||||||
|
if p == len(s) {
|
||||||
|
return n.value
|
||||||
|
}
|
||||||
|
idx := getIdx(s[p])
|
||||||
|
if idx == -1 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if n.son[idx] == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return n.son[idx].find(s, p+1)
|
||||||
|
}
|
243
goSTL/data_structure/trie/trie.go
Normal file
243
goSTL/data_structure/trie/trie.go
Normal file
@ -0,0 +1,243 @@
|
|||||||
|
package trie
|
||||||
|
|
||||||
|
//@Title trie
|
||||||
|
//@Description
|
||||||
|
// 单词查找树-Trie
|
||||||
|
// 以多叉树的形式实现,本次实现中有64叉,即a~z,A~Z,0~9,'+','/'共64个,对应base64的字符
|
||||||
|
// 当存储的string中出现其他字符则无法存储
|
||||||
|
// 存储的string可以携带一个元素
|
||||||
|
// 结点不允许覆盖,即插入值已经存在时会插入失败,需要先删除原值
|
||||||
|
// 使用互斥锁实现并发控制
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/hlccd/goSTL/utils/iterator"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
//trie单词查找树结构体
|
||||||
|
//该实例存储单词查找树的根节点
|
||||||
|
//同时保存该树已经存储了多少个元素
|
||||||
|
//整个树不允许重复插入,若出现重复插入则直接失败
|
||||||
|
type trie struct {
|
||||||
|
root *node //根节点指针
|
||||||
|
size int //存放的元素数量
|
||||||
|
mutex sync.Mutex //并发控制锁
|
||||||
|
}
|
||||||
|
|
||||||
|
//trie单词查找树容器接口
|
||||||
|
//存放了trie单词查找树可使用的函数
|
||||||
|
//对应函数介绍见下方
|
||||||
|
type trieer interface {
|
||||||
|
Iterator() (i *Iterator.Iterator) //返回包含该trie的所有string
|
||||||
|
Size() (num int) //返回该trie中保存的元素个数
|
||||||
|
Clear() //清空该trie
|
||||||
|
Empty() (b bool) //判断该trie是否为空
|
||||||
|
Insert(s string, e interface{}) (b bool) //向trie中插入string并携带元素e
|
||||||
|
Erase(s string) (b bool) //从trie中删除以s为索引的元素e
|
||||||
|
Count(s string) (num int) //从trie中寻找以s为前缀的string单词数
|
||||||
|
Find(s string) (e interface{}) //从trie中寻找以s为索引的元素e
|
||||||
|
}
|
||||||
|
|
||||||
|
//@title New
|
||||||
|
//@description
|
||||||
|
// 新建一个trie单词查找树容器并返回
|
||||||
|
// 初始根节点为nil
|
||||||
|
//@receiver nil
|
||||||
|
//@param nil
|
||||||
|
//@return t *trie 新建的trie指针
|
||||||
|
func New() (t *trie) {
|
||||||
|
return &trie{
|
||||||
|
root: newNode(nil),
|
||||||
|
size: 0,
|
||||||
|
mutex: sync.Mutex{},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//@title Iterator
|
||||||
|
//@description
|
||||||
|
// 以trie单词查找树做接收者
|
||||||
|
// 将该trie中所有存放的string放入迭代器中并返回
|
||||||
|
//@receiver t *trie 接受者trie的指针
|
||||||
|
//@param nil
|
||||||
|
//@return i *iterator.Iterator 新建的Iterator迭代器指针
|
||||||
|
func (t *trie) Iterator() (i *Iterator.Iterator) {
|
||||||
|
if t == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
t.mutex.Lock()
|
||||||
|
//找到trie中存在的所有string
|
||||||
|
es := t.root.inOrder("")
|
||||||
|
i = Iterator.New(&es)
|
||||||
|
t.mutex.Unlock()
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
|
||||||
|
//@title Size
|
||||||
|
//@description
|
||||||
|
// 以trie单词查找树做接收者
|
||||||
|
// 返回该容器当前含有元素的数量
|
||||||
|
// 如果容器为nil返回0
|
||||||
|
//@receiver t *trie 接受者trie的指针
|
||||||
|
//@param nil
|
||||||
|
//@return num int 容器中实际使用元素所占空间大小
|
||||||
|
func (t *trie) Size() (num int) {
|
||||||
|
if t == nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return t.size
|
||||||
|
}
|
||||||
|
|
||||||
|
//@title Clear
|
||||||
|
//@description
|
||||||
|
// 以trie单词查找树做接收者
|
||||||
|
// 将该容器中所承载的元素清空
|
||||||
|
// 将该容器的size置0
|
||||||
|
//@receiver t *trie 接受者trie的指针
|
||||||
|
//@param nil
|
||||||
|
//@return nil
|
||||||
|
func (t *trie) Clear() {
|
||||||
|
if t == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
t.mutex.Lock()
|
||||||
|
t.root = newNode(nil)
|
||||||
|
t.size = 0
|
||||||
|
t.mutex.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
//@title Empty
|
||||||
|
//@description
|
||||||
|
// 以trie单词查找树做接收者
|
||||||
|
// 判断该trie是否含有元素
|
||||||
|
// 如果含有元素则不为空,返回false
|
||||||
|
// 如果不含有元素则说明为空,返回true
|
||||||
|
// 如果容器不存在,返回true
|
||||||
|
//@receiver t *trie 接受者trie的指针
|
||||||
|
//@param nil
|
||||||
|
//@return b bool 该容器是空的吗?
|
||||||
|
func (t *trie) Empty() (b bool) {
|
||||||
|
if t.Size() > 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
//@title Insert
|
||||||
|
//@description
|
||||||
|
// 以trie单词查找树做接收者
|
||||||
|
// 向trie插入以string类型的s为索引的元素e
|
||||||
|
// 若存在重复的s则插入失败,不允许覆盖
|
||||||
|
// 否则插入成功
|
||||||
|
//@receiver t *trie 接受者trie的指针
|
||||||
|
//@param s string 待插入元素的索引s
|
||||||
|
//@param e interface{} 待插入元素e
|
||||||
|
//@return b bool 添加成功?
|
||||||
|
func (t *trie) Insert(s string, e interface{}) (b bool) {
|
||||||
|
if t == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if len(s) == 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
t.mutex.Lock()
|
||||||
|
if t.root == nil {
|
||||||
|
//避免根节点为nil
|
||||||
|
t.root = newNode(nil)
|
||||||
|
}
|
||||||
|
//从根节点开始插入
|
||||||
|
b = t.root.insert(s, 0, e)
|
||||||
|
if b {
|
||||||
|
//插入成功,size+1
|
||||||
|
t.size++
|
||||||
|
}
|
||||||
|
t.mutex.Unlock()
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
//@title Erase
|
||||||
|
//@description
|
||||||
|
// 以trie单词查找树做接收者
|
||||||
|
// 从trie树中删除元素以s为索引的元素e
|
||||||
|
//@receiver t *trie 接受者trie的指针
|
||||||
|
//@param s string 待删除元素的索引
|
||||||
|
//@return b bool 删除成功?
|
||||||
|
func (t *trie) Erase(s string) (b bool) {
|
||||||
|
if t == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if t.Empty() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if len(s) == 0 {
|
||||||
|
//长度为0无法删除
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if t.root == nil {
|
||||||
|
//根节点为nil即无法删除
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
t.mutex.Lock()
|
||||||
|
//从根节点开始删除
|
||||||
|
b = t.root.erase(s, 0)
|
||||||
|
if b {
|
||||||
|
//删除成功,size-1
|
||||||
|
t.size--
|
||||||
|
if t.size == 0 {
|
||||||
|
//所有string都被删除,根节点置为nil
|
||||||
|
t.root = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
t.mutex.Unlock()
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
//@title Count
|
||||||
|
//@description
|
||||||
|
// 以trie单词查找树做接收者
|
||||||
|
// 从trie中查找以s为前缀的所有string的个数
|
||||||
|
// 如果存在以s为前缀的则返回大于0的值即其数量
|
||||||
|
// 如果未找到则返回0
|
||||||
|
//@receiver t *trie 接受者trie的指针
|
||||||
|
//@param s string 待查找的前缀s
|
||||||
|
//@return num int 待查找前缀在trie中存在的数量
|
||||||
|
func (t *trie) Count(s string) (num int) {
|
||||||
|
if t == nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
if t.Empty() {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
if t.root == nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
t.mutex.Lock()
|
||||||
|
//统计所有以s为前缀的string的数量并返回
|
||||||
|
num = int(t.root.count(s, 0))
|
||||||
|
t.mutex.Unlock()
|
||||||
|
return num
|
||||||
|
}
|
||||||
|
|
||||||
|
//@title Find
|
||||||
|
//@description
|
||||||
|
// 以trie单词查找树做接收者
|
||||||
|
// 从trie中查找以s为索引的元素e,找到则返回e
|
||||||
|
// 如果未找到则返回nil
|
||||||
|
//@receiver t *trie 接受者trie的指针
|
||||||
|
//@param s string 待查找索引s
|
||||||
|
//@return ans interface{} 待查找索引所指向的元素
|
||||||
|
func (t *trie) Find(s string) (e interface{}) {
|
||||||
|
if t == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if t.Empty() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if t.root == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
t.mutex.Lock()
|
||||||
|
//从根节点开始查找以s为索引的元素e
|
||||||
|
e = t.root.find(s, 0)
|
||||||
|
t.mutex.Unlock()
|
||||||
|
return e
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user