Trie

当我们在做key-value存储时,最简单的就是 map[string]string, 假如有两个键值对('child', 'value1'), ('children', 'value2'),毫无疑问,value1与value2是一定要存的,不过 'child'与‘children'不一定都要存下来,只存'children'也不是不可以,这样就少存一个'child',省点空间,不过我们要在字符‘d' 和 'n'处做上记号。

code

package trie

type Trie[T any] struct {
	isEnd    bool  // 只有当isEnd为true时,value字段才会存值
	value    T
	children map[rune]*Trie[T]
}

func New[T any]() *Trie[T] {
	return &Trie[T]{
		isEnd:    false,
		children: map[rune]*Trie[T]{},
	}
}

func (root *Trie[T]) Insert(word string, value T) {
	node := root
	for _, c := range word {
		if child, ok := node.children[c]; ok {
			node = child
		} else {
			newNode := &Trie[T]{
				children: map[rune]*Trie[T]{},
			}
			node.children[c] = newNode
			node = newNode
		}
	}

	node.isEnd = true
	node.value = value
}

func (root *Trie[T]) Search(word string) (isEnd bool, value T) {
	node := root
	for _, c := range word {
		if child, ok := node.children[c]; ok {
			node = child
			continue
		} else {
			isEnd = false
			return
		}
	}
	isEnd = node.isEnd
	value = node.value
	return
}

func (root *Trie[T]) StartWith(prefix string) bool {
	node := root
	for _, c := range prefix {
		if child, ok := node.children[c]; ok {
			node = child
			continue
		} else {
			return false
		}
	}
	return true
}

Test

package trie

import (
	"testing"

	"github.com/stretchr/testify/assert"
)

// go test -run TestTrie
func TestTrie(t *testing.T) {
	trie := New[int]()

	word1, value1 := "letter", 25

	trie.Insert(word1, value1)

	ok1, ret1 := trie.Search("lette")

	assert.Equal(t, ok1, false)
	assert.Equal(t, ret1, 0)

	ok2 := trie.StartWith("lette")
	assert.Equal(t, ok2, true)

	ok3, ret2 := trie.Search("letter")

	assert.Equal(t, ok3, true)
	assert.Equal(t, ret2, 25)

	word2, value2 := "lette", 26

	trie.Insert(word2, value2)

	ok4, ret3 := trie.Search("lette")
	assert.Equal(t, ok4, true)
	assert.Equal(t, ret3, 26)

}


SourceCode

leetcode208

type Trie struct {
    isWord bool
    children map[rune]*Trie
}


func Constructor() Trie {
    return Trie{
        isWord: false,
        children: make(map[rune]*Trie),
    }
}


func (this *Trie) Insert(word string)  {
    node := this
    for _, c := range word {
        if child, ok := node.children[c]; ok {
            node = child
        } else {
            newNode := &Trie{
                isWord: false,
                children: make(map[rune]*Trie),
            }
            node.children[c] = newNode
            node = newNode
        }
    }
    node.isWord = true
}


func (this *Trie) Search(word string) bool {
    node := this
    for _, c := range word {
        if child, ok := node.children[c]; ok {
            node = child
            continue
        }
        return false
    }
    return node.isWord
}


func (this *Trie) StartsWith(prefix string) bool {
    node := this
    for _, c := range prefix {
        if child, ok := node.children[c]; ok {
            node = child
            continue
        }
        return false
    }
    return true
}