• 前缀树的简单实现


    前言

    我们每天在用搜索引擎搜索信息,相信大家肯定有注意过这样一个细节: 当输入某个字符的时候,搜索引框底下会出现多个推荐词,如下,输入关键字后底下会出现挺多以以输入内容为前缀的推荐搜索文本。它是如何实现的呢?

    前缀树

    原理介绍参考:轻松搞懂Trie树
    Trie树是一种搜索树,也称字典树或单词查找树。此外也称前缀树,因为某节点的后代存在共同的前缀。它的key都为字符串,能做到高效查询和插入。时间复杂度为O(k),k为字符串长度。缺点是如果大量字符串没有共同前缀时很耗内存。它的核心思想就是减少没必要的字符比较,使查询高效率。即用空间换时间,再利用共同前缀来提高查询效率。

    • 根节点不包含字符,其他节点每个节点只包含一个字符。
    • 从根节点到某一节点经过路径的字符连起来即为该节点对应的字符串。
    • 每个节点的所有子节点字符都不相同。

    简单实现

    库文件: t9.go

    package t9
    
    import "fmt"
    
    type t9tree struct {
    	children []*t9tree
    	char     byte
    	desc     string
    }
    
    func NewT9() *t9tree {
    	return &t9tree{}
    }
    
    func (t *t9tree) Insert(start *t9tree, word []byte, desc string) *t9tree {
    	if len(word) == 0 {
    		return nil
    	}
    
    	if start == nil {
    		start = t
    	}
    
    	for _, node := range start.children {
    		if node.char == word[0] {
    			return t.Insert(node, word[1:], desc)
    		}
    	}
    
    	node := &t9tree{
    		char:     word[0],
    		children: nil,
    		desc:     "",
    	}
    
    	start.children = append(start.children, node)
    	if len(word) == 1 {
    		node.desc = desc
    		return node
    	}
    	return t.Insert(node, word[1:], desc)
    }
    
    func (t *t9tree) Walk() {
    	var _walk func(*t9tree)
    	var word []byte
    
    	if t.children == nil {
    		return
    	}
    
    	_walk = func(t *t9tree) {
    		if t == nil {
    			return
    		}
    
    		for _, node := range t.children {
    			word = append(word, node.char)
    			if len(node.children) == 0 {
    				// fmt.Println(string(node.char))
    				line := make([]byte, 0)
    				line = append(line, word...)
    				for len(line) < 25 {
    					line = append(line, ' ')
    				}
    				line = append(line, []byte("--- ")...)
    				line = append(line, []byte(node.desc)...)
    				fmt.Println(string(line))
    			}
    			_walk(node)
    		}
    
    		if (len(word)) > 0 {
    			word = word[:len(word)-1]
    		}
    	}
    
    	_walk(t)
    }
    

    主文件:demo.go

    package main
    
    import (
    	"demo/t9"
    	"fmt"
    )
    
    func main() {
    	t := t9.NewT9()
    
    	t.Insert(nil, []byte("dictionary"), "字典")
    	t.Insert(nil, []byte("translation"), "翻译")
    	t.Insert(nil, []byte("input"), "输入")
    	t.Insert(nil, []byte("output"), "输出")
    	t.Insert(nil, []byte("cpu"), "中央处理器")
    
    	t.Walk()
    }
    

    运行日志:

  • 相关阅读:
    Nodejs学习笔记(三)--- 模块
    Nodejs学习笔记(二)--- 事件模块
    Nodejs学习笔记(一)--- 简介及安装Node.js开发环境
    leetcode题解实践
    坑爹的bugsbunnyctf复现
    两道interesting的题目
    python 习题集
    数据结构与算法--java描述
    pentestbox下运行ssh报错,命令报错
    ntfs交换数据流在隐写
  • 原文地址:https://www.cnblogs.com/sinpo828/p/14143171.html
Copyright © 2020-2023  润新知