TUN-813: Clean up cloudflared dependencies

This commit is contained in:
Areg Harutyunyan
2018-07-24 18:04:33 -05:00
parent d06fc520c7
commit 0468866626
3310 changed files with 993 additions and 1223303 deletions

View File

@@ -1,26 +0,0 @@
# Badgerodon Collections
Maps and slices go a long way in Go, but sometimes you need more. This is a collection of collections that may be useful.
## Queue
A [queue](http://en.wikipedia.org/wiki/Queue_(data_structure%29) is a first-in first-out data structure.
## Set
A [set](http://en.wikipedia.org/wiki/Set_(computer_science%29) is an unordered collection of unique values typically used for testing membership.
## Skip list
A [skip list](http://en.wikipedia.org/wiki/Skip_list) is a data structure that stores nodes in a hierarchy of linked lists. It gives performance similar to binary search trees by using a random number of forward links to skip parts of the list.
## Splay Tree
A [splay tree](http://en.wikipedia.org/wiki/Splay_tree) is a type of binary search tree where every access to the tree results in the tree being rearranged so that the current node gets put on top.
## Stack
A [stack](http://en.wikipedia.org/wiki/Stack_(abstract_data_type%29) is a last-in last-out data structure.
## Trie
A [trie](http://en.wikipedia.org/wiki/Trie) is a type of tree where each node represents one byte of a key.
## Ternary Search Tree
A [ternary search tree](http://en.wikipedia.org/wiki/Ternary_search_tree) is similar to a trie in that nodes store the letters of the key, but instead of either using a list or hash at each node a binary tree is used. Ternary search trees have the performance benefits of a trie without the usual memory costs.

View File

@@ -1,27 +0,0 @@
package collections
type (
Collection interface {
Do(func(interface{})bool)
}
)
func GetRange(c Collection, start, length int) []interface{} {
end := start + length
items := make([]interface{}, length)
i := 0
j := 0
c.Do(func(item interface{})bool{
if i >= start {
if i < end {
items[j] = item
j++
} else {
return false
}
}
i++
return true
})
return items[:j]
}

View File

@@ -1,52 +0,0 @@
package grid
import (
. "github.com/badgerodon/collections"
)
type (
Grid struct {
values []interface{}
cols, rows int
}
)
func New(cols, rows int) *Grid {
return &Grid{
values: make([]interface{}, cols*rows),
cols: cols,
rows: rows,
}
}
func (this *Grid) Do(f func(p Point, value interface{})) {
for x := 0; x < this.cols; x++ {
for y := 0; y < this.rows; y++ {
f(Point{x, y}, this.values[x*this.cols+y])
}
}
}
func (this *Grid) Get(p Point) interface{} {
if p.X < 0 || p.Y < 0 || p.X >= this.cols || p.Y >= this.rows {
return nil
}
v, _ := this.values[p.X*this.cols+p.Y]
return v
}
func (this *Grid) Rows() int {
return this.rows
}
func (this *Grid) Cols() int {
return this.cols
}
func (this *Grid) Len() int {
return this.rows * this.cols
}
func (this *Grid) Set(p Point, v interface{}) {
}

View File

@@ -1,7 +0,0 @@
package collections
type (
Point struct {
X, Y int
}
)

View File

@@ -1,50 +0,0 @@
package queue
import (
"testing"
)
func Test(t *testing.T) {
q := New()
if q.Len() != 0 {
t.Errorf("Length should be 0")
}
q.Enqueue(1)
if q.Len() != 1 {
t.Errorf("Length should be 1")
}
if q.Peek().(int) != 1 {
t.Errorf("Enqueued value should be 1")
}
v := q.Dequeue()
if v.(int) != 1 {
t.Errorf("Dequeued value should be 1")
}
if q.Peek() != nil || q.Dequeue() != nil {
t.Errorf("Empty queue should have no values")
}
q.Enqueue(1)
q.Enqueue(2)
if q.Len() != 2 {
t.Errorf("Length should be 2")
}
if q.Peek().(int) != 1 {
t.Errorf("First value should be 1")
}
q.Dequeue()
if q.Peek().(int) != 2 {
t.Errorf("Next value should be 2")
}
}

View File

@@ -1,106 +0,0 @@
package set
type (
Set struct {
hash map[interface{}]nothing
}
nothing struct{}
)
// Create a new set
func New(initial ...interface{}) *Set {
s := &Set{make(map[interface{}]nothing)}
for _, v := range initial {
s.Insert(v)
}
return s
}
// Find the difference between two sets
func (this *Set) Difference(set *Set) *Set {
n := make(map[interface{}]nothing)
for k, _ := range this.hash {
if _, exists := set.hash[k]; !exists {
n[k] = nothing{}
}
}
return &Set{n}
}
// Call f for each item in the set
func (this *Set) Do(f func(interface{})) {
for k, _ := range this.hash {
f(k)
}
}
// Test to see whether or not the element is in the set
func (this *Set) Has(element interface{}) bool {
_, exists := this.hash[element]
return exists
}
// Add an element to the set
func (this *Set) Insert(element interface{}) {
this.hash[element] = nothing{}
}
// Find the intersection of two sets
func (this *Set) Intersection(set *Set) *Set {
n := make(map[interface{}]nothing)
for k, _ := range this.hash {
if _, exists := set.hash[k]; exists {
n[k] = nothing{}
}
}
return &Set{n}
}
// Return the number of items in the set
func (this *Set) Len() int {
return len(this.hash)
}
// Test whether or not this set is a proper subset of "set"
func (this *Set) ProperSubsetOf(set *Set) bool {
return this.SubsetOf(set) && this.Len() < set.Len()
}
// Remove an element from the set
func (this *Set) Remove(element interface{}) {
delete(this.hash, element)
}
// Test whether or not this set is a subset of "set"
func (this *Set) SubsetOf(set *Set) bool {
if this.Len() > set.Len() {
return false
}
for k, _ := range this.hash {
if _, exists := set.hash[k]; !exists {
return false
}
}
return true
}
// Find the union of two sets
func (this *Set) Union(set *Set) *Set {
n := make(map[interface{}]nothing)
for k, _ := range this.hash {
n[k] = nothing{}
}
for k, _ := range set.hash {
n[k] = nothing{}
}
return &Set{n}
}

View File

@@ -1,74 +0,0 @@
package set
import (
"testing"
)
func Test(t *testing.T) {
s := New()
s.Insert(5)
if s.Len() != 1 {
t.Errorf("Length should be 1")
}
if !s.Has(5) {
t.Errorf("Membership test failed")
}
s.Remove(5)
if s.Len() != 0 {
t.Errorf("Length should be 0")
}
if s.Has(5) {
t.Errorf("The set should be empty")
}
// Difference
s1 := New(1,2,3,4,5,6)
s2 := New(4,5,6)
s3 := s1.Difference(s2)
if s3.Len() != 3 {
t.Errorf("Length should be 3")
}
if !(s3.Has(1) && s3.Has(2) && s3.Has(3)) {
t.Errorf("Set should only contain 1, 2, 3")
}
// Intersection
s3 = s1.Intersection(s2)
if s3.Len() != 3 {
t.Errorf("Length should be 3 after intersection")
}
if !(s3.Has(4) && s3.Has(5) && s3.Has(6)) {
t.Errorf("Set should contain 4, 5, 6")
}
// Union
s4 := New(7,8,9)
s3 = s2.Union(s4)
if s3.Len() != 6 {
t.Errorf("Length should be 6 after union")
}
if !(s3.Has(7)) {
t.Errorf("Set should contain 4, 5, 6, 7, 8, 9")
}
// Subset
if !s1.SubsetOf(s1) {
t.Errorf("set should be a subset of itself")
}
// Proper Subset
if s1.ProperSubsetOf(s1) {
t.Errorf("set should not be a subset of itself")
}
}

View File

@@ -1,171 +0,0 @@
package skip
import (
"fmt"
"math/rand"
"time"
)
type (
node struct {
next []*node
key interface{}
value interface{}
}
SkipList struct {
root *node
size int
less func(interface{},interface{})bool
gen *rand.Rand
probability float64
}
)
// Create a new skip list
func New(less func(interface{},interface{})bool) *SkipList {
gen := rand.New(rand.NewSource(time.Now().UnixNano()))
n := &node{make([]*node, 0),nil,nil}
return &SkipList{n, 0, less, gen, 0.75}
}
func (this *SkipList) Do(f func(interface{}, interface{})bool) {
if this.size == 0 {
return
}
cur := this.root.next[0]
for cur != nil {
if !f(cur.key, cur.value) {
break
}
cur = cur.next[0]
}
}
// Get an item from the skip list
func (this *SkipList) Get(key interface{}) interface{} {
if this.size == 0 {
return nil
}
cur := this.root
// Start at the top
for i := len(cur.next)-1; i >= 0; i-- {
for this.less(cur.next[i].key, key) {
cur = cur.next[i]
}
}
cur = cur.next[0]
if this.equals(cur.key, key) {
return cur.value
}
return nil
}
// Insert a new item into the skip list
func (this *SkipList) Insert(key interface{}, value interface{}) {
prev := this.getPrevious(key)
// Already in the list so just update the value
if len(prev) > 0 && prev[0].next[0] != nil && this.equals(prev[0].next[0].key, key) {
prev[0].next[0].value = value
return
}
h := len(this.root.next)
nh := this.pickHeight()
n := &node{make([]*node, nh),key,value}
// Higher than anything seen before, so tack it on top
if nh > h {
this.root.next = append(this.root.next, n)
}
// Update the previous nodes
for i := 0; i < h && i < nh; i++ {
n.next[i] = prev[i].next[i]
prev[i].next[i] = n
}
this.size++
}
// Get the length of the skip list
func (this *SkipList) Len() int {
return this.size
}
// Remove an item from the skip list
func (this *SkipList) Remove(key interface{}) interface{} {
prev := this.getPrevious(key)
if len(prev) == 0 {
return nil
}
cur := prev[0].next[0]
// If we found it
if cur != nil && this.equals(key, cur.key) {
// Change all the linked lists
for i := 0; i < len(prev); i++ {
if prev[i] != nil && prev[i].next[i] != nil {
prev[i].next[i] = cur.next[i]
}
}
// Kill off the upper links if they're nil
for i := len(this.root.next)-1; i>=0; i-- {
if this.root.next[i] == nil {
this.root.next = this.root.next[:i]
} else {
break
}
}
this.size--
return cur.value
}
return nil
}
// String representation of the list
func (this *SkipList) String() string {
str := "{"
if len(this.root.next) > 0 {
cur := this.root.next[0]
for cur != nil {
str += fmt.Sprint(cur.key)
str += ":"
str += fmt.Sprint(cur.value)
str += " "
cur = cur.next[0]
}
}
str += "}"
return str
}
// Get a vertical list of nodes of all the things that occur
// immediately before "key"
func (this *SkipList) getPrevious(key interface{}) []*node {
cur := this.root
h := len(cur.next)
nodes := make([]*node, h)
for i := h-1; i >= 0; i-- {
for cur.next[i] != nil && this.less(cur.next[i].key, key) {
cur = cur.next[i]
}
nodes[i] = cur
}
return nodes
}
// Defines an equals method in terms of "less"
func (this *SkipList) equals(a, b interface{}) bool {
return !this.less(a,b) && !this.less(b,a)
}
// Pick a random height
func (this *SkipList) pickHeight() int {
h := 1
for this.gen.Float64() > this.probability {
h++
}
if h > len(this.root.next) {
return h + 1
}
return h
}

View File

@@ -1,38 +0,0 @@
package skip
import (
//"fmt"
"testing"
)
func Test(t *testing.T) {
sl := New(func(a,b interface{})bool {
return a.(int) < b.(int)
})
sl.Insert(1, 100)
if sl.Len() != 1 {
t.Errorf("expecting len 1")
}
sl.Insert(1, 1000)
if sl.Len() != 1 {
t.Errorf("expecting len 1")
}
if sl.Get(1).(int) != 1000 {
t.Errorf("expecting sl[1] == 1000")
}
sl.Remove(1)
if sl.Len() != 0 {
t.Errorf("expecting len 0")
}
sl.Insert(2, 200)
sl.Insert(1, 100)
vs := make([]int, 0)
sl.Do(func(k, v interface{}) bool {
vs = append(vs, k.(int))
return true
})
if len(vs) != 2 || vs[0] != 1 || vs[1] != 2 {
t.Errorf("expecting sorted iteration of all keys")
}
}

View File

@@ -1,487 +0,0 @@
package splay
import (
"fmt"
)
type (
Any interface{}
LessFunc func(interface{}, interface{}) bool
VisitFunc func(interface{}) bool
node struct {
value Any
parent, left, right *node
}
nodei struct {
step int
node *node
prev *nodei
}
SplayTree struct {
length int
root *node
less LessFunc
}
)
// Create a new splay tree, using the less function to determine the order.
func New(less LessFunc) *SplayTree {
return &SplayTree{0, nil, less}
}
// Get the first value from the collection. Returns nil if empty.
func (this *SplayTree) First() Any {
if this.length == 0 {
return nil
}
n := this.root
for n.left != nil {
n = n.left
}
return n.value
}
// Get the last value from the collection. Returns nil if empty.
func (this *SplayTree) Last() Any {
if this.length == 0 {
return nil
}
n := this.root
for n.right != nil {
n = n.right
}
return n.value
}
// Get an item from the splay tree
func (this *SplayTree) Get(item Any) Any {
if this.length == 0 {
return nil
}
n := this.root
for n != nil {
if this.less(item, n.value) {
n = n.left
continue
}
if this.less(n.value, item) {
n = n.right
continue
}
this.splay(n)
return n.value
}
return nil
}
func (this *SplayTree) Has(value Any) bool {
return this.Get(value) != nil
}
func (this *SplayTree) Init() {
this.length = 0
this.root = nil
}
func (this *SplayTree) Add(value Any) {
if this.length == 0 {
this.root = &node{value, nil, nil, nil}
this.length = 1
return
}
n := this.root
for {
if this.less(value, n.value) {
if n.left == nil {
n.left = &node{value, n, nil, nil}
this.length++
n = n.left
break
}
n = n.left
continue
}
if this.less(n.value, value) {
if n.right == nil {
n.right = &node{value, n, nil, nil}
this.length++
n = n.right
break
}
n = n.right
continue
}
n.value = value
break
}
this.splay(n)
}
func (this *SplayTree) PreOrder(visit VisitFunc) {
if this.length == 1 {
return
}
i := &nodei{0, this.root, nil}
for i != nil {
switch i.step {
// Value
case 0:
i.step++
if !visit(i.node.value) {
break
}
// Left
case 1:
i.step++
if i.node.left != nil {
i = &nodei{0, i.node.left, i}
}
// Right
case 2:
i.step++
if i.node.right != nil {
i = &nodei{0, i.node.right, i}
}
default:
i = i.prev
}
}
}
func (this *SplayTree) InOrder(visit VisitFunc) {
if this.length == 1 {
return
}
i := &nodei{0, this.root, nil}
for i != nil {
switch i.step {
// Left
case 0:
i.step++
if i.node.left != nil {
i = &nodei{0, i.node.left, i}
}
// Value
case 1:
i.step++
if !visit(i.node.value) {
break
}
// Right
case 2:
i.step++
if i.node.right != nil {
i = &nodei{0, i.node.right, i}
}
default:
i = i.prev
}
}
}
func (this *SplayTree) PostOrder(visit VisitFunc) {
if this.length == 1 {
return
}
i := &nodei{0, this.root, nil}
for i != nil {
switch i.step {
// Left
case 0:
i.step++
if i.node.left != nil {
i = &nodei{0, i.node.left, i}
}
// Right
case 1:
i.step++
if i.node.right != nil {
i = &nodei{0, i.node.right, i}
}
// Value
case 2:
i.step++
if !visit(i.node.value) {
break
}
default:
i = i.prev
}
}
}
func (this *SplayTree) Do(visit VisitFunc) {
this.InOrder(visit)
}
func (this *SplayTree) Len() int {
return this.length
}
func (this *SplayTree) Remove(value Any) {
if this.length == 0 {
return
}
n := this.root
for n != nil {
if this.less(value, n.value) {
n = n.left
continue
}
if this.less(n.value, value) {
n = n.right
continue
}
// First splay the parent node
if n.parent != nil {
this.splay(n.parent)
}
// No children
if n.left == nil && n.right == nil {
// guess we're the root node
if n.parent == nil {
this.root = nil
break
}
if n.parent.left == n {
n.parent.left = nil
} else {
n.parent.right = nil
}
} else if n.left == nil {
// root node
if n.parent == nil {
this.root = n.right
break
}
if n.parent.left == n {
n.parent.left = n.right
} else {
n.parent.right = n.right
}
} else if n.right == nil {
// root node
if n.parent == nil {
this.root = n.left
break
}
if n.parent.left == n {
n.parent.left = n.left
} else {
n.parent.right = n.left
}
} else {
// find the successor
s := n.right
for s.left != nil {
s = s.left
}
np := n.parent
nl := n.left
nr := n.right
sp := s.parent
sr := s.right
// Update parent
s.parent = np
if np == nil {
this.root = s
} else {
if np.left == n {
np.left = s
} else {
np.right = s
}
}
// Update left
s.left = nl
s.left.parent = s
// Update right
if nr != s {
s.right = nr
s.right.parent = s
}
// Update successor parent
if sp.left == s {
sp.left = sr
} else {
sp.right = sr
}
}
break
}
if n != nil {
this.length--
}
}
func (this *SplayTree) String() string {
if this.length == 0 {
return "{}"
}
return this.root.String()
}
// Splay a node in the tree (send it to the top)
func (this *SplayTree) splay(n *node) {
// Already root, nothing to do
if n.parent == nil {
this.root = n
return
}
p := n.parent
g := p.parent
// Zig
if p == this.root {
if n == p.left {
p.rotateRight()
} else {
p.rotateLeft()
}
} else {
// Zig-zig
if n == p.left && p == g.left {
g.rotateRight()
p.rotateRight()
} else if n == p.right && p == g.right {
g.rotateLeft()
p.rotateLeft()
// Zig-zag
} else if n == p.right && p == g.left {
p.rotateLeft()
g.rotateRight()
} else if n == p.left && p == g.right {
p.rotateRight()
g.rotateLeft()
}
}
this.splay(n)
}
// Swap two nodes in the tree
func (this *SplayTree) swap(n1, n2 *node) {
p1 := n1.parent
l1 := n1.left
r1 := n1.right
p2 := n2.parent
l2 := n2.left
r2 := n2.right
// Update node links
n1.parent = p2
n1.left = l2
n1.right = r2
n2.parent = p1
n2.left = l1
n2.right = r1
// Update parent links
if p1 != nil {
if p1.left == n1 {
p1.left = n2
} else {
p1.right = n2
}
}
if p2 != nil {
if p2.left == n2 {
p2.left = n1
} else {
p2.right = n1
}
}
if n1 == this.root {
this.root = n2
} else if n2 == this.root {
this.root = n1
}
}
// Node methods
func (this *node) String() string {
str := "{" + fmt.Sprint(this.value) + "|"
if this.left != nil {
str += this.left.String()
}
str += "|"
if this.right != nil {
str += this.right.String()
}
str += "}"
return str
}
func (this *node) rotateLeft() {
parent := this.parent
pivot := this.right
child := pivot.left
if pivot == nil {
return
}
// Update the parent
if parent != nil {
if parent.left == this {
parent.left = pivot
} else {
parent.right = pivot
}
}
// Update the pivot
pivot.parent = parent
pivot.left = this
// Update the child
if child != nil {
child.parent = this
}
// Update this
this.parent = pivot
this.right = child
}
func (this *node) rotateRight() {
parent := this.parent
pivot := this.left
child := pivot.right
if pivot == nil {
return
}
// Update the parent
if parent != nil {
if parent.left == this {
parent.left = pivot
} else {
parent.right = pivot
}
}
// Update the pivot
pivot.parent = parent
pivot.right = this
if child != nil {
child.parent = this
}
// Update this
this.parent = pivot
this.left = child
}

View File

@@ -1,27 +0,0 @@
package splay
import (
//"fmt"
"testing"
)
func Test(t *testing.T) {
tree := New(func(a,b interface{})bool {
return a.(string) < b.(string)
})
tree.Insert("d", 4)
tree.Insert("b", 2)
tree.Insert("a", 1)
tree.Insert("c", 3)
if tree.Len() != 4 {
t.Errorf("expecting len 4")
}
tree.Remove("b")
if tree.Len() != 3 {
t.Errorf("expecting len 3")
}
}

View File

@@ -1,44 +0,0 @@
package stack
type (
Stack struct {
top *node
length int
}
node struct {
value interface{}
prev *node
}
)
// Create a new stack
func New() *Stack {
return &Stack{nil,0}
}
// Return the number of items in the stack
func (this *Stack) Len() int {
return this.length
}
// View the top item on the stack
func (this *Stack) Peek() interface{} {
if this.length == 0 {
return nil
}
return this.top.value
}
// Pop the top item of the stack and return it
func (this *Stack) Pop() interface{} {
if this.length == 0 {
return nil
}
n := this.top
this.top = n.prev
this.length--
return n.value
}
// Push a value onto the top of the stack
func (this *Stack) Push(value interface{}) {
n := &node{value,this.top}
this.top = n
this.length++
}

View File

@@ -1,42 +0,0 @@
package stack
import (
"testing"
)
func Test(t *testing.T) {
s := New()
if s.Len() != 0 {
t.Errorf("Length of an empty stack should be 0")
}
s.Push(1)
if s.Len() != 1 {
t.Errorf("Length should be 0")
}
if s.Peek().(int) != 1 {
t.Errorf("Top item on the stack should be 1")
}
if s.Pop().(int) != 1 {
t.Errorf("Top item should have been 1")
}
if s.Len() != 0 {
t.Errorf("Stack should be empty")
}
s.Push(1)
s.Push(2)
if s.Len() != 2 {
t.Errorf("Length should be 2")
}
if s.Peek().(int) != 2 {
t.Errorf("Top of the stack should be 2")
}
}

View File

@@ -1,148 +0,0 @@
package trie
import (
"fmt"
)
type (
Trie struct {
root *node
size int
}
node struct {
key interface{}
value interface{}
next [256]*node
}
iterator struct {
step int
node *node
prev *iterator
}
)
func toBytes(obj interface{}) []byte {
switch o := obj.(type) {
case []byte:
return o
case string:
return []byte(o)
}
return []byte(fmt.Sprint(obj))
}
func New() *Trie {
return &Trie{nil,0}
}
func (this *Trie) Do(handler func(interface{},interface{})bool) {
if this.size > 0 {
this.root.do(handler)
}
}
func (this *Trie) Get(key interface{}) interface{} {
if this.size == 0 {
return nil
}
bs := toBytes(key)
cur := this.root
for i := 0; i < len(bs); i++ {
if cur.next[bs[i]] != nil {
cur = cur.next[bs[i]]
} else {
return nil
}
}
return cur.value
}
func (this *Trie) Has(key interface{}) bool {
return this.Get(key) != nil
}
func (this *Trie) Init() {
this.root = nil
this.size = 0
}
func (this *Trie) Insert(key interface{}, value interface{}) {
if this.size == 0 {
this.root = newNode()
}
bs := toBytes(key)
cur := this.root
for i := 0; i < len(bs); i++ {
if cur.next[bs[i]] != nil {
cur = cur.next[bs[i]]
} else {
cur.next[bs[i]] = newNode()
cur = cur.next[bs[i]]
}
}
if cur.key == nil {
this.size++
}
cur.key = key
cur.value = value
}
func (this *Trie) Len() int {
return this.size
}
func (this *Trie) Remove(key interface{}) interface{} {
if this.size == 0 {
return nil
}
bs := toBytes(key)
cur := this.root
for i := 0; i < len(bs); i++ {
if cur.next[bs[i]] != nil {
cur = cur.next[bs[i]]
} else {
return nil
}
}
// TODO: cleanup dead nodes
val := cur.value
if cur.value != nil {
this.size--
cur.value = nil
cur.key = nil
}
return val
}
func (this *Trie) String() string {
str := "{"
i := 0
this.Do(func(k, v interface{}) bool {
if i > 0 {
str += ", "
}
str += fmt.Sprint(k, ":", v)
i++
return true
})
str += "}"
return str
}
func newNode() *node {
var next [256]*node
return &node{nil,nil,next}
}
func (this *node) do(handler func(interface{}, interface{}) bool) bool {
for i := 0; i < 256; i++ {
if this.next[i] != nil {
if this.next[i].key != nil {
if !handler(this.next[i].key, this.next[i].value) {
return false
}
}
if !this.next[i].do(handler) {
return false
}
}
}
return true
}

View File

@@ -1,31 +0,0 @@
package trie
import (
//"fmt"
"testing"
)
func Test(t *testing.T) {
x := New()
x.Insert(1, 100)
if x.Len() != 1 {
t.Errorf("expected len 1")
}
if x.Get(1).(int) != 100 {
t.Errorf("expected to get 100 for 1")
}
x.Remove(1)
if x.Len() != 0 {
t.Errorf("expected len 0")
}
x.Insert(2, 200)
x.Insert(1, 100)
vs := make([]int, 0)
x.Do(func(k, v interface{}) bool {
vs = append(vs, k.(int))
return true
})
if len(vs) != 2 || vs[0] != 1 || vs[1] != 2 {
t.Errorf("expected in order traversal")
}
}

View File

@@ -1,306 +0,0 @@
package tst
import (
"fmt"
)
type (
Node struct {
key byte
value interface{}
left, middle, right *Node
}
NodeIterator struct {
step int
node *Node
prev *NodeIterator
}
TernarySearchTree struct {
length int
root *Node
}
)
// Create a new ternary search tree
func New() *TernarySearchTree {
tree := &TernarySearchTree{}
tree.Init()
return tree
}
// Iterate over the collection
func (this *TernarySearchTree) Do(callback func(string, interface{})bool) {
if this.Len() == 0 {
return
}
bs := []byte{}
i := &NodeIterator{0,this.root,nil}
for i != nil {
switch i.step {
// Left
case 0:
i.step++
if i.node.left != nil {
i = &NodeIterator{0,i.node.left,i}
continue
}
// Value
case 1:
i.step++
if i.node.key > 0 {
bs = append(bs, i.node.key)
}
if i.node.value != nil {
if !callback(string(bs), i.node.value) {
return
}
continue
}
// Middle
case 2:
i.step++
if i.node.middle != nil {
i = &NodeIterator{0,i.node.middle,i}
continue
}
// Right
case 3:
if len(bs) > 0 {
bs = bs[:len(bs)-1]
}
i.step++
if i.node.right != nil {
i = &NodeIterator{0,i.node.right,i}
continue
}
// Backtrack
case 4:
i = i.prev
}
}
}
// Get the value at the specified key. Returns nil if not found.
func (this *TernarySearchTree) Get(key string) interface{} {
if this.length == 0 {
return nil
}
node := this.root
bs := []byte(key)
for i := 0; i < len(bs); {
b := bs[i]
if b > node.key {
if node.right == nil {
return nil
}
node = node.right
} else if (b < node.key) {
if node.left == nil {
return nil
}
node = node.left
} else {
i++
if i < len(bs) {
if node.middle == nil {
return nil
}
node = node.middle
} else {
break
}
}
}
return node.value
}
func (this *TernarySearchTree) GetLongestPrefix(key string) interface{} {
if this.length == 0 {
return nil
}
n := this.root
v := n.value
bs := []byte(key)
for i := 0; i < len(bs); {
b := bs[i]
if n.value != nil {
v = n.value
}
if b > n.key {
if n.right == nil {
break
}
n = n.right
} else if b < n.key {
if n.left == nil {
break
}
n = n.left
} else {
i++
if i < len(bs) {
if n.middle == nil {
break
}
n = n.middle
} else {
break
}
}
}
if n.value != nil {
v = n.value
}
return v
}
// Test to see whether or not the given key is contained in the tree.
func (this *TernarySearchTree) Has(key string) bool {
return this.Get(key) != nil
}
// Initialize the tree (reset it so that it's empty). New will do this for you.
func (this *TernarySearchTree) Init() {
this.length = 0
this.root = nil
}
// Insert a new key value pair into the collection
func (this *TernarySearchTree) Insert(key string, value interface{}) {
// If the value is nil then remove this key from the collection
if value == nil {
this.Remove(key)
return
}
if this.length == 0 {
this.root = &Node{0,nil,nil,nil,nil}
}
t := this.root
bs := []byte(key)
for i := 0; i < len(bs); {
b := bs[i]
if b > t.key {
if t.right == nil {
t.right = &Node{b,nil,nil,nil,nil}
}
t = t.right
} else if b < t.key {
if t.left == nil {
t.left = &Node{b,nil,nil,nil,nil}
}
t = t.left
} else {
i++
if i < len(bs) {
if t.middle == nil {
t.middle = &Node{bs[i],nil,nil,nil,nil}
}
t = t.middle
}
}
}
if t.value == nil {
this.length++
}
t.value = value
}
// Get the number of items stored in the tree
func (this *TernarySearchTree) Len() int {
return this.length
}
// Remove a key from the collection
func (this *TernarySearchTree) Remove(key string) interface{} {
if this.length == 0 {
return nil
}
var remove *Node
var direction int
t := this.root
bs := []byte(key)
for i := 0; i < len(bs); {
b := bs[i]
if b > t.key {
// Not in the collection
if t.right == nil {
return nil
}
// This is a branch so we have to keep it
remove = t
direction = 1
// Move to the next node
t = t.right
} else if b < t.key {
// Not in the collection
if t.left == nil {
return nil
}
// This is a branch so we have to keep it
remove = t
direction = -1
// Move to the next node
t = t.left
} else {
i++
if i < len(bs) {
// Not in the collection
if t.middle == nil {
return nil
}
// Has a value so we need to keep at least this much
if t.value != nil {
remove = t
direction = 0
}
// Move to the next node
t = t.middle
}
}
}
// If this was the only item in the tree, set the root pointer to nil
if this.length == 1 {
this.root = nil
} else {
if direction == -1 {
remove.left = nil
} else if direction == 0 {
remove.middle = nil
} else {
remove.right = nil
}
}
this.length--
return t.value
}
func (this *TernarySearchTree) String() string {
if this.length == 0 {
return "{}"
}
return this.root.String()
}
// Dump the tree to a string for easier debugging
func (this *Node) String() string {
str := "{" + string(this.key)
if this.value != nil {
str += ":" + fmt.Sprint(this.value)
}
if this.left != nil {
str += this.left.String()
} else {
str += " "
}
if this.middle != nil {
str += this.middle.String()
} else {
str += " "
}
if this.right != nil {
str += this.right.String()
} else {
str += " "
}
str += "}"
return str
}

View File

@@ -1,83 +0,0 @@
package tst
import (
//"fmt"
"math/rand"
"testing"
)
func randomString() string {
n := 3 + rand.Intn(10)
bs := make([]byte, n)
for i := 0; i<n; i++ {
bs[i] = byte(97 + rand.Intn(25))
}
return string(bs)
}
func Test(t *testing.T) {
tree := New()
tree.Insert("test", 1)
if tree.Len() != 1 {
t.Errorf("expecting len 1")
}
if !tree.Has("test") {
t.Errorf("expecting to find key=test")
}
tree.Insert("testing", 2)
tree.Insert("abcd", 0)
found := false
tree.Do(func(key string, val interface{})bool {
if key == "test" && val.(int) == 1 {
found = true
}
return true
})
if !found {
t.Errorf("expecting iterator to find test")
}
tree.Remove("testing")
tree.Remove("abcd")
v := tree.Remove("test")
if tree.Len() != 0 {
t.Errorf("expecting len 0")
}
if tree.Has("test") {
t.Errorf("expecting not to find key=test")
}
if v.(int) != 1 {
t.Errorf("expecting value=1")
}
}
func BenchmarkInsert(b *testing.B) {
b.StopTimer()
strs := make([]string, b.N)
for i := 0; i<b.N; i++ {
strs[i] = randomString()
}
b.StartTimer()
tree := New()
for i, str := range strs {
tree.Insert(str, i)
}
}
func BenchmarkMapInsert(b *testing.B) {
b.StopTimer()
strs := make([]string, b.N)
for i := 0; i<b.N; i++ {
strs[i] = randomString()
}
b.StartTimer()
m := make(map[string]int)
for i, str := range strs {
m[str] = i
}
}