Trie-字典树

Trie-字典树/前缀树

最近在看Gin 的源码。Gin的高性能依靠前缀树,每一个分支代表一个路由而树的节点中则可以存放该路由的执行中间件以及handle控制器。

前言

在这里插入图片描述

字典树,是一种树形结构。主要思想是利用字符串的公共前缀来节约存储空间。

抽象应用场景

利用几个基本单元的按顺序排列组合来表示更多的单元。例如单词的表示,网站的网址……

字典树优点

  • 节约空间:例如我们用字典树去存储英语单词,我们不需要针对每个单词而重复地存储组成他们的字母。
  • 快速检索: 要从字典树中检索某个单词时,我们只需要按照单词的顺序依次检索,而每个节点的子节点用Map进行存储。因此,用单词树进行检索的效率很高。

Go实现字典树

package main

import "fmt"

// 单词树节点的结构体
type trieNode struct {
	isWord bool
	next   map[rune]*trieNode
}

// 单词树的结构体
type trie struct {
	size int
	root *trieNode
}

// 初始化一颗单词树
func InitTrie() *trie {
	return &trie{
		0,
		&trieNode{
			false, make(map[rune]*trieNode),
		},
	}
}

// 获得单词树的size
func (t *trie) GetSize() int { return t.size }

// 向单词树中添加单词
// 若成功添加则树的深度 + 1
func (t *trie) Add(word string) {
	if len(word) == 0 {
		return
	}
	cur := t.root
	t.size = t.size + cur.insert(word)
}

// 递归的像树中插入单词
func (node *trieNode) insert(word string) int {
	_, ok := node.next[rune(word[0])]
	if !ok {
		node.next[rune(word[0])] = &trieNode{
			false,
			map[rune]*trieNode{},
		}
	}
	node = node.next[rune(word[0])]

	if len(word) == 1 {
		if !node.isWord {
			node.isWord = true
			return 1
		}
		return 0
	}
	return node.insert(word[1:])
}

// 输出一个节点的下的单词
func (node *trieNode) show(prex string) {
	if node.isWord {
		fmt.Printf("%s\n", prex)
	}
	for k, _ := range node.next {
		node.next[k].show(prex + string(k))
	}
}

// 是否包含这个路径
func (t *trie) ContainsWordPath(word string) (bool, *trieNode) {
	if len(word) == 0 {
		return false, nil
	}
	cur := t.root
	for _, v := range word {
		t1, ok := cur.next[v]
		if !ok {
			return false, nil
		}
		cur = t1
	}
	return true, cur
}

// 单词树是否包含某个单词
func (t *trie) Contains(word string) bool {
	containsPath, cur := t.ContainsWordPath(word)
	return containsPath && cur.isWord
}

// 是否包含该前缀的单词
func (t *trie) IsPrefix(word string) bool {
	containsPath, _ := t.ContainsWordPath(word)
	return containsPath
}

// 输出单词树中的所有单词
func (t *trie) Show() {
	if t.size == 0 {
		return
	}
	t.root.show("")
}

func test() {
	tree := InitTrie()
	tree.Add("ywhtest")
	tree.Add("ywab")
	tree.Add("asdsa")
	tree.Show()
}

func main() {
	test()
}

output

ywhtest
ywab
asdsa

在这个案例中我们使用字典树存储单词,并将字典树中的单词按行进行输出。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值