前缀树 完成基本功能, 准备添加一个高度属性达到长度检索的目的
This commit is contained in:
parent
edecf0453e
commit
b92f270429
@ -62,26 +62,20 @@ func (tried *Tried) Put(words string, values ...interface{}) {
|
|||||||
cur = n
|
cur = n
|
||||||
}
|
}
|
||||||
|
|
||||||
vlen := len(values)
|
if values != nil {
|
||||||
switch vlen {
|
|
||||||
case 0:
|
|
||||||
cur.value = tried
|
|
||||||
case 1:
|
|
||||||
cur.value = values[0]
|
cur.value = values[0]
|
||||||
case 2:
|
} else {
|
||||||
// TODO: 执行函数 values[1] 为函数类型 func (cur *Node, value interface{}) ...可以插入, 也可以不插入
|
cur.value = tried
|
||||||
default:
|
|
||||||
panic("unknow select to do")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tried *Tried) Get(words string) interface{} {
|
func (tried *Tried) Get(words string) interface{} {
|
||||||
cur := tried.root
|
cur := tried.root
|
||||||
var n *Node
|
var n *Node
|
||||||
|
bytes := []byte(words)
|
||||||
|
|
||||||
for i := 0; i < len(words); i++ {
|
for i := 0; i < len(bytes); i++ {
|
||||||
w := tried.wiStore.Byte2Index(words[i]) //TODO: 升级Index 函数
|
w := tried.wiStore.Byte2Index(bytes[i]) //TODO: 升级Index 函数
|
||||||
if n = cur.data[w]; n == nil {
|
if n = cur.data[w]; n == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -95,7 +89,61 @@ func (tried *Tried) Has(words string) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (tried *Tried) HasPrefix(words string) bool {
|
func (tried *Tried) HasPrefix(words string) bool {
|
||||||
return tried.Get(words) != nil
|
cur := tried.root
|
||||||
|
var n *Node
|
||||||
|
bytes := []byte(words)
|
||||||
|
|
||||||
|
for i := 0; i < len(bytes); i++ {
|
||||||
|
w := tried.wiStore.Byte2Index(bytes[i]) //TODO: 升级Index 函数
|
||||||
|
if n = cur.data[w]; n == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
cur = n
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tried *Tried) PrefixWords(words string) []string {
|
||||||
|
cur := tried.root
|
||||||
|
var n *Node
|
||||||
|
bytes := []byte(words)
|
||||||
|
|
||||||
|
var header []byte
|
||||||
|
for i := 0; i < len(bytes); i++ {
|
||||||
|
curbyte := bytes[i]
|
||||||
|
header = append(header, curbyte)
|
||||||
|
w := tried.wiStore.Byte2Index(curbyte)
|
||||||
|
if n = cur.data[w]; n == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
cur = n
|
||||||
|
}
|
||||||
|
|
||||||
|
var result []string
|
||||||
|
|
||||||
|
var traversal func([]byte, *Node)
|
||||||
|
traversal = func(prefix []byte, cur *Node) {
|
||||||
|
|
||||||
|
for i, n := range cur.data {
|
||||||
|
if n != nil {
|
||||||
|
nextPrefix := append(prefix, tried.wiStore.Index2Byte(uint(i)))
|
||||||
|
traversal(nextPrefix, n)
|
||||||
|
if n.value != nil {
|
||||||
|
result = append(result, string(append(header, nextPrefix...)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
// 拼接头
|
||||||
|
if n != nil {
|
||||||
|
if n.value != nil {
|
||||||
|
result = append(result, string(header))
|
||||||
|
}
|
||||||
|
traversal([]byte{}, n)
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tried *Tried) Traversal(every func(cidx uint, value interface{}) bool) {
|
func (tried *Tried) Traversal(every func(cidx uint, value interface{}) bool) {
|
||||||
|
@ -12,6 +12,127 @@ import (
|
|||||||
"github.com/Pallinder/go-randomdata"
|
"github.com/Pallinder/go-randomdata"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func CompareSliceWithSorted(source, words []string) (bool, string) {
|
||||||
|
sort.Slice(words, func(i, j int) bool {
|
||||||
|
if words[i] < words[j] {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
|
||||||
|
// source := tried.WordsArray()
|
||||||
|
sort.Slice(source, func(i, j int) bool {
|
||||||
|
if source[i] < source[j] {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
result1 := spew.Sprint(source)
|
||||||
|
result2 := spew.Sprint(words)
|
||||||
|
|
||||||
|
if result1 != result2 {
|
||||||
|
return false, spew.Sprint(result1, " != ", result2)
|
||||||
|
}
|
||||||
|
return true, ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTried_Has(t *testing.T) {
|
||||||
|
var tried *Tried
|
||||||
|
tried = NewWithWordType(WordIndexLower)
|
||||||
|
tried.Put("ads")
|
||||||
|
tried.Put("zadads")
|
||||||
|
tried.Put("asdgdf")
|
||||||
|
if !tried.Has("ads") {
|
||||||
|
t.Error("ads is exist, but not has")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !tried.HasPrefix("ad") {
|
||||||
|
t.Error("ads is exist, but not HasPrefix")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !tried.HasPrefix("za") {
|
||||||
|
t.Error("ads is exist, but not HasPrefix")
|
||||||
|
}
|
||||||
|
|
||||||
|
if tried.HasPrefix("fsdf") {
|
||||||
|
t.Error("fsdf is not exist, but HasPrefix")
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(tried.String()) < 10 {
|
||||||
|
t.Error(tried.WordsArray())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func TestTried_PrefixWords(t *testing.T) {
|
||||||
|
|
||||||
|
var tried *Tried
|
||||||
|
var wordsCollection []string
|
||||||
|
var input []string
|
||||||
|
|
||||||
|
var wordsList [][]string
|
||||||
|
var inputParams [][]string
|
||||||
|
var triedList []*Tried
|
||||||
|
|
||||||
|
triedList = append(triedList, NewWithWordType(WordIndexLower))
|
||||||
|
inputParams = append(inputParams, []string{"ad", "adf"})
|
||||||
|
wordsList = append(wordsList, []string{"ad", "adfsxzcdas", "adfadsasd"})
|
||||||
|
|
||||||
|
triedList = append(triedList, NewWithWordType(WordIndexUpper))
|
||||||
|
inputParams = append(inputParams, []string{"AD", "ADF"})
|
||||||
|
wordsList = append(wordsList, []string{"AD", "ADFSXZCDAS", "ADFADSASD"})
|
||||||
|
|
||||||
|
triedList = append(triedList, NewWithWordType(WordIndexUpperLower))
|
||||||
|
inputParams = append(inputParams, []string{"aD", "aDf"})
|
||||||
|
wordsList = append(wordsList, []string{"aDF", "aDfsxzcdas", "aDfadsasd"})
|
||||||
|
|
||||||
|
triedList = append(triedList, NewWithWordType(WordIndexUpperDigital))
|
||||||
|
inputParams = append(inputParams, []string{"A09D", "A09DF"})
|
||||||
|
wordsList = append(wordsList, []string{"A09D", "A09DFSXZCD312AS", "A09DFA32DSASD"})
|
||||||
|
|
||||||
|
triedList = append(triedList, NewWithWordType(WordIndexLowerDigital))
|
||||||
|
inputParams = append(inputParams, []string{"a09d", "a09df"})
|
||||||
|
wordsList = append(wordsList, []string{"a09d", "a09dfsxzcd312as", "a09dfa32dsasd"})
|
||||||
|
|
||||||
|
triedList = append(triedList, NewWithWordType(WordIndexUpperLowerDigital))
|
||||||
|
inputParams = append(inputParams, []string{"A09d", "A09dZ"})
|
||||||
|
wordsList = append(wordsList, []string{"A09d", "A09dZsxzcd312as", "A09dZa32dsasd"})
|
||||||
|
|
||||||
|
triedList = append(triedList, NewWithWordType(WordIndex256))
|
||||||
|
inputParams = append(inputParams, []string{"阿萨德", "阿萨德!"})
|
||||||
|
wordsList = append(wordsList, []string{"阿萨德", "阿萨德!@$*#))(#*", "阿萨德!╜╝╞╟╠╡╢╣╤╥╦╧╨╩╪╫╬╭╮╯╰╱╲╳▁▂▃▄▅▆▇█ ▉ ▊▋▌▍▎▏"})
|
||||||
|
|
||||||
|
triedList = append(triedList, NewWithWordType(WordIndex32to126))
|
||||||
|
inputParams = append(inputParams, []string{" `", " `<"})
|
||||||
|
wordsList = append(wordsList, []string{" `21`3tcdbxcfhyop8901zc[]\\'/?()#$%^&**! ", " `<AZaz09~ dys!@#$)(*^$#", " `<>.,?/"})
|
||||||
|
|
||||||
|
for i := 0; i < len(triedList); i++ {
|
||||||
|
tried = triedList[i]
|
||||||
|
input = inputParams[i]
|
||||||
|
wordsCollection = wordsList[i]
|
||||||
|
for _, words := range wordsCollection {
|
||||||
|
tried.Put(words)
|
||||||
|
}
|
||||||
|
var prefixWords []string
|
||||||
|
prefixWords = tried.PrefixWords(input[0])
|
||||||
|
if ok, errorResult := CompareSliceWithSorted(prefixWords, wordsCollection); !ok {
|
||||||
|
t.Error(errorResult)
|
||||||
|
}
|
||||||
|
|
||||||
|
prefixWords = tried.PrefixWords(input[1])
|
||||||
|
if ok, _ := CompareSliceWithSorted(prefixWords, wordsCollection); ok {
|
||||||
|
t.Error("should be not ok")
|
||||||
|
}
|
||||||
|
if len(prefixWords) != 2 {
|
||||||
|
t.Error(prefixWords, " Size of Array should be 2")
|
||||||
|
}
|
||||||
|
|
||||||
|
if ok, errorResult := CompareSliceWithSorted(prefixWords, wordsCollection[1:]); !ok {
|
||||||
|
t.Error(errorResult)
|
||||||
|
}
|
||||||
|
|
||||||
|
// t.Error(tried.WordsArray())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestTried_NewWith(t *testing.T) {
|
func TestTried_NewWith(t *testing.T) {
|
||||||
var tried *Tried
|
var tried *Tried
|
||||||
var wordsCollection []string
|
var wordsCollection []string
|
||||||
@ -98,25 +219,12 @@ func TestTried_String(t *testing.T) {
|
|||||||
t.Error("should be not nil the type is ", tried.wiStore.Type)
|
t.Error("should be not nil the type is ", tried.wiStore.Type)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sort.Slice(wordsCollection, func(i, j int) bool {
|
|
||||||
if wordsCollection[i] < wordsCollection[j] {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
})
|
|
||||||
|
|
||||||
resultArray := tried.WordsArray()
|
resultArray := tried.WordsArray()
|
||||||
sort.Slice(resultArray, func(i, j int) bool {
|
if ok, errorResult := CompareSliceWithSorted(resultArray, wordsCollection); !ok {
|
||||||
if resultArray[i] < resultArray[j] {
|
t.Error(errorResult)
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
})
|
|
||||||
result1 := spew.Sprint(resultArray)
|
|
||||||
result2 := spew.Sprint(wordsCollection)
|
|
||||||
if result1 != result2 {
|
|
||||||
t.Error(result1, " != ", result2)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// t.Error(tried.WordsArray())
|
// t.Error(tried.WordsArray())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user