go:实现前缀树
- 2019 年 11 月 22 日
- 筆記
url路由的副产品。
package utils /* PrefixTree 前缀树 使用姿势: tree := utils.BuildTree([]string{ "/yuedu/account", "/yuedu", "/yuedu/master", }) fmt.Println(tree.Match("/yuedu")) fmt.Println(tree.Match("/yuedu/details")) fmt.Println(tree.Match("/yuedu/account")) fmt.Println(tree.Match("/yuedu/account/user")) fmt.Println(tree.Match("/yuedu/master/")) result: /yuedu true /yuedu false /yuedu/account true /yuedu/account false /yuedu/master false */ type PrefixTree struct { root *treeNode } // BuildTree 生成这棵前缀树 func BuildTree(keys []string) *PrefixTree { tree := new(PrefixTree) root := makeNode() for _, key := range keys { buildNode(key, root) } tree.root = root return tree } // Match 尝试匹配一个Path,返回最终匹配的结果和是否完全匹配 func (t PrefixTree) Match(path string) (string, bool) { tpnode := t.root result := "" for _, pathpart := range path { _, ok := tpnode.subNode[pathpart] if !ok { return result, false } tpnode = tpnode.subNode[pathpart] if tpnode.value != "" { result = tpnode.value } } return result, tpnode.value != "" } type treeNode struct { subNode map[rune]*treeNode value string } func makeNode() *treeNode { node := new(treeNode) node.subNode = make(map[rune]*treeNode) return node } func buildNode(key string, root *treeNode) { tpnode := root for _, keypart := range key { _, ok := tpnode.subNode[keypart] if ok { tpnode = tpnode.subNode[keypart] } else { tpnode.subNode[keypart] = makeNode() tpnode = tpnode.subNode[keypart] } } tpnode.value = key }