package trie //@Title trie //@Description // 单词查找树的节点 // 可通过节点的分叉对string进行查找 // 增添string时候只需要增删结点即可 // 当string到终点时存储元素 //node树节点结构体 //该节点是trie的树节点 //结点存储到此时的string的前缀数量 //以son为分叉存储下属的string //该节点同时存储其元素 type node struct { num int //以当前结点为前缀的string的数量 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 } ok := true if n.son[idx] == nil { //判断该子结点是否存在 n.son[idx] = newNode(nil) ok = false } b = n.son[idx].insert(s, p+1, e) if b { n.num++ } else { if !ok { //插入失败且该子节点为新建结点则需要删除该子结点 n.son[idx] = nil } } 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 delete //@description // 以node单词查找树节点做接收者 // 从n节点中继续删除以s为索引的元素e,且当前抵达的string位置为p // 当到达s终点时进行删除,删除所有后续元素,并返回其后续元素的数量 // 当未到达终点时,根据当前抵达的位置去寻找其子结点继续遍历即可,若其分叉为nil则直接返回0 //@receiver n *node 接受者node的指针 //@param s string 待删除元素的索引s //@param p int 索引当前抵达的位置 //@return num int 被删除元素的数量 func (n *node) delete(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 } num = n.son[idx].delete(s, p+1) if num > 0 { n.num -= num if n.son[idx].num <= 0 { n.son[idx] = nil } } return num } //@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) }