From b92f270429eb8c524158ec6650a4bfbfc0d448eb Mon Sep 17 00:00:00 2001 From: huangsimin Date: Tue, 20 Aug 2019 15:03:05 +0800 Subject: [PATCH] =?UTF-8?q?=E5=89=8D=E7=BC=80=E6=A0=91=20=E5=AE=8C?= =?UTF-8?q?=E6=88=90=E5=9F=BA=E6=9C=AC=E5=8A=9F=E8=83=BD,=20=E5=87=86?= =?UTF-8?q?=E5=A4=87=E6=B7=BB=E5=8A=A0=E4=B8=80=E4=B8=AA=E9=AB=98=E5=BA=A6?= =?UTF-8?q?=E5=B1=9E=E6=80=A7=E8=BE=BE=E5=88=B0=E9=95=BF=E5=BA=A6=E6=A3=80?= =?UTF-8?q?=E7=B4=A2=E7=9A=84=E7=9B=AE=E7=9A=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tree/tried/tried.go | 74 +++++++++++++++++---- tree/tried/tried_test.go | 140 ++++++++++++++++++++++++++++++++++----- 2 files changed, 185 insertions(+), 29 deletions(-) diff --git a/tree/tried/tried.go b/tree/tried/tried.go index 4c58fff..3150406 100644 --- a/tree/tried/tried.go +++ b/tree/tried/tried.go @@ -62,26 +62,20 @@ func (tried *Tried) Put(words string, values ...interface{}) { cur = n } - vlen := len(values) - switch vlen { - case 0: - cur.value = tried - case 1: + if values != nil { cur.value = values[0] - case 2: - // TODO: 执行函数 values[1] 为函数类型 func (cur *Node, value interface{}) ...可以插入, 也可以不插入 - default: - panic("unknow select to do") + } else { + cur.value = tried } - } func (tried *Tried) Get(words string) interface{} { cur := tried.root var n *Node + bytes := []byte(words) - for i := 0; i < len(words); i++ { - w := tried.wiStore.Byte2Index(words[i]) //TODO: 升级Index 函数 + for i := 0; i < len(bytes); i++ { + w := tried.wiStore.Byte2Index(bytes[i]) //TODO: 升级Index 函数 if n = cur.data[w]; n == nil { return nil } @@ -95,7 +89,61 @@ func (tried *Tried) Has(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) { diff --git a/tree/tried/tried_test.go b/tree/tried/tried_test.go index b6b7789..5cbd88a 100644 --- a/tree/tried/tried_test.go +++ b/tree/tried/tried_test.go @@ -12,6 +12,127 @@ import ( "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[]\\'/?()#$%^&**! ", " `.,?/"}) + + 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) { var tried *Tried 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) } } - sort.Slice(wordsCollection, func(i, j int) bool { - if wordsCollection[i] < wordsCollection[j] { - return true - } - return false - }) resultArray := tried.WordsArray() - sort.Slice(resultArray, func(i, j int) bool { - if resultArray[i] < resultArray[j] { - return true - } - return false - }) - result1 := spew.Sprint(resultArray) - result2 := spew.Sprint(wordsCollection) - if result1 != result2 { - t.Error(result1, " != ", result2) + if ok, errorResult := CompareSliceWithSorted(resultArray, wordsCollection); !ok { + t.Error(errorResult) } + // t.Error(tried.WordsArray()) } }