pax_global_header00006660000000000000000000000064134504031610014507gustar00rootroot0000000000000052 comment=cc880e8d6c8863be5709e7dc952ac35a634db5ad golang-github-badgerodon-collections-0.0~git20130729.604e922/000077500000000000000000000000001345040316100231575ustar00rootroot00000000000000golang-github-badgerodon-collections-0.0~git20130729.604e922/LICENSE000066400000000000000000000020621345040316100241640ustar00rootroot00000000000000Copyright (c) 2012 Caleb Doxsey Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.golang-github-badgerodon-collections-0.0~git20130729.604e922/Readme.md000066400000000000000000000027141345040316100247020ustar00rootroot00000000000000# 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.golang-github-badgerodon-collections-0.0~git20130729.604e922/collections.go000066400000000000000000000006571345040316100260340ustar00rootroot00000000000000package 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] } golang-github-badgerodon-collections-0.0~git20130729.604e922/grid/000077500000000000000000000000001345040316100241045ustar00rootroot00000000000000golang-github-badgerodon-collections-0.0~git20130729.604e922/grid/grid.go000066400000000000000000000015161345040316100253630ustar00rootroot00000000000000package 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{}) { } golang-github-badgerodon-collections-0.0~git20130729.604e922/point.go000066400000000000000000000000741345040316100246400ustar00rootroot00000000000000package collections type ( Point struct { X, Y int } ) golang-github-badgerodon-collections-0.0~git20130729.604e922/queue/000077500000000000000000000000001345040316100243035ustar00rootroot00000000000000golang-github-badgerodon-collections-0.0~git20130729.604e922/queue/queue.go000066400000000000000000000020021345040316100257500ustar00rootroot00000000000000package queue type ( Queue struct { start, end *node length int } node struct { value interface{} next *node } ) // Create a new queue func New() *Queue { return &Queue{nil,nil,0} } // Take the next item off the front of the queue func (this *Queue) Dequeue() interface{} { if this.length == 0 { return nil } n := this.start if this.length == 1 { this.start = nil this.end = nil } else { this.start = this.start.next } this.length-- return n.value } // Put an item on the end of a queue func (this *Queue) Enqueue(value interface{}) { n := &node{value,nil} if this.length == 0 { this.start = n this.end = n } else { this.end.next = n this.end = n } this.length++ } // Return the number of items in the queue func (this *Queue) Len() int { return this.length } // Return the first item in the queue without removing it func (this *Queue) Peek() interface{} { if this.length == 0 { return nil } return this.start.value } golang-github-badgerodon-collections-0.0~git20130729.604e922/queue/queue_test.go000066400000000000000000000013601345040316100270150ustar00rootroot00000000000000package 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") } }golang-github-badgerodon-collections-0.0~git20130729.604e922/set/000077500000000000000000000000001345040316100237525ustar00rootroot00000000000000golang-github-badgerodon-collections-0.0~git20130729.604e922/set/set.go000077500000000000000000000040461345040316100251030ustar00rootroot00000000000000package 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} } golang-github-badgerodon-collections-0.0~git20130729.604e922/set/set_test.go000066400000000000000000000023311345040316100261320ustar00rootroot00000000000000package 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") } } golang-github-badgerodon-collections-0.0~git20130729.604e922/skip/000077500000000000000000000000001345040316100241255ustar00rootroot00000000000000golang-github-badgerodon-collections-0.0~git20130729.604e922/skip/skip.go000066400000000000000000000071421345040316100254260ustar00rootroot00000000000000package 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 } golang-github-badgerodon-collections-0.0~git20130729.604e922/skip/skip_test.go000066400000000000000000000013101345040316100264540ustar00rootroot00000000000000package 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") } } golang-github-badgerodon-collections-0.0~git20130729.604e922/splay/000077500000000000000000000000001345040316100243075ustar00rootroot00000000000000golang-github-badgerodon-collections-0.0~git20130729.604e922/splay/splay.go000066400000000000000000000176051345040316100257770ustar00rootroot00000000000000package 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 } golang-github-badgerodon-collections-0.0~git20130729.604e922/splay/splay_test.go000066400000000000000000000006161345040316100270300ustar00rootroot00000000000000package 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") } }golang-github-badgerodon-collections-0.0~git20130729.604e922/stack/000077500000000000000000000000001345040316100242645ustar00rootroot00000000000000golang-github-badgerodon-collections-0.0~git20130729.604e922/stack/stack.go000066400000000000000000000014421345040316100257210ustar00rootroot00000000000000package 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++ }golang-github-badgerodon-collections-0.0~git20130729.604e922/stack/stack_test.go000066400000000000000000000011671345040316100267640ustar00rootroot00000000000000package 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") } }golang-github-badgerodon-collections-0.0~git20130729.604e922/trie/000077500000000000000000000000001345040316100241225ustar00rootroot00000000000000golang-github-badgerodon-collections-0.0~git20130729.604e922/trie/trie.go000066400000000000000000000047411345040316100254220ustar00rootroot00000000000000package 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 }golang-github-badgerodon-collections-0.0~git20130729.604e922/trie/trie_test.go000066400000000000000000000010461345040316100264540ustar00rootroot00000000000000package 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") } }golang-github-badgerodon-collections-0.0~git20130729.604e922/tst/000077500000000000000000000000001345040316100237715ustar00rootroot00000000000000golang-github-badgerodon-collections-0.0~git20130729.604e922/tst/tst.go000066400000000000000000000131751345040316100251410ustar00rootroot00000000000000package 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 } golang-github-badgerodon-collections-0.0~git20130729.604e922/tst/tst_test.go000066400000000000000000000026661345040316100262030ustar00rootroot00000000000000package tst import ( //"fmt" "math/rand" "testing" ) func randomString() string { n := 3 + rand.Intn(10) bs := make([]byte, n) for i := 0; i