在计算机科学中,基数树(Radix Tree),也被称为压缩前缀树(Compact Prefix Tree)或Patricia Trie,是一种用于高效存储和检索字符串键值对的数据结构。它在路由表、IP地址查找、自动补全系统等场景中被广泛应用。
本文将带你从零开始,使用 Go语言 实现一个简单的基数树,并解释其核心原理。即使你是编程新手,也能轻松理解!
普通的 Trie 树(字典树)每个节点只存储一个字符,这会导致大量中间节点,浪费内存。而 基数树 通过合并单子节点路径,将多个字符压缩到一个节点中,从而减少节点数量,提升空间效率。
我们先定义基数树的节点结构:
type RadixNode struct { key string value interface{} children []*RadixNode isLeaf bool} 每个节点包含:
key:当前节点存储的字符串片段(不再是单个字符)value:可选的值(用于键值对存储)children:子节点列表isLeaf:是否为叶子节点(即是否代表一个完整键)插入是基数树最复杂的部分,需要处理以下几种情况:
下面是 Go 语言的插入实现:
func (node *RadixNode) Insert(key string, value interface{}) { // 找到最长公共前缀 i := 0 for i < len(key) && i < len(node.key) && key[i] == node.key[i] { i++ } // 情况1:完全匹配 if i == len(key) && i == len(node.key) { node.value = value node.isLeaf = true return } // 情况2:当前节点 key 是新 key 的前缀 if i == len(node.key) { // 在子节点中继续插入剩余部分 suffix := key[i:] for _, child := range node.children { if child.key[0] == suffix[0] { child.Insert(suffix, value) return } } // 没有匹配子节点,新建一个 newNode := &RadixNode{ key: suffix, value: value, isLeaf: true, } node.children = append(node.children, newNode) return } // 情况3:需要拆分当前节点 commonPrefix := node.key[:i] splitNode := &RadixNode{ key: commonPrefix, children: []*RadixNode{node}, } // 更新原节点的 key 为剩余部分 node.key = node.key[i:] // 创建新节点存放新 key 的剩余部分 if i < len(key) { newNode := &RadixNode{ key: key[i:], value: value, isLeaf: true, } splitNode.children = append(splitNode.children, newNode) } else { // 新 key 正好是公共前缀 splitNode.value = value splitNode.isLeaf = true } // 将 splitNode 的信息复制回原 node *node = *splitNode} 查找相对简单,只需沿着匹配路径向下遍历:
func (node *RadixNode) Get(key string) (interface{}, bool) { if len(key) == 0 { return nil, false } // 检查当前节点是否匹配前缀 if len(key) < len(node.key) || key[:len(node.key)] != node.key { return nil, false } // 完全匹配当前节点 if len(key) == len(node.key) { if node.isLeaf { return node.value, true } return nil, false } // 继续在子节点中查找 suffix := key[len(node.key):] for _, child := range node.children { if len(suffix) > 0 && suffix[0] == child.key[0] { return child.Get(suffix) } } return nil, false} 创建根节点并插入几个键值对:
func main() { root := &RadixNode{key: "", isLeaf: false} root.Insert("hello", 1) root.Insert("he", 2) root.Insert("help", 3) root.Insert("world", 4) if val, ok := root.Get("he"); ok { fmt.Println("Found:", val) // 输出: Found: 2 } if val, ok := root.Get("help"); ok { fmt.Println("Found:", val) // 输出: Found: 3 }} 通过本教程,你已经掌握了 Go语言 中 基数树(Radix Tree)的基本实现。这种 数据结构 在需要高效前缀匹配的场景中非常有用,比如网络路由、搜索引擎建议、缓存系统等。
虽然我们实现的是简化版,但核心思想已经涵盖。你可以在此基础上添加删除、遍历、前缀搜索等功能,进一步完善你的 Radix Tree。
记住:理解数据结构的本质,比死记代码更重要!
本文由主机测评网于2025-12-09发表在主机测评网_免费VPS_免费云服务器_免费独立服务器,如有疑问,请联系我们。
本文链接:https://www.vpshk.cn/2025125276.html