搜索项目关键问题总结及trie树 | 青训营笔记

134 阅读2分钟

这是我参与「第三届青训营 -后端场」笔记创作活动的第5篇笔记。

后端关键问题

  1. 支持用户自定义关键词过滤

  2. 支持"相关搜索"功能,自动给出可能的关联条目(字典树)

  3. 实现关联度算法,能够把关联度高的信息优先展示

  4. 支持搜索图片

    • 用户输入纯文本,根据纯文本搜索出关联的图片数据。
  • 图片搜索结果以略缩图展示,支持点击打开原图
  1. 支持以图搜图

    • 用户上传一张图片,系统能理解图片内容,然后搜索出关联的图片

前缀树用于支持"相关搜索"功能,自动给出可能的关联条目和实现关联度算法。

package main

import (
	"fmt"
)

//数据节点;存储数据:数据值、是否结束标志位、下一个节点指针
type TNode struct {
	Data   byte
	IsWord bool
	Next   map[byte]*TNode
}

//根节点,存储数据为:1、字符串个数;2、数据节点map序列
type TNRoot struct {
	Len  int
	Node map[byte]*TNode
}

func CreateTire() TNRoot {
	tn := make(map[byte]*TNode)
	//创建节点的时候,需要将node赋值
	tRoot := TNRoot{
		Len:  0,
		Node: tn, //todo 技巧:需要赋值,不然后续没有办法操作
	}
	return tRoot
}
func (tn *TNRoot) insert(str string) {
	cur := tn.Node
	for i := 0; i < len(str); i++ {
		if cur[str[i]] == nil {
			newNode := &TNode{
				Data:   str[i],
				IsWord: false,
				Next:   make(map[byte]*TNode), //TODO 技巧:下一个节点需要实例化,不然是空,后续无法操作。
			}
			cur[str[i]] = newNode
		}
		if i == len(str)-1 {
			cur[str[i]].IsWord = true
		}
		cur = cur[str[i]].Next
	}
	tn.Len++

}
func (tn *TNRoot) isExist(str string) bool {
	if tn.Node == nil {
		return false
	}
	cur := tn.Node
	var res []byte
	for i := 0; i < len(str); i++ {
		if cur[str[i]] == nil { //如果比较的数据不存在,直接返回
			return false
		}
		res = append(res, cur[str[i]].Data)
		fmt.Println("res", string(res))
		// fmt.Println("11", cur[str[i]].Next)
		mp := cur[str[i]].Next

		for k, v := range mp {
			fmt.Println(k, v.Data)
		}
		fmt.Println("--", cur[str[i]].Data, str[i])
		if cur[str[i]].Data != str[i] {
			return false
		}
		if i == len(str)-1 { //判断最后一个比较的字符是否是结束标志位
			if cur[str[i]].IsWord == true {
				return true
			}
		}
		cur = cur[str[i]].Next
	}
	return false
}
func (tn *TNRoot) search(str string) []string {
	heights := make([]string, 20)
	if tn.Node == nil {
		return heights
	}
	cur := tn.Node
	var res []byte
	j := 0
	for i := 0; i < len(str); i++ {
		if cur[str[i]] == nil { //如果比较的数据不存在,直接返回
			return heights
		}
		// res = append(res, cur[str[i]].Data)
		res = append(res, cur[str[i]].Data)
		if cur[str[i]].Data != str[i] {
			return heights
		}
		if i == len(str)-1 { //判断最后一个比较的字符是否是结束标志位
			if cur[str[i]].IsWord == true {
				heights[j] = string(res)
				j++
			}
			cur = cur[str[i]].Next
			break
		}
		cur = cur[str[i]].Next
	}
	mp := cur
	stk := make([]byte, 2000)
	tt := 0
	for k, v := range mp {
		tt += 1
		stk[tt] = v.Data
		fmt.Println(k, v.Data)
	}
	// for {
	// 	if tt <= 0 {
	// 		break
	// 	}
	// }
	return heights
}
func main() {
	// heights := make([]string, 20)
	// heights[0] = "222"
	// fmt.Println("11", heights)
	tire := CreateTire()
	tire.insert("中文")
	tire.insert("中文期刊")
	tire.insert("中文胡刊")
	tire.insert("中国")
	// fmt.Println(tire.search("中"))
	tire.insert("hello")
	tire.insert("hel")
	// fmt.Println(tire.isExist("中文"))
	fmt.Println(tire.search("中文"))
	// fmt.Println(tire.isExist("中国"))
	// fmt.Println(tire.isExist("hel"))
	// fmt.Println(tire.isExist("hell"))
	// fmt.Println(tire.isExist("hello"))
	// fmt.Println("tire树的字符串数量:", tire.Len)
}