修改为Interface的形式

This commit is contained in:
huangsimin 2019-08-19 14:30:24 +08:00
parent f4cd890053
commit ebbce1e0a2
3 changed files with 102 additions and 22 deletions

1
go.sum
View File

@ -4,3 +4,4 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg= github.com/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg=
github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o= github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o=
github.com/petar/GoLLRB v0.0.0-20190514000832-33fb24c13b99 h1:KcEvVBAvyHkUdFAygKAzwB6LAcZ6LS32WHmRD2VyXMI=

View File

@ -1,9 +1,30 @@
package tried package tried
type TriedString string
func (ts TriedString) Size() uint {
return uint(len(ts))
}
func (ts TriedString) WordIndex(idx uint) uint {
w := ts[idx]
if w >= 'a' && w <= 'z' {
return uint(w) - 'a'
} else if w >= 'A' && w <= 'Z' {
return uint(w) - 'A' + 26
} else {
return uint(w) - '0' + 52
}
}
type ObjectIndex interface {
WordIndex(idx uint) uint
Size() uint
}
type Tried struct { type Tried struct {
root *Node root *Node
datasize uint datasize uint
// wordIndex func ()
} }
type Node struct { type Node struct {
@ -14,17 +35,28 @@ type Node struct {
func New() *Tried { func New() *Tried {
tried := &Tried{} tried := &Tried{}
tried.root = new(Node) tried.root = new(Node)
tried.datasize = 62
return tried return tried
} }
func (tried *Tried) Put(words string, values ...interface{}) { func (tried *Tried) wordIndex(w byte) uint {
if w >= 'a' && w <= 'z' {
return uint(w) - 'a'
} else if w >= 'A' && w <= 'Z' {
return uint(w) - 'A' + 26
} else {
return uint(w) - '0' + 52
}
}
func (tried *Tried) Put(words ObjectIndex, values ...interface{}) {
cur := tried.root cur := tried.root
var n *Node var n *Node
for i := 0; i < len(words); i++ { for i := uint(0); i < words.Size(); i++ {
w := uint(words[i] - 'a') w := words.WordIndex(i)
if cur.data == nil { if cur.data == nil {
cur.data = make([]*Node, 26) cur.data = make([]*Node, tried.datasize)
} }
if n = cur.data[w]; n == nil { if n = cur.data[w]; n == nil {
@ -48,11 +80,11 @@ func (tried *Tried) Put(words string, values ...interface{}) {
} }
func (tried *Tried) Get(words string) interface{} { func (tried *Tried) Get(words ObjectIndex) interface{} {
cur := tried.root cur := tried.root
var n *Node var n *Node
for i := 0; i < len(words); i++ { for i := uint(0); i < words.Size(); i++ {
w := uint(words[i] - 'a') //TODO: 升级Index 函数 w := words.WordIndex(i) //TODO: 升级Index 函数
if n = cur.data[w]; n == nil { if n = cur.data[w]; n == nil {
return nil return nil
} }
@ -61,7 +93,7 @@ func (tried *Tried) Get(words string) interface{} {
return n.value return n.value
} }
func (tried *Tried) Has(words string) bool { func (tried *Tried) Has(words ObjectIndex) bool {
return tried.Get(words) != nil return tried.Get(words) != nil
} }

View File

@ -2,37 +2,40 @@ package tried
import ( import (
"testing" "testing"
"github.com/Pallinder/go-randomdata"
) )
func TestTried_PutAndGet1(t *testing.T) { func TestTried_PutAndGet1(t *testing.T) {
tried := New() tried := New()
tried.Put("asdf")
tried.Put("hehe", "hehe") tried.Put(TriedString("asdf"))
tried.Put("xixi", 3) tried.Put(TriedString("hehe"), "hehe")
tried.Put(TriedString("xixi"), 3)
var result interface{} var result interface{}
result = tried.Get("asdf") result = tried.Get(TriedString("asdf"))
if result != tried { if result != tried {
t.Error("result should be 3") t.Error("result should be 3")
} }
result = tried.Get("xixi") result = tried.Get(TriedString("xixi"))
if result != 3 { if result != 3 {
t.Error("result should be 3") t.Error("result should be 3")
} }
result = tried.Get("hehe") result = tried.Get(TriedString("hehe"))
if result != "hehe" { if result != "hehe" {
t.Error("result should be hehe") t.Error("result should be hehe")
} }
result = tried.Get("haha") result = tried.Get(TriedString("haha"))
if result != nil { if result != nil {
t.Error("result should be nil") t.Error("result should be nil")
} }
result = tried.Get("b") result = tried.Get(TriedString("b"))
if result != nil { if result != nil {
t.Error("result should be nil") t.Error("result should be nil")
} }
@ -40,10 +43,10 @@ func TestTried_PutAndGet1(t *testing.T) {
func TestTried_Traversal(t *testing.T) { func TestTried_Traversal(t *testing.T) {
tried := New() tried := New()
tried.Put("asdf") tried.Put(TriedString("asdf"))
tried.Put("abdf", "ab") tried.Put(TriedString("abdf"), "ab")
tried.Put("hehe", "hehe") tried.Put(TriedString("hehe"), "hehe")
tried.Put("xixi", 3) tried.Put(TriedString("xixi"), 3)
var result []interface{} var result []interface{}
tried.Traversal(func(idx uint, v interface{}) bool { tried.Traversal(func(idx uint, v interface{}) bool {
@ -67,5 +70,49 @@ func TestTried_Traversal(t *testing.T) {
if result[3] != 3 { if result[3] != 3 {
t.Error(result[3]) t.Error(result[3])
} }
}
func BenchmarkTried_Put(b *testing.B) {
var data []TriedString
b.N = 10000
count := 1000
for i := 0; i < b.N; i++ {
data = append(data, TriedString(randomdata.RandStringRunes(10)+randomdata.RandStringRunes(4)))
}
b.ResetTimer()
b.N = b.N * count
for c := 0; c < count; c++ {
tried := New()
for _, v := range data {
tried.Put(v)
}
}
}
func BenchmarkTried_Get(b *testing.B) {
var data []TriedString
b.N = 10000
count := 1000
for i := 0; i < b.N; i++ {
data = append(data, TriedString(randomdata.RandStringRunes(10)+randomdata.RandStringRunes(4)))
}
b.N = b.N * count
tried := New()
for _, v := range data {
tried.Put(v)
}
b.ResetTimer()
for c := 0; c < count; c++ {
for _, v := range data {
tried.Get(v)
}
}
} }