zoukankan      html  css  js  c++  java
  • 前缀树的简单实现

    前言

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

    前缀树

    原理介绍参考:轻松搞懂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()
    }
    

    运行日志:

  • 相关阅读:
    js的基本数据类型有哪些?
    页面优化的方式有哪些?
    为什么要用rem
    sass开发过程中遇到的几个坑
    js事件监听
    js数组去重的方法
    什么是怪异盒模型
    Cookie SameSite属性介绍及其在ASP.NET项目中的应用
    HttpServlet在第一个Servlet程序中的知识点
    Myeclipse 2017 创建第一个servlet步骤
  • 原文地址:https://www.cnblogs.com/sinpo828/p/14143171.html
Copyright © 2011-2022 走看看