From fdb989f4c05f6ac3f2fb7767d70dab81533887a3 Mon Sep 17 00:00:00 2001 From: hlccd <56643462+hlccd@users.noreply.github.com> Date: Sun, 26 Dec 2021 17:27:12 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=B8=BAradix?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- goSTL/data_structure/rax/node.go | 221 ---------------------- goSTL/data_structure/rax/rax.go | 303 ------------------------------- 2 files changed, 524 deletions(-) delete mode 100644 goSTL/data_structure/rax/node.go delete mode 100644 goSTL/data_structure/rax/rax.go diff --git a/goSTL/data_structure/rax/node.go b/goSTL/data_structure/rax/node.go deleted file mode 100644 index 3c8047d..0000000 --- a/goSTL/data_structure/rax/node.go +++ /dev/null @@ -1,221 +0,0 @@ -package rax - -//@Title rax -//@Description -// 前缀基数树的节点 -// 可通过节点的分叉对string进行查找 -// 增添string时候需要增删结点,同时将结点内置的map中增删删除对应的string即可 -// 当string到终点时存储元素 - -//node树节点结构体 -//该节点是rax的树节点 -//结点存储到此时的string的前缀数量 -//son存储其下属分叉的子结点指针 -//该节点同时存储其元素 -type node struct { - name string //以当前结点的string内容 - num int //以当前结点为前缀的数量 - value interface{} //当前结点存储的元素 - sons map[string]*node //该结点下属结点的指针 -} - -//@title newNode -//@description -// 新建一个前缀基数树节点并返回 -// 将传入的元素e作为该节点的承载元素 -//@receiver nil -//@param name string 该节点的名字,即其对应的string -//@param e interface{} 承载元素e -//@return n *node 新建的单词查找树节点的指针 -func newNode(name string, e interface{}) (n *node) { - return &node{ - name: name, - num: 0, - value: e, - sons: make(map[string]*node), - } -} - -//@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+n.name) - } - for _, son := range n.sons { - es = append(es, son.inOrder(s+n.name+"/")...) - } - return es -} - -//@title insert -//@description -// 以node前缀基数树节点做接收者 -// 从n节点中继续插入以s为索引的元素e,且当前抵达的string位置为p -// 若该层string为""时候视为失败 -// 当到达s终点时进行插入,如果此时node承载了元素则插入失败,否则成功 -// 当未到达终点时,根据当前抵达的位置去寻找其子结点继续遍历即可 -// 当插入失败且对应子结点为新建节点时则需要删除该子结点 -//@receiver n *node 接受者node的指针 -//@param ss []string 待删除元素的索引s的按'/'进行分层的索引集合 -//@param p int 索引当前抵达的位置 -//@param e interface{} 待插入元素e -//@return b bool 是否插入成功? -func (n *node) insert(ss []string, p int, e interface{}) (b bool) { - if p == len(ss) { - if n.value != nil { - return false - } - n.value = e - n.num++ - return true - } - s := ss[p] - if s == "" { - return false - } - //从其子结点的map中找到对应的方向 - son, ok := n.sons[s] - if !ok { - //不存在,新建并放入map中 - son = newNode(s, nil) - n.sons[s] = son - } - //从子结点对应方向继续插入 - b = son.insert(ss, p+1, e) - if b { - n.num++ - } else { - if !ok { - //插入失败且该子节点为新建结点则需要删除该子结点 - delete(n.sons, s) - } - } - return b -} - -//@title erase -//@description -// 以node前缀基数树节点做接收者 -// 从n节点中继续删除以s为索引的元素e,且当前抵达的string位置为p -// 若该层string为""时候视为失败 -// 当到达s终点时进行删除,如果此时node未承载元素则删除失败,否则成功 -// 当未到达终点时,根据当前抵达的位置去寻找其子结点继续遍历即可,若其分叉为nil则直接失败 -//@receiver n *node 接受者node的指针 -//@param ss []string 待删除元素的索引s的按'/'进行分层的索引集合 -//@param p int 索引当前抵达的位置 -//@return b bool 是否删除成功? -func (n *node) erase(ss []string, p int) (b bool) { - if p == len(ss) { - if n.value != nil { - n.value = nil - n.num-- - return true - } - return false - } - //从map中找到对应下子结点位置并递归进行删除 - s := ss[p] - son, ok := n.sons[s] - if !ok || son == nil { - //未找到或son不存在,删除失败 - return false - } - b = son.erase(ss, p+1) - if b { - n.num-- - if son.num <= 0 { - //删除后子结点的num<=0即该节点无后续存储元素,可以销毁 - delete(n.sons, s) - } - } - return b -} - -//@title delete -//@description -// 以node前缀基数树节点做接收者 -// 从n节点中继续删除以s为索引的元素e,且当前抵达的string位置为p -// 若该层string为""时候视为失败 -// 当到达s终点时进行删除,删除所有后续元素,并返回其后续元素的数量 -// 当未到达终点时,根据当前抵达的位置去寻找其子结点继续遍历即可,若其分叉为nil则直接返回0 -//@receiver n *node 接受者node的指针 -//@param ss []string 待删除元素的索引s的按'/'进行分层的索引集合 -//@param p int 索引当前抵达的位置 -//@return num int 被删除元素的数量 -func (n *node) delete(ss []string, p int) (num int) { - if p == len(ss) { - return n.num - } - //从map中找到对应下子结点位置并递归进行删除 - s := ss[p] - son, ok := n.sons[s] - if !ok || son == nil { - return 0 - } - num = son.delete(ss, p+1) - if num > 0 { - n.num -= num - if son.num <= 0 { - //删除后子结点的num<=0即该节点无后续存储元素,可以销毁 - delete(n.sons, s) - } - } - return num -} - -//@title count -//@description -// 以node前缀基数树节点做接收者 -// 从n节点中继续查找以s为前缀索引的元素e,且当前抵达的string位置为p -// 若该层string为""时候视为查找失败 -// 当到达s终点时返回其值即可 -// 当未到达终点时,根据当前抵达的位置去寻找其子结点继续遍历即可,当其分叉为nil则直接返回0 -//@receiver n *node 接受者node的指针 -//@param ss []string 待删除元素的索引s的按'/'进行分层的索引集合 -//@param p int 索引当前抵达的位置 -//@return num int 以该s为前缀的string的数量 -func (n *node) count(ss []string, p int) (num int) { - if p == len(ss) { - return n.num - } - //从map中找到对应下子结点位置并递归进行查找 - s := ss[p] - son, ok := n.sons[s] - if !ok || son == nil { - return 0 - } - return son.count(ss, p+1) -} - -//@title find -//@description -// 以node前缀基数树节点做接收者 -// 从n节点中继续查找以s为前缀索引的元素e,且当前抵达的string位置为p -// 若该层string为""时候视为查找失败 -// 当到达s终点时返回其承载的元素即可 -// 当未到达终点时,根据当前抵达的位置去寻找其子结点继续遍历即可,当其分叉为nil则直接返回nil -//@receiver n *node 接受者node的指针 -//@param ss []string 待删除元素的索引s的按'/'进行分层的索引集合 -//@param p int 索引当前抵达的位置 -//@return e interface{} 该索引所指向的元素e -func (n *node) find(ss []string, p int) (e interface{}) { - if p == len(ss) { - return n.value - } - //从map中找到对应下子结点位置并递归进行查找 - s := ss[p] - son, ok := n.sons[s] - if !ok || son == nil { - return 0 - } - return son.find(ss, p+1) -} diff --git a/goSTL/data_structure/rax/rax.go b/goSTL/data_structure/rax/rax.go deleted file mode 100644 index 5dc8250..0000000 --- a/goSTL/data_structure/rax/rax.go +++ /dev/null @@ -1,303 +0,0 @@ -package rax - -//@Title rax -//@Description -// 前缀基数树-Rax -// 以多叉树的形式实现,根据'/'进行string分割,将分割后的string数组进行段存储 -// 插入的string首字符必须为'/' -// 任意一段string不能为"" -// 结点不允许覆盖,即插入值已经存在时会插入失败,需要先删除原值 -// 使用互斥锁实现并发控制 - -import ( - "github.com/hlccd/goSTL/utils/iterator" - "strings" - "sync" -) - -//rax前缀基数树结构体 -//该实例存储前缀基数树的根节点 -//同时保存该树已经存储了多少个元素 -//整个树不允许重复插入,若出现重复插入则直接失败 -type rax struct { - root *node //前缀基数树的根节点指针 - size int //当前已存放的元素数量 - mutex sync.Mutex //并发控制锁 -} - -//rax前缀基数树容器接口 -//存放了rax前缀基数树可使用的函数 -//对应函数介绍见下方 -type raxer interface { - Iterator() (i *Iterator.Iterator) //返回包含该rax的所有string - Size() (num int) //返回该rax中保存的元素个数 - Clear() //清空该rax - Empty() (b bool) //判断该rax是否为空 - Insert(s string, e interface{}) (b bool) //向rax中插入string并携带元素e - Erase(s string) (b bool) //从rax中删除以s为索引的元素e - Delete(s string) (num int) //从rax中删除以s为前缀的所有元素 - Count(s string) (num int) //从rax中寻找以s为前缀的string单词数 - Find(s string) (e interface{}) //从rax中寻找以s为索引的元素e -} - -//@title New -//@description -// 新建一个rax前缀基数树容器并返回 -// 初始根节点为nil -//@receiver nil -//@param nil -//@return r *rax 新建的rax指针 -func New() (r *rax) { - return &rax{ - root: newNode("", nil), - size: 0, - mutex: sync.Mutex{}, - } -} - -//@title Iterator -//@description -// 以rax前缀基数树做接收者 -// 将该rax中所有存放的string放入迭代器中并返回 -//@receiver r *rax 接受者rax的指针 -//@param nil -//@return i *iterator.Iterator 新建的Iterator迭代器指针 -func (r *rax) 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 -// 以rax前缀基数树做接收者 -// 返回该容器当前含有元素的数量 -// 如果容器为nil返回0 -//@receiver r *rax 接受者rax的指针 -//@param nil -//@return num int 容器中实际使用元素所占空间大小 -func (r *rax) Size() (num int) { - if r == nil { - return 0 - } - if r.root == nil { - return 0 - } - return r.size -} - -//@title Clear -//@description -// 以rax前缀基数树做接收者 -// 将该容器中所承载的元素清空 -// 将该容器的size置0 -//@receiver r *rax 接受者rax的指针 -//@param nil -//@return nil -func (r *rax) Clear() { - if r == nil { - return - } - r.mutex.Lock() - r.root = newNode("", nil) - r.size = 0 - r.mutex.Unlock() -} - -//@title Empty -//@description -// 以rax前缀基数树做接收者 -// 判断该rax是否含有元素 -// 如果含有元素则不为空,返回false -// 如果不含有元素则说明为空,返回true -// 如果容器不存在,返回true -//@receiver r *rax 接受者rax的指针 -//@param nil -//@return b bool 该容器是空的吗? -func (r *rax) Empty() (b bool) { - if r == nil { - return true - } - return r.size == 0 -} - -//@title Insert -//@description -// 以rax前缀基数树做接收者 -// 向rax插入以string类型的s为索引的元素e -// 插入的string的首字符必须为'/',且中间按'/'分割的string不能为"" -// 若存在重复的s则插入失败,不允许覆盖 -// 否则插入成功 -//@receiver r *rax 接受者rax的指针 -//@param s string 待插入元素的索引s -//@param e interface{} 待插入元素e -//@return b bool 添加成功? -func (r *rax) Insert(s string, e interface{}) (b bool) { - if r == nil { - return false - } - if len(s) == 0 { - return false - } - if s[0] != '/' { - return false - } - //将s按'/'进行分割,并去掉第一个即去掉"",随后一次按照分层结果进行插入 - ss := strings.Split(s, "/")[1:] - r.mutex.Lock() - if r.root == nil { - //避免根节点为nil - r.root = newNode("", nil) - } - //从根节点开始插入 - b = r.root.insert(ss, 0, e) - if b { - //插入成功,size+1 - r.size++ - } - r.mutex.Unlock() - return b -} - -//@title Erase -//@description -// 以rax前缀基数树做接收者 -// 从rax树中删除元素以s为索引的元素e -// 用以删除的string索引的首字符必须为'/' -//@receiver r *rax 接受者rax的指针 -//@param s string 待删除元素的索引 -//@return b bool 删除成功? -func (r *rax) Erase(s string) (b bool) { - if r.Empty() { - return false - } - if len(s) == 0 { - return false - } - if s[0] != '/' { - return false - } - //将s按'/'进行分割,并去掉第一个即去掉"",随后一次按照分层结果进行删除 - ss := strings.Split(s, "/")[1:] - if r.root == nil { - //根节点为nil即无法删除 - return false - } - 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 -// 以rax前缀基数树做接收者 -// 从rax树中删除以s为前缀的所有元素 -// 用以删除的string索引的首字符必须为'/' -//@receiver r *rax 接受者rax的指针 -//@param s string 待删除元素的前缀 -//@return num int 被删除的元素的数量 -func (r *rax) Delete(s string) (num int) { - if r.Empty() { - return 0 - } - if len(s) == 0 { - return 0 - } - if s[0] != '/' { - return 0 - } - if r.root == nil { - return 0 - } - //将s按'/'进行分割,并去掉第一个即去掉"",随后一次按照分层结果进行删除 - ss := strings.Split(s, "/")[1:] - 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 -// 以rax前缀基数树做接收者 -// 从rax中查找以s为前缀的所有string的个数 -// 用以查找的string索引的首字符必须为'/' -// 如果存在以s为前缀的则返回大于0的值即其数量 -// 如果未找到则返回0 -//@receiver r *rax 接受者rax的指针 -//@param s string 待查找的前缀s -//@return num int 待查找前缀在rax树中存在的数量 -func (r *rax) Count(s string) (num int) { - if r.Empty() { - return 0 - } - if r.root == nil { - return 0 - } - if len(s) == 0 { - return 0 - } - if s[0] != '/' { - return 0 - } - //将s按'/'进行分割,并去掉第一个即去掉"",随后一次按照分层结果进行查找 - ss := strings.Split(s, "/")[1:] - r.mutex.Lock() - num = r.root.count(ss, 0) - r.mutex.Unlock() - return num -} - -//@title Find -//@description -// 以rax前缀基数树做接收者 -// 从rax中查找以s为索引的元素e,找到则返回e -// 用以查找的string索引的首字符必须为'/' -// 如果未找到则返回nil -//@receiver r *rax 接受者rax的指针 -//@param s string 待查找索引s -//@return ans interface{} 待查找索引所指向的元素 -func (r *rax) Find(s string) (e interface{}) { - if r.Empty() { - return nil - } - if len(s) == 0 { - return nil - } - if s[0] != '/' { - return nil - } - if r.root == nil { - return nil - } - //将s按'/'进行分割,并去掉第一个即去掉"",随后一次按照分层结果进行查找 - ss := strings.Split(s, "/")[1:] - r.mutex.Lock() - e = r.root.find(ss, 0) - r.mutex.Unlock() - return e -}