├── go.sum ├── trie ├── .gitignore ├── tst_node.go ├── tst.go └── tst_test.go ├── doc.go ├── go.mod ├── hashtable.test ├── .activate ├── .gitignore ├── types ├── map_entry.go ├── string.go ├── types.go ├── int.go └── util.go ├── heap ├── unique_test.go ├── unique.go ├── pq_test.go └── pq.go ├── set ├── setmap_test.go ├── example_serialize_test.go ├── ops.go ├── setmap.go ├── mapset_test.go ├── mapset.go ├── sortedset.go └── sortedset_test.go ├── test └── support.go ├── tree ├── avl │ ├── traversal_test.go │ ├── avltree_test.go │ ├── avltree.go │ └── imm_avltree.go ├── bptree │ ├── bpmap.go │ └── bptree.go └── util.go ├── linked ├── unique_test.go ├── linked_test.go ├── unique.go └── linked.go ├── cast_test.go ├── rand └── rand.go ├── pool └── pool.go ├── errors └── errors.go ├── list ├── fixed_test.go ├── sorted.go ├── sorted_test.go ├── array_list_test.go └── array_list.go ├── hashtable ├── linhash.go ├── hashtable.go └── hashtable_test.go ├── LICENSE └── exc ├── doc.go ├── README.md ├── exc_test.go ├── exception.go └── block.go /go.sum: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /trie/.gitignore: -------------------------------------------------------------------------------- 1 | *.dot 2 | *.png 3 | -------------------------------------------------------------------------------- /doc.go: -------------------------------------------------------------------------------- 1 | package data_structures 2 | 3 | // meta package 4 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/timtadh/data-structures 2 | 3 | go 1.18 4 | -------------------------------------------------------------------------------- /hashtable.test: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/timtadh/data-structures/HEAD/hashtable.test -------------------------------------------------------------------------------- /.activate: -------------------------------------------------------------------------------- 1 | export GOPATH=$(readlink -e $(pwd)/../../../..) 2 | export PATH=$GOPATH/bin:$PATH 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 2 | *.o 3 | *.a 4 | *.so 5 | 6 | # Folders 7 | _obj 8 | _test 9 | pkg 10 | bin 11 | 12 | # Architecture specific extensions/prefixes 13 | *.[568vq] 14 | [568vq].out 15 | 16 | *.cgo1.go 17 | *.cgo2.c 18 | _cgo_defun.c 19 | _cgo_gotypes.go 20 | _cgo_export.* 21 | 22 | _testmain.go 23 | 24 | # editor files 25 | *.swp 26 | *.swo 27 | 28 | -------------------------------------------------------------------------------- /types/map_entry.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | type MapEntry struct { 8 | Key Hashable 9 | Value interface{} 10 | } 11 | 12 | func (m *MapEntry) Equals(other Equatable) bool { 13 | if o, ok := other.(*MapEntry); ok { 14 | return m.Key.Equals(o.Key) 15 | } else { 16 | return m.Key.Equals(other) 17 | } 18 | } 19 | 20 | func (m *MapEntry) Less(other Sortable) bool { 21 | if o, ok := other.(*MapEntry); ok { 22 | return m.Key.Less(o.Key) 23 | } else { 24 | return m.Key.Less(other) 25 | } 26 | } 27 | 28 | func (m *MapEntry) Hash() int { 29 | return m.Key.Hash() 30 | } 31 | 32 | func (m *MapEntry) String() string { 33 | return fmt.Sprintf("", m.Key, m.Value) 34 | } 35 | -------------------------------------------------------------------------------- /heap/unique_test.go: -------------------------------------------------------------------------------- 1 | package heap 2 | 3 | import "testing" 4 | 5 | import ( 6 | "github.com/timtadh/data-structures/test" 7 | "github.com/timtadh/data-structures/types" 8 | ) 9 | 10 | func TestUniquePushMax(x *testing.T) { 11 | t := (*test.T)(x) 12 | h := NewUnique(NewHeap(12, false)) 13 | h.Push(18, types.String("g")) 14 | h.Push(3, types.String("g")) 15 | h.Push(5, types.String("g")) 16 | h.Push(7, types.String("e")) 17 | h.Push(3, types.String("i")) 18 | h.Push(6, types.String("a")) 19 | h.Push(25, types.String("x")) 20 | h.Push(22, types.String("t")) 21 | h.Push(14, types.String("n")) 22 | h.Push(8, types.String("b")) 23 | h.Push(19, types.String("m")) 24 | h.Push(9, types.String("r")) 25 | h.Push(20, types.String("o")) 26 | h.Push(16, types.String("s")) 27 | t.Log(h.pq) 28 | t.AssertNil(h.pq.(*Heap).Verify()) 29 | t.Assert(h.pq.(*Heap).list[3].item.(types.String) == "g", "heap[3] != {g 18} %v", h.pq.(*Heap).list[3]) 30 | t.Assert(h.pq.(*Heap).list[3].priority == 18, "heap[3] != {g 18} %v", h.pq.(*Heap).list[3]) 31 | } 32 | -------------------------------------------------------------------------------- /set/setmap_test.go: -------------------------------------------------------------------------------- 1 | package set 2 | 3 | import "testing" 4 | 5 | import ( 6 | "fmt" 7 | ) 8 | 9 | import ( 10 | "github.com/timtadh/data-structures/hashtable" 11 | "github.com/timtadh/data-structures/types" 12 | ) 13 | 14 | func TestNewSetMap(t *testing.T) { 15 | s := types.Set(NewSetMap(hashtable.NewLinearHash())) 16 | t.Log(s.Size()) 17 | } 18 | 19 | func TestSetMapAddHasDelete(x *testing.T) { 20 | t := (*T)(x) 21 | SIZE := 100 22 | set := NewSortedSet(10) 23 | items := make([]types.Int, 0, SIZE) 24 | for i := 0; i < SIZE; i++ { 25 | item := types.Int(rand.Intn(1000)) 26 | for set.Has(item) { 27 | item = types.Int(rand.Intn(1000)) 28 | } 29 | items = append(items, item) 30 | t.assert_nil(set.Add(item)) 31 | } 32 | for i, item := range items { 33 | t.assert(fmt.Sprintf("i %v, !set.Has(item)", i), set.Has(item)) 34 | } 35 | for _, item := range items { 36 | t.assert_nil(set.Delete(item)) 37 | } 38 | for i, item := range items { 39 | t.assert(fmt.Sprintf("i %v, !set.Has(item)", i), !set.Has(item)) 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /test/support.go: -------------------------------------------------------------------------------- 1 | package test 2 | 3 | import ( 4 | "runtime/debug" 5 | "testing" 6 | 7 | crand "crypto/rand" 8 | "encoding/binary" 9 | "encoding/hex" 10 | mrand "math/rand" 11 | 12 | trand "github.com/timtadh/data-structures/rand" 13 | ) 14 | 15 | var rand *mrand.Rand 16 | 17 | func init() { 18 | seed := make([]byte, 8) 19 | if _, err := crand.Read(seed); err == nil { 20 | rand = trand.ThreadSafeRand(int64(binary.BigEndian.Uint64(seed))) 21 | } else { 22 | panic(err) 23 | } 24 | } 25 | 26 | type T testing.T 27 | 28 | func (t *T) Assert(ok bool, msg string, vars ...interface{}) { 29 | if !ok { 30 | t.Log("\n" + string(debug.Stack())) 31 | t.Fatalf(msg, vars...) 32 | } 33 | } 34 | 35 | func (t *T) AssertNil(errors ...error) { 36 | any := false 37 | for _, err := range errors { 38 | if err != nil { 39 | any = true 40 | t.Log("\n" + string(debug.Stack())) 41 | t.Error(err) 42 | } 43 | } 44 | if any { 45 | t.Fatal("assert failed") 46 | } 47 | } 48 | 49 | func RandSlice(length int) []byte { 50 | slice := make([]byte, length) 51 | if _, err := crand.Read(slice); err != nil { 52 | panic(err) 53 | } 54 | return slice 55 | } 56 | 57 | func RandHex(length int) string { 58 | return hex.EncodeToString(RandSlice(length / 2)) 59 | } 60 | 61 | func RandStr(length int) string { 62 | return string(RandSlice(length)) 63 | } 64 | -------------------------------------------------------------------------------- /set/example_serialize_test.go: -------------------------------------------------------------------------------- 1 | package set_test 2 | 3 | import ( 4 | "log" 5 | ) 6 | 7 | import ( 8 | "github.com/timtadh/data-structures/list" 9 | "github.com/timtadh/data-structures/set" 10 | "github.com/timtadh/data-structures/types" 11 | ) 12 | 13 | func makeSet() *set.SortedSet { 14 | return set.FromSlice([]types.Hashable{types.Int(1), types.Int(-1), types.Int(3)}) 15 | } 16 | 17 | func serialize(s *set.SortedSet) ([]byte, error) { 18 | marshal, unmarshal := types.IntMarshals() 19 | m := set.NewMSortedSet(s, marshal, unmarshal) 20 | return m.MarshalBinary() 21 | } 22 | 23 | func deserialize(bytes []byte) (*set.SortedSet, error) { 24 | marshal, unmarshal := types.IntMarshals() 25 | m := &set.MSortedSet{MSorted: list.MSorted{MList: list.MList{MarshalItem: marshal, UnmarshalItem: unmarshal}}} 26 | err := m.UnmarshalBinary(bytes) 27 | if err != nil { 28 | return nil, err 29 | } 30 | return m.SortedSet(), nil 31 | } 32 | 33 | func Example_serialize() { 34 | a := makeSet() 35 | b := makeSet() 36 | if !a.Equals(b) { 37 | log.Panic("a was not equal to b") 38 | } 39 | bytes, err := serialize(a) 40 | if err != nil { 41 | log.Panic(err) 42 | } 43 | log.Println(bytes) 44 | c, err := deserialize(bytes) 45 | if err != nil { 46 | log.Panic(err) 47 | } 48 | if !c.Equals(b) { 49 | log.Panic("c was not equal to b") 50 | } 51 | log.Println("success") 52 | } 53 | -------------------------------------------------------------------------------- /types/string.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "bytes" 5 | "hash/fnv" 6 | ) 7 | 8 | type String string 9 | type ByteSlice []byte 10 | 11 | func (self *String) MarshalBinary() ([]byte, error) { 12 | return []byte(*self), nil 13 | } 14 | 15 | func (self *String) UnmarshalBinary(data []byte) error { 16 | *self = String(data) 17 | return nil 18 | } 19 | 20 | func (self String) Equals(other Equatable) bool { 21 | if o, ok := other.(String); ok { 22 | return self == o 23 | } else { 24 | return false 25 | } 26 | } 27 | 28 | func (self String) Less(other Sortable) bool { 29 | if o, ok := other.(String); ok { 30 | return self < o 31 | } else { 32 | return false 33 | } 34 | } 35 | 36 | func (self String) Hash() int { 37 | h := fnv.New32a() 38 | h.Write([]byte(string(self))) 39 | return int(h.Sum32()) 40 | } 41 | 42 | func (self *ByteSlice) MarshalBinary() ([]byte, error) { 43 | return []byte(*self), nil 44 | } 45 | 46 | func (self *ByteSlice) UnmarshalBinary(data []byte) error { 47 | *self = ByteSlice(data) 48 | return nil 49 | } 50 | 51 | func (self ByteSlice) Equals(other Equatable) bool { 52 | if o, ok := other.(ByteSlice); ok { 53 | return bytes.Equal(self, o) 54 | } else { 55 | return false 56 | } 57 | } 58 | 59 | func (self ByteSlice) Less(other Sortable) bool { 60 | if o, ok := other.(ByteSlice); ok { 61 | return bytes.Compare(self, o) < 0 // -1 if a < b 62 | } else { 63 | return false 64 | } 65 | } 66 | 67 | func (self ByteSlice) Hash() int { 68 | h := fnv.New32a() 69 | h.Write([]byte(self)) 70 | return int(h.Sum32()) 71 | } 72 | -------------------------------------------------------------------------------- /tree/avl/traversal_test.go: -------------------------------------------------------------------------------- 1 | package avl 2 | 3 | import "testing" 4 | 5 | import ( 6 | "github.com/timtadh/data-structures/tree" 7 | "github.com/timtadh/data-structures/types" 8 | ) 9 | 10 | func TestTraversals(t *testing.T) { 11 | var data []int = []int{ 12 | 1, 5, 7, 9, 12, 13, 17, 18, 19, 20, 13 | } 14 | var order []int = []int{ 15 | 6, 1, 8, 2, 4, 9, 5, 7, 0, 3, 16 | } 17 | var preorder []int = []int{ 18 | 17, 7, 5, 1, 12, 9, 13, 19, 18, 20, 19 | } 20 | var postorder []int = []int{ 21 | 1, 5, 9, 13, 12, 7, 18, 20, 19, 17, 22 | } 23 | 24 | test := func(T types.TreeMap) { 25 | t.Logf("%T", T) 26 | for j := range order { 27 | if err := T.Put(types.Int(data[order[j]]), order[j]); err != nil { 28 | t.Error(err) 29 | } 30 | } 31 | 32 | j := 0 33 | for tn, next := tree.TraverseBinaryTreeInOrder(T.Root().(types.BinaryTreeNode))(); next != nil; tn, next = next() { 34 | if int(tn.Key().(types.Int)) != data[j] { 35 | t.Error("key in wrong spot in-order") 36 | } 37 | j += 1 38 | } 39 | 40 | j = 0 41 | for tn, next := tree.TraverseTreePreOrder(T.Root())(); next != nil; tn, next = next() { 42 | if int(tn.Key().(types.Int)) != preorder[j] { 43 | t.Error("key in wrong spot pre-order") 44 | } 45 | j += 1 46 | } 47 | 48 | j = 0 49 | for tn, next := tree.TraverseTreePostOrder(T.Root())(); next != nil; tn, next = next() { 50 | if int(tn.Key().(types.Int)) != postorder[j] { 51 | t.Error("key in wrong spot post-order") 52 | } 53 | j += 1 54 | } 55 | } 56 | test(NewAvlTree()) 57 | test(NewImmutableAvlTree()) 58 | } 59 | -------------------------------------------------------------------------------- /heap/unique.go: -------------------------------------------------------------------------------- 1 | package heap 2 | 3 | import ( 4 | "github.com/timtadh/data-structures/hashtable" 5 | "github.com/timtadh/data-structures/set" 6 | "github.com/timtadh/data-structures/types" 7 | ) 8 | 9 | // This priority queue only allows unique entries. Internally this is 10 | // implemented using a Hash set. All items added must be types.Hashable 11 | type UniquePQ struct { 12 | pq PriorityQueue 13 | set *set.SetMap 14 | } 15 | 16 | // Construct a new unique priority queue using the provided priority queue. 17 | func NewUnique(pq PriorityQueue) *UniquePQ { 18 | return &UniquePQ{ 19 | pq: pq, 20 | set: set.NewSetMap(hashtable.NewLinearHash()), 21 | } 22 | } 23 | 24 | // How many items in the queue? 25 | func (u *UniquePQ) Size() int { 26 | return u.pq.Size() 27 | } 28 | 29 | // Add an item to the priority queue. It must be hashable. 30 | func (u *UniquePQ) Add(priority int, item types.Hashable) { 31 | if !u.set.Has(item) { 32 | u.set.Add(item) 33 | u.pq.Push(priority, item) 34 | } 35 | } 36 | 37 | // This method is provided so it implements the PriorityQueue interface. In 38 | // reality item must be types.Hashable. The implementation simply does a type 39 | // assertion on item and calls Add. 40 | func (u *UniquePQ) Push(priority int, item interface{}) { 41 | u.Add(priority, item.(types.Hashable)) 42 | } 43 | 44 | // Get the top element 45 | func (u *UniquePQ) Peek() interface{} { 46 | return u.pq.Peek() 47 | } 48 | 49 | // Get and remove the top element 50 | func (u *UniquePQ) Pop() interface{} { 51 | item := u.pq.Pop().(types.Hashable) 52 | u.set.Delete(item) 53 | return item 54 | } 55 | -------------------------------------------------------------------------------- /linked/unique_test.go: -------------------------------------------------------------------------------- 1 | package linked 2 | 3 | import "testing" 4 | 5 | import ( 6 | "github.com/timtadh/data-structures/list" 7 | ) 8 | 9 | func TestUniquePushPopSize(t *testing.T) { 10 | al := list.New(10) 11 | ll := NewUniqueDeque() 12 | for i := 0; i < 10; i++ { 13 | ll.Push(randhex(4)) 14 | ll.Push(ll.Last()) 15 | al.Push(ll.Last()) 16 | } 17 | if !ll.Equals(al) { 18 | t.Fatalf("ll != al, %v != %v", ll, al) 19 | } 20 | t.Logf("ll %v", ll) 21 | t.Logf("al %v", al) 22 | for i := 0; i < 10; i++ { 23 | llItem, err := ll.Pop() 24 | if err != nil { 25 | t.Fatal(err) 26 | } 27 | alItem, err := al.Pop() 28 | if err != nil { 29 | t.Fatal(err) 30 | } 31 | if !alItem.Equals(llItem) { 32 | t.Fatalf("llItem != alItem, %v != %v", llItem, alItem) 33 | } 34 | } 35 | if !ll.Equals(al) { 36 | t.Fatalf("ll != al, %v != %v", ll, al) 37 | } 38 | } 39 | 40 | func TestUniqueFrontPushPopSize(t *testing.T) { 41 | al := list.New(10) 42 | ll := NewUniqueDeque() 43 | for i := 0; i < 10; i++ { 44 | ll.EnqueFront(randhex(4)) 45 | ll.EnqueFront(ll.First()) 46 | al.Insert(0, ll.First()) 47 | } 48 | if !ll.Equals(al) { 49 | t.Fatalf("ll != al, %v != %v", ll, al) 50 | } 51 | for i := 0; i < 10; i++ { 52 | llItem, err := ll.DequeFront() 53 | if err != nil { 54 | t.Fatal(err) 55 | } 56 | alItem, err := al.Get(0) 57 | if err != nil { 58 | t.Fatal(err) 59 | } 60 | err = al.Remove(0) 61 | if err != nil { 62 | t.Fatal(err) 63 | } 64 | if !alItem.Equals(llItem) { 65 | t.Fatalf("llItem != alItem, %v != %v", llItem, alItem) 66 | } 67 | } 68 | if !ll.Equals(al) { 69 | t.Fatalf("ll != al, %v != %v", ll, al) 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /cast_test.go: -------------------------------------------------------------------------------- 1 | package data_structures 2 | 3 | import "testing" 4 | import ( 5 | "github.com/timtadh/data-structures/hashtable" 6 | "github.com/timtadh/data-structures/list" 7 | "github.com/timtadh/data-structures/set" 8 | "github.com/timtadh/data-structures/tree/avl" 9 | "github.com/timtadh/data-structures/tree/bptree" 10 | "github.com/timtadh/data-structures/trie" 11 | "github.com/timtadh/data-structures/types" 12 | ) 13 | 14 | func TestAvlTreeCast(t *testing.T) { 15 | tree := avl.NewAvlTree() 16 | _ = types.TreeMap(tree) 17 | } 18 | 19 | func TestImmutableAvlTreeCast(t *testing.T) { 20 | tree := avl.NewImmutableAvlTree() 21 | _ = types.TreeMap(tree) 22 | } 23 | 24 | func TestHashtableCast(t *testing.T) { 25 | hash := hashtable.NewHashTable(16) 26 | _ = types.Sized(hash) 27 | _ = types.MapIterable(hash) 28 | _ = types.MapOperable(hash) 29 | _ = types.Map(hash) 30 | } 31 | 32 | func TestLinearHashtableCast(t *testing.T) { 33 | hash := hashtable.NewLinearHash() 34 | _ = types.Sized(hash) 35 | _ = types.MapIterable(hash) 36 | _ = types.MapOperable(hash) 37 | _ = types.Map(hash) 38 | } 39 | 40 | func TestTSTCast(t *testing.T) { 41 | tst := new(trie.TST) 42 | _ = types.MapIterable(tst) 43 | } 44 | 45 | func TestBpTreeCast(t *testing.T) { 46 | bpt := bptree.NewBpTree(17) 47 | _ = types.MapIterable(bpt) 48 | _ = types.MultiMapOperable(bpt) 49 | _ = types.MultiMap(bpt) 50 | } 51 | 52 | func TestListCast(t *testing.T) { 53 | s := list.New(17) 54 | _ = types.Hashable(s) 55 | _ = types.List(s) 56 | } 57 | 58 | func TestSortedCast(t *testing.T) { 59 | s := list.NewSorted(17, false) 60 | _ = types.Hashable(s) 61 | _ = types.OrderedList(s) 62 | } 63 | 64 | func TestSetCast(t *testing.T) { 65 | s := set.NewSortedSet(17) 66 | _ = types.Set(s) 67 | _ = types.Hashable(s) 68 | } 69 | -------------------------------------------------------------------------------- /rand/rand.go: -------------------------------------------------------------------------------- 1 | package rand 2 | 3 | import ( 4 | "math/rand" 5 | "sync" 6 | ) 7 | 8 | // ThreadSafeRand provides a thread safe version of math/rand.Rand using 9 | // the same technique used in the math/rand package to make the top level 10 | // functions thread safe. 11 | func ThreadSafeRand(seed int64) *rand.Rand { 12 | return rand.New(&lockedSource{src: rand.NewSource(seed).(rand.Source64)}) 13 | } 14 | 15 | // from: https://golang.org/src/math/rand/rand.go?s=8161:8175#L317 16 | type lockedSource struct { 17 | lk sync.Mutex 18 | src rand.Source64 19 | } 20 | 21 | func (r *lockedSource) Int63() (n int64) { 22 | r.lk.Lock() 23 | n = r.src.Int63() 24 | r.lk.Unlock() 25 | return 26 | } 27 | 28 | func (r *lockedSource) Uint64() (n uint64) { 29 | r.lk.Lock() 30 | n = r.src.Uint64() 31 | r.lk.Unlock() 32 | return 33 | } 34 | 35 | func (r *lockedSource) Seed(seed int64) { 36 | r.lk.Lock() 37 | r.src.Seed(seed) 38 | r.lk.Unlock() 39 | } 40 | 41 | // seedPos implements Seed for a lockedSource without a race condiiton. 42 | func (r *lockedSource) seedPos(seed int64, readPos *int8) { 43 | r.lk.Lock() 44 | r.src.Seed(seed) 45 | *readPos = 0 46 | r.lk.Unlock() 47 | } 48 | 49 | // read implements Read for a lockedSource without a race condition. 50 | func (r *lockedSource) read(p []byte, readVal *int64, readPos *int8) (n int, err error) { 51 | r.lk.Lock() 52 | n, err = read(p, r.src.Int63, readVal, readPos) 53 | r.lk.Unlock() 54 | return 55 | } 56 | 57 | func read(p []byte, int63 func() int64, readVal *int64, readPos *int8) (n int, err error) { 58 | pos := *readPos 59 | val := *readVal 60 | for n = 0; n < len(p); n++ { 61 | if pos == 0 { 62 | val = int63() 63 | pos = 7 64 | } 65 | p[n] = byte(val) 66 | val >>= 8 67 | pos-- 68 | } 69 | *readPos = pos 70 | *readVal = val 71 | return 72 | } 73 | -------------------------------------------------------------------------------- /tree/bptree/bpmap.go: -------------------------------------------------------------------------------- 1 | package bptree 2 | 3 | import ( 4 | "github.com/timtadh/data-structures/errors" 5 | "github.com/timtadh/data-structures/types" 6 | ) 7 | 8 | /* A BpMap is a B+Tree with support for duplicate keys disabled. This makes it 9 | * behave like a regular Map rather than a MultiMap. 10 | */ 11 | type BpMap BpTree 12 | 13 | func NewBpMap(node_size int) *BpMap { 14 | return &BpMap{ 15 | root: NewLeaf(node_size, true), 16 | size: 0, 17 | } 18 | } 19 | 20 | func (self *BpMap) Size() int { 21 | return (*BpTree)(self).Size() 22 | } 23 | 24 | func (self *BpMap) Has(key types.Hashable) bool { 25 | return (*BpTree)(self).Has(key) 26 | } 27 | 28 | func (self *BpMap) Put(key types.Hashable, value interface{}) (err error) { 29 | had := self.Has(key) 30 | new_root, err := self.root.put(key, value) 31 | if err != nil { 32 | return err 33 | } 34 | self.root = new_root 35 | if !had { 36 | self.size += 1 37 | } 38 | return nil 39 | } 40 | 41 | func (self *BpMap) Get(key types.Hashable) (value interface{}, err error) { 42 | j, l := self.root.get_start(key) 43 | if l.keys[j].Equals(key) { 44 | return l.values[j], nil 45 | } 46 | return nil, errors.NotFound(key) 47 | } 48 | 49 | func (self *BpMap) Remove(key types.Hashable) (value interface{}, err error) { 50 | value, err = self.Get(key) 51 | if err != nil { 52 | return nil, err 53 | } 54 | ns := self.root.NodeSize() 55 | new_root, err := self.root.remove(key, func(value interface{}) bool { return true }) 56 | if err != nil { 57 | return nil, err 58 | } 59 | if new_root == nil { 60 | self.root = NewLeaf(ns, true) 61 | } else { 62 | self.root = new_root 63 | } 64 | self.size-- 65 | return value, nil 66 | } 67 | 68 | func (self *BpMap) Keys() (ki types.KIterator) { 69 | return (*BpTree)(self).Keys() 70 | } 71 | 72 | func (self *BpMap) Values() (vi types.Iterator) { 73 | return (*BpTree)(self).Values() 74 | } 75 | 76 | func (self *BpMap) Iterate() (kvi types.KVIterator) { 77 | return (*BpTree)(self).Iterate() 78 | } 79 | -------------------------------------------------------------------------------- /set/ops.go: -------------------------------------------------------------------------------- 1 | package set 2 | 3 | import ( 4 | "github.com/timtadh/data-structures/hashtable" 5 | "github.com/timtadh/data-structures/types" 6 | ) 7 | 8 | func newSetBestType(a types.Set, sizeHint int) types.Set { 9 | switch a.(type) { 10 | case *MapSet: 11 | return NewMapSet(NewSortedSet(sizeHint)) 12 | case *SortedSet: 13 | return NewSortedSet(sizeHint) 14 | case *SetMap: 15 | return NewSetMap(hashtable.NewLinearHash()) 16 | default: 17 | return NewSortedSet(sizeHint) 18 | } 19 | } 20 | 21 | func Union(a, b types.Set) (types.Set, error) { 22 | c := newSetBestType(a, a.Size()+b.Size()) 23 | err := c.Extend(a.Items()) 24 | if err != nil { 25 | return nil, err 26 | } 27 | err = c.Extend(b.Items()) 28 | if err != nil { 29 | return nil, err 30 | } 31 | return c, nil 32 | } 33 | 34 | func Intersect(a, b types.Set) (types.Set, error) { 35 | c := newSetBestType(a, a.Size()+b.Size()) 36 | for item, next := a.Items()(); next != nil; item, next = next() { 37 | if b.Has(item) { 38 | err := c.Add(item) 39 | if err != nil { 40 | return nil, err 41 | } 42 | } 43 | } 44 | return c, nil 45 | } 46 | 47 | // Unions s with o and returns a new Sorted Set 48 | func Subtract(a, b types.Set) (types.Set, error) { 49 | c := newSetBestType(a, a.Size()+b.Size()) 50 | for item, next := a.Items()(); next != nil; item, next = next() { 51 | if !b.Has(item) { 52 | err := c.Add(item) 53 | if err != nil { 54 | return nil, err 55 | } 56 | } 57 | } 58 | return c, nil 59 | } 60 | 61 | func Subset(a, b types.Set) bool { 62 | if a.Size() > b.Size() { 63 | return false 64 | } 65 | for item, next := a.Items()(); next != nil; item, next = next() { 66 | if !b.Has(item) { 67 | return false 68 | } 69 | } 70 | return true 71 | } 72 | 73 | func ProperSubset(a, b types.Set) bool { 74 | if a.Size() >= b.Size() { 75 | return false 76 | } 77 | return Subset(a, b) 78 | } 79 | 80 | func Superset(a, b types.Set) bool { 81 | return Subset(b, a) 82 | } 83 | 84 | func ProperSuperset(a, b types.Set) bool { 85 | return ProperSubset(b, a) 86 | } 87 | -------------------------------------------------------------------------------- /set/setmap.go: -------------------------------------------------------------------------------- 1 | package set 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | 7 | "github.com/timtadh/data-structures/errors" 8 | "github.com/timtadh/data-structures/types" 9 | ) 10 | 11 | type SetMap struct { 12 | types.Map 13 | } 14 | 15 | func NewSetMap(m types.Map) *SetMap { 16 | return &SetMap{m} 17 | } 18 | 19 | func (s *SetMap) String() string { 20 | if s.Size() <= 0 { 21 | return "{}" 22 | } 23 | items := make([]string, 0, s.Size()) 24 | for item, next := s.Items()(); next != nil; item, next = next() { 25 | items = append(items, fmt.Sprintf("%v", item)) 26 | } 27 | return "{" + strings.Join(items, ", ") + "}" 28 | } 29 | 30 | func (s *SetMap) Items() types.KIterator { 31 | return s.Keys() 32 | } 33 | 34 | // unimplemented 35 | func (s *SetMap) Item(item types.Hashable) (types.Hashable, error) { 36 | return nil, errors.Errorf("un-implemented") 37 | } 38 | 39 | // unimplemented 40 | func (s *SetMap) Equals(o types.Equatable) bool { 41 | panic(errors.Errorf("un-implemented")) 42 | } 43 | 44 | func (s *SetMap) Add(item types.Hashable) (err error) { 45 | return s.Put(item, nil) 46 | } 47 | 48 | func (s *SetMap) Delete(item types.Hashable) (err error) { 49 | _, err = s.Remove(item) 50 | return err 51 | } 52 | 53 | func (s *SetMap) Extend(items types.KIterator) (err error) { 54 | for item, next := items(); next != nil; item, next = next() { 55 | err := s.Add(item) 56 | if err != nil { 57 | return err 58 | } 59 | } 60 | return nil 61 | } 62 | 63 | // Unions s with o and returns a new SetMap (with a LinearHash) 64 | func (s *SetMap) Union(other types.Set) (types.Set, error) { 65 | return Union(s, other) 66 | } 67 | 68 | // Unions s with o and returns a new SetMap (with a LinearHash) 69 | func (s *SetMap) Intersect(other types.Set) (types.Set, error) { 70 | return Intersect(s, other) 71 | } 72 | 73 | // Unions s with o and returns a new SetMap (with a LinearHash) 74 | func (s *SetMap) Subtract(other types.Set) (types.Set, error) { 75 | return Subtract(s, other) 76 | } 77 | 78 | // Is s a subset of o? 79 | func (s *SetMap) Subset(o types.Set) bool { 80 | return Subset(s, o) 81 | } 82 | 83 | // Is s a proper subset of o? 84 | func (s *SetMap) ProperSubset(o types.Set) bool { 85 | return ProperSubset(s, o) 86 | } 87 | 88 | // Is s a superset of o? 89 | func (s *SetMap) Superset(o types.Set) bool { 90 | return Superset(s, o) 91 | } 92 | 93 | // Is s a proper superset of o? 94 | func (s *SetMap) ProperSuperset(o types.Set) bool { 95 | return ProperSuperset(s, o) 96 | } 97 | -------------------------------------------------------------------------------- /pool/pool.go: -------------------------------------------------------------------------------- 1 | package pool 2 | 3 | import ( 4 | "sync" 5 | "math/rand" 6 | ) 7 | 8 | import ( 9 | "github.com/timtadh/data-structures/errors" 10 | ) 11 | 12 | type Pool struct { 13 | workers []*worker 14 | wg sync.WaitGroup 15 | workin int 16 | workCond *sync.Cond 17 | mu sync.RWMutex 18 | } 19 | 20 | func New(n int) *Pool { 21 | pool := &Pool{ 22 | workers: make([]*worker, 0, n), 23 | workCond: sync.NewCond(&sync.Mutex{}), 24 | } 25 | for i := 0; i < n; i++ { 26 | w := &worker{ 27 | in: make(chan func(), 100), 28 | wg: &pool.wg, 29 | workin: &pool.workin, 30 | workCond: pool.workCond, 31 | } 32 | go w.work() 33 | pool.workers = append(pool.workers, w) 34 | } 35 | return pool 36 | } 37 | 38 | func (p *Pool) WaitCount() int { 39 | p.workCond.L.Lock() 40 | if p.workin <= 0 { 41 | n := p.workin 42 | p.workCond.L.Unlock() 43 | return n 44 | } 45 | p.workCond.Wait() 46 | n := p.workin 47 | p.workCond.L.Unlock() 48 | return n 49 | } 50 | 51 | func (p *Pool) WaitLock() { 52 | p.mu.Lock() 53 | p.workCond.L.Lock() 54 | for p.workin > 0 { 55 | p.workCond.Wait() 56 | } 57 | } 58 | 59 | func (p *Pool) Unlock() { 60 | p.workCond.L.Unlock() 61 | p.mu.Unlock() 62 | } 63 | 64 | func (p *Pool) Stop() { 65 | p.mu.Lock() 66 | if len(p.workers) == 0 { 67 | p.mu.Unlock() 68 | return 69 | } 70 | workers := p.workers 71 | p.workers = nil 72 | p.mu.Unlock() 73 | for _, wrkr := range workers { 74 | close(wrkr.in) 75 | } 76 | p.wg.Wait() 77 | } 78 | 79 | // This will only return an error if the pool is stopped 80 | func (p *Pool) Do(f func()) error { 81 | p.mu.RLock() 82 | defer p.mu.RUnlock() 83 | if len(p.workers) <= 0 { 84 | return errors.Errorf("The pool was stopped") 85 | } 86 | p.workCond.L.Lock() 87 | p.workin += 1 88 | p.workCond.L.Unlock() 89 | offset := rand.Intn(len(p.workers)) 90 | for i := 0; i < len(p.workers); i++ { 91 | j := (offset + i) % len(p.workers) 92 | wrkr := p.workers[j].in 93 | select { 94 | case wrkr<-f: 95 | return nil 96 | default: 97 | } 98 | } 99 | p.workers[offset].in<-f 100 | return nil 101 | } 102 | 103 | type worker struct { 104 | in chan func() 105 | wg *sync.WaitGroup 106 | workin *int 107 | workCond *sync.Cond 108 | } 109 | 110 | func (w *worker) work() { 111 | w.wg.Add(1) 112 | for f := range w.in { 113 | f() 114 | w.workCond.L.Lock() 115 | *w.workin -= 1 116 | w.workCond.L.Unlock() 117 | w.workCond.Broadcast() 118 | } 119 | w.wg.Done() 120 | } 121 | -------------------------------------------------------------------------------- /linked/linked_test.go: -------------------------------------------------------------------------------- 1 | package linked 2 | 3 | import ( 4 | "testing" 5 | 6 | crand "crypto/rand" 7 | "encoding/binary" 8 | "encoding/hex" 9 | mrand "math/rand" 10 | 11 | "github.com/timtadh/data-structures/list" 12 | trand "github.com/timtadh/data-structures/rand" 13 | "github.com/timtadh/data-structures/types" 14 | ) 15 | 16 | var rand *mrand.Rand 17 | 18 | func init() { 19 | seed := make([]byte, 8) 20 | if _, err := crand.Read(seed); err == nil { 21 | rand = trand.ThreadSafeRand(int64(binary.BigEndian.Uint64(seed))) 22 | } else { 23 | panic(err) 24 | } 25 | } 26 | 27 | func randstr(length int) types.String { 28 | slice := make([]byte, length) 29 | if _, err := crand.Read(slice); err != nil { 30 | panic(err) 31 | } 32 | return types.String(slice) 33 | } 34 | 35 | func randhex(length int) types.String { 36 | slice := make([]byte, length/2) 37 | if _, err := crand.Read(slice); err != nil { 38 | panic(err) 39 | } 40 | return types.String(hex.EncodeToString(slice)) 41 | } 42 | 43 | func TestEquals(t *testing.T) { 44 | al := list.New(10) 45 | ll := New() 46 | for i := 0; i < 10; i++ { 47 | ll.Push(randhex(4)) 48 | al.Push(ll.Last()) 49 | } 50 | if !ll.Equals(al) { 51 | t.Fatalf("ll != al, %v != %v", ll, al) 52 | } 53 | t.Logf("ll %v", ll) 54 | t.Logf("al %v", ll) 55 | } 56 | 57 | func TestPushPopSize(t *testing.T) { 58 | al := list.New(10) 59 | ll := New() 60 | for i := 0; i < 10; i++ { 61 | ll.Push(randhex(4)) 62 | al.Push(ll.Last()) 63 | } 64 | if !ll.Equals(al) { 65 | t.Fatalf("ll != al, %v != %v", ll, al) 66 | } 67 | for i := 0; i < 10; i++ { 68 | llItem, err := ll.Pop() 69 | if err != nil { 70 | t.Fatal(err) 71 | } 72 | alItem, err := al.Pop() 73 | if err != nil { 74 | t.Fatal(err) 75 | } 76 | if !alItem.Equals(llItem) { 77 | t.Fatalf("llItem != alItem, %v != %v", llItem, alItem) 78 | } 79 | } 80 | if !ll.Equals(al) { 81 | t.Fatalf("ll != al, %v != %v", ll, al) 82 | } 83 | } 84 | 85 | func TestFrontPushPopSize(t *testing.T) { 86 | al := list.New(10) 87 | ll := New() 88 | for i := 0; i < 10; i++ { 89 | ll.EnqueFront(randhex(4)) 90 | al.Insert(0, ll.First()) 91 | } 92 | if !ll.Equals(al) { 93 | t.Fatalf("ll != al, %v != %v", ll, al) 94 | } 95 | for i := 0; i < 10; i++ { 96 | llItem, err := ll.DequeFront() 97 | if err != nil { 98 | t.Fatal(err) 99 | } 100 | alItem, err := al.Get(0) 101 | if err != nil { 102 | t.Fatal(err) 103 | } 104 | err = al.Remove(0) 105 | if err != nil { 106 | t.Fatal(err) 107 | } 108 | if !alItem.Equals(llItem) { 109 | t.Fatalf("llItem != alItem, %v != %v", llItem, alItem) 110 | } 111 | } 112 | if !ll.Equals(al) { 113 | t.Fatalf("ll != al, %v != %v", ll, al) 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /heap/pq_test.go: -------------------------------------------------------------------------------- 1 | package heap 2 | 3 | import "testing" 4 | 5 | import ( 6 | "github.com/timtadh/data-structures/test" 7 | ) 8 | 9 | func heap1(min bool) *Heap { 10 | h := NewHeap(12, min) 11 | if min { 12 | h.list = []entry{ 13 | {"x", 3}, 14 | {"t", 7}, 15 | {"o", 5}, 16 | {"g", 18}, 17 | {"s", 16}, 18 | {"m", 19}, 19 | {"n", 14}, 20 | {"b", 28}, 21 | {"e", 27}, 22 | {"r", 29}, 23 | {"a", 26}, 24 | {"i", 23}, 25 | } 26 | } else { 27 | h.list = []entry{ 28 | {"x", 25}, 29 | {"t", 22}, 30 | {"o", 20}, 31 | {"g", 18}, 32 | {"s", 16}, 33 | {"m", 19}, 34 | {"n", 14}, 35 | {"b", 8}, 36 | {"e", 7}, 37 | {"r", 9}, 38 | {"a", 6}, 39 | {"i", 3}, 40 | } 41 | } 42 | return h 43 | } 44 | 45 | func TestMaxFixUp(x *testing.T) { 46 | t := (*test.T)(x) 47 | h := heap1(false) 48 | t.Log(h) 49 | h.list[10].priority = 30 50 | h.fixUp(10) 51 | t.Log(h) 52 | t.Assert(h.list[0].item.(string) == "a", "heap did not start with {a 30} %v", h) 53 | } 54 | 55 | func TestMinFixUp(x *testing.T) { 56 | t := (*test.T)(x) 57 | h := heap1(true) 58 | t.Log(h) 59 | h.list[10].priority = 1 60 | h.fixUp(10) 61 | t.Log(h) 62 | t.Assert(h.list[0].item.(string) == "a", "heap did not start with {a 1} %v", h) 63 | } 64 | 65 | func TestMaxFixDown(x *testing.T) { 66 | t := (*test.T)(x) 67 | h := heap1(false) 68 | t.Log(h) 69 | h.list[0].priority = 0 70 | h.fixDown(0) 71 | t.Log(h) 72 | t.Assert(h.list[0].item.(string) == "t", "heap did not start with {t 22} %v", h) 73 | t.Assert(h.list[7].item.(string) == "x", "heap[8] != {x 0} %v", h) 74 | } 75 | 76 | func TestMinFixDown(x *testing.T) { 77 | t := (*test.T)(x) 78 | h := heap1(true) 79 | t.Log(h) 80 | h.list[0].priority = 30 81 | h.fixDown(0) 82 | t.Log(h) 83 | t.Assert(h.list[0].item.(string) == "o", "heap did not start with {o 5} %v", h) 84 | t.Assert(h.list[6].item.(string) == "x", "heap[8] != {n 30} %v", h) 85 | } 86 | 87 | func TestPushMax(x *testing.T) { 88 | t := (*test.T)(x) 89 | h := NewHeap(12, false) 90 | h.Push(18, "g") 91 | h.Push(7, "e") 92 | h.Push(3, "i") 93 | h.Push(6, "a") 94 | h.Push(25, "x") 95 | h.Push(22, "t") 96 | h.Push(14, "n") 97 | h.Push(8, "b") 98 | h.Push(19, "m") 99 | h.Push(9, "r") 100 | h.Push(20, "o") 101 | h.Push(16, "s") 102 | t.Log(h) 103 | t.AssertNil(h.Verify()) 104 | } 105 | 106 | func TestPushMin(x *testing.T) { 107 | t := (*test.T)(x) 108 | h := NewHeap(12, true) 109 | h.Push(18, "g") 110 | h.Push(7, "e") 111 | h.Push(3, "i") 112 | h.Push(6, "a") 113 | h.Push(25, "x") 114 | h.Push(22, "t") 115 | h.Push(14, "n") 116 | h.Push(8, "b") 117 | h.Push(19, "m") 118 | h.Push(9, "r") 119 | h.Push(20, "o") 120 | h.Push(16, "s") 121 | t.Log(h) 122 | t.AssertNil(h.Verify()) 123 | } 124 | -------------------------------------------------------------------------------- /errors/errors.go: -------------------------------------------------------------------------------- 1 | package errors 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "runtime" 7 | "strings" 8 | ) 9 | 10 | var SkipLogging map[string]bool 11 | 12 | func init() { 13 | SkipLogging = make(map[string]bool, 10) 14 | } 15 | 16 | type Error struct { 17 | Errs []error 18 | Stack []byte 19 | } 20 | 21 | func Errorf(format string, args ...interface{}) error { 22 | buf := make([]byte, 50000) 23 | n := runtime.Stack(buf, true) 24 | trace := make([]byte, n) 25 | copy(trace, buf) 26 | return &Error{ 27 | Errs: []error{fmt.Errorf(format, args...)}, 28 | Stack: trace, 29 | } 30 | } 31 | 32 | func Logf(level, format string, args ...interface{}) { 33 | if SkipLogging[level] { 34 | return 35 | } 36 | pc, _, line, ok := runtime.Caller(1) 37 | if !ok { 38 | log.Printf(format, args...) 39 | return 40 | } 41 | fn := runtime.FuncForPC(pc) 42 | msg := fmt.Sprintf(format, args...) 43 | log.Printf("%v (%v:%v): %v", level, fn.Name(), line, msg) 44 | } 45 | 46 | func (e *Error) Chain(err error) error { 47 | e.Errs = append(e.Errs, err) 48 | return e 49 | } 50 | 51 | func (e *Error) Error() string { 52 | if e == nil { 53 | return "Error " 54 | } else if len(e.Errs) == 0 { 55 | return fmt.Sprintf("%v\n%s", e.Errs, string(e.Stack)) 56 | } else if len(e.Errs) == 1 { 57 | return fmt.Sprintf("%v\n%s", e.Errs[0], string(e.Stack)) 58 | } else { 59 | errs := make([]string, 0, len(e.Errs)) 60 | for _, err := range e.Errs { 61 | errs = append(errs, err.Error()) 62 | } 63 | return fmt.Sprintf("{%v}\n%s", strings.Join(errs, ", "), string(e.Stack)) 64 | } 65 | } 66 | 67 | func (e *Error) String() string { 68 | return e.Error() 69 | } 70 | 71 | type ErrorFmter func(a ...interface{}) error 72 | 73 | func NotFound(a ...interface{}) error { 74 | // return fmt.Errorf("Key '%v' was not found.", a...) 75 | return Errorf("Key was not found.") 76 | } 77 | 78 | func NotFoundInBucket(a ...interface{}) error { 79 | return Errorf("Key, '%v', was not in bucket when expected.", a...) 80 | } 81 | 82 | func InvalidKey(a ...interface{}) error { 83 | return Errorf("Key, '%v', is invalid, %s", a...) 84 | } 85 | 86 | func TSTError(a ...interface{}) error { 87 | return Errorf("Internal TST error - "+a[0].(string), a[1:]...) 88 | } 89 | 90 | func NegativeSize(a ...interface{}) error { 91 | return Errorf("Negative size") 92 | } 93 | 94 | func BpTreeError(a ...interface{}) error { 95 | return Errorf("Internal B+ Tree error - "+a[0].(string), a[1:]...) 96 | } 97 | 98 | var Errors map[string]ErrorFmter = map[string]ErrorFmter{ 99 | "not-found": NotFound, 100 | "not-found-in-bucket": NotFoundInBucket, 101 | "invalid-key": InvalidKey, 102 | "tst-error": TSTError, 103 | "negative-size": NegativeSize, 104 | "bptree-error": BpTreeError, 105 | } 106 | -------------------------------------------------------------------------------- /list/fixed_test.go: -------------------------------------------------------------------------------- 1 | package list 2 | 3 | import "testing" 4 | 5 | import ( 6 | "fmt" 7 | ) 8 | 9 | import ( 10 | "github.com/timtadh/data-structures/types" 11 | ) 12 | 13 | func TestFixed(x *testing.T) { 14 | t := (*T)(x) 15 | SIZE := 75 16 | list := Fixed(SIZE) 17 | items := make([]types.ByteSlice, 0, SIZE) 18 | for i := 0; i < SIZE; i++ { 19 | item := t.randslice(rand.Intn(10) + 1) 20 | items = append(items, item) 21 | t.assert_nil(list.Append(item)) 22 | } 23 | t.assert(fmt.Sprintf("list.Full() (%v)", list.Full()), list.Full()) 24 | t.assert(fmt.Sprintf("list.Size == %d (%d)", SIZE, list.Size()), list.Size() == SIZE) 25 | err := list.Append(t.randslice(10)) 26 | t.assert(fmt.Sprintf("err != nil (%v)", err), err != nil) 27 | for i, item := range items { 28 | lg, err := list.Get(i) 29 | t.assert_nil(err) 30 | t.assert(fmt.Sprintf("i %v, items[i] == list.Get(i)", i), lg.Equals(item)) 31 | } 32 | } 33 | 34 | func TestFixedSorted(x *testing.T) { 35 | t := (*T)(x) 36 | SIZE := 100 37 | set := NewFixedSorted(SIZE, false) 38 | items := make([]types.Int, 0, SIZE) 39 | for i := 0; i < SIZE; i++ { 40 | item := types.Int(rand.Intn(1000)) 41 | for set.Has(item) { 42 | item = types.Int(rand.Intn(1000)) 43 | } 44 | items = append(items, item) 45 | t.assert_nil(set.Add(item)) 46 | } 47 | t.assert(fmt.Sprintf("set.Full() (%v)", set.Full()), set.Full()) 48 | t.assert(fmt.Sprintf("set.Size == %d (%d)", SIZE, set.Size()), set.Size() == SIZE) 49 | for i, item := range items { 50 | t.assert(fmt.Sprintf("i %v, !set.Has(item)", i), set.Has(item)) 51 | } 52 | for _, item := range items { 53 | t.assert_nil(set.Delete(item)) 54 | } 55 | for i, item := range items { 56 | t.assert(fmt.Sprintf("i %v, !set.Has(item)", i), !set.Has(item)) 57 | } 58 | } 59 | 60 | func TestFixedAppendMarshalUnmarshalGet(x *testing.T) { 61 | t := (*T)(x) 62 | SIZE := 100 63 | list := Fixed(SIZE) 64 | items := make([]types.Int, 0, SIZE) 65 | for i := 0; i < SIZE; i++ { 66 | item := types.Int(rand.Intn(10) + 1) 67 | items = append(items, item) 68 | t.assert_nil(list.Append(item)) 69 | } 70 | for i, item := range items { 71 | lg, err := list.Get(i) 72 | t.assert_nil(err) 73 | t.assert(fmt.Sprintf("i %v, items[i] == list.Get(i)", i), lg.Equals(item)) 74 | } 75 | err := list.Append(t.randslice(10)) 76 | t.assert(fmt.Sprintf("err != nil (%v)", err), err != nil) 77 | marshal, unmarshal := types.IntMarshals() 78 | mlist1 := NewMList(list, marshal, unmarshal) 79 | bytes, err := mlist1.MarshalBinary() 80 | t.assert_nil(err) 81 | mlist2 := &MList{MarshalItem: marshal, UnmarshalItem: unmarshal} 82 | t.assert_nil(mlist2.UnmarshalBinary(bytes)) 83 | for i, item := range items { 84 | lg, err := mlist2.Get(i) 85 | t.assert_nil(err) 86 | t.assert(fmt.Sprintf("i %v, items[i] == list.Get(i)", i), lg.Equals(item)) 87 | } 88 | err = mlist2.Append(t.randslice(10)) 89 | t.assert(fmt.Sprintf("err != nil (%v)", err), err != nil) 90 | } 91 | -------------------------------------------------------------------------------- /linked/unique.go: -------------------------------------------------------------------------------- 1 | package linked 2 | 3 | import ( 4 | "github.com/timtadh/data-structures/hashtable" 5 | "github.com/timtadh/data-structures/list" 6 | "github.com/timtadh/data-structures/set" 7 | "github.com/timtadh/data-structures/types" 8 | ) 9 | 10 | type UniqueDeque struct { 11 | queue *LinkedList 12 | set types.Set 13 | } 14 | 15 | // A double ended queue that only allows unique items inside. Constructed from a 16 | // doubly linked list and a linear hash table. 17 | func NewUniqueDeque() *UniqueDeque { 18 | return &UniqueDeque{ 19 | queue: New(), 20 | set: set.NewSetMap(hashtable.NewLinearHash()), 21 | } 22 | } 23 | 24 | func (l *UniqueDeque) Size() int { 25 | return l.queue.Size() 26 | } 27 | 28 | func (l *UniqueDeque) Items() (it types.KIterator) { 29 | return l.queue.Items() 30 | } 31 | 32 | func (l *UniqueDeque) Backwards() (it types.KIterator) { 33 | return l.queue.Backwards() 34 | } 35 | 36 | func (l *UniqueDeque) Has(item types.Hashable) bool { 37 | return l.set.Has(item) 38 | } 39 | 40 | func (l *UniqueDeque) Push(item types.Hashable) (err error) { 41 | return l.EnqueBack(item) 42 | } 43 | 44 | func (l *UniqueDeque) Pop() (item types.Hashable, err error) { 45 | return l.DequeBack() 46 | } 47 | 48 | func (l *UniqueDeque) EnqueFront(item types.Hashable) (err error) { 49 | if l.Has(item) { 50 | return nil 51 | } 52 | err = l.queue.EnqueFront(item) 53 | if err != nil { 54 | return err 55 | } 56 | return l.set.Add(item) 57 | } 58 | 59 | func (l *UniqueDeque) EnqueBack(item types.Hashable) (err error) { 60 | if l.Has(item) { 61 | return nil 62 | } 63 | err = l.queue.EnqueBack(item) 64 | if err != nil { 65 | return err 66 | } 67 | return l.set.Add(item) 68 | } 69 | 70 | func (l *UniqueDeque) DequeFront() (item types.Hashable, err error) { 71 | item, err = l.queue.DequeFront() 72 | if err != nil { 73 | return nil, err 74 | } 75 | err = l.set.Delete(item) 76 | if err != nil { 77 | return nil, err 78 | } 79 | return item, nil 80 | } 81 | 82 | func (l *UniqueDeque) DequeBack() (item types.Hashable, err error) { 83 | item, err = l.queue.DequeBack() 84 | if err != nil { 85 | return nil, err 86 | } 87 | err = l.set.Delete(item) 88 | if err != nil { 89 | return nil, err 90 | } 91 | return item, nil 92 | } 93 | 94 | func (l *UniqueDeque) First() (item types.Hashable) { 95 | return l.queue.First() 96 | } 97 | 98 | func (l *UniqueDeque) Last() (item types.Hashable) { 99 | return l.queue.Last() 100 | } 101 | 102 | // Can be compared to any types.IterableContainer 103 | func (l *UniqueDeque) Equals(b types.Equatable) bool { 104 | return l.queue.Equals(b) 105 | } 106 | 107 | // Can be compared to any types.IterableContainer 108 | func (l *UniqueDeque) Less(b types.Sortable) bool { 109 | return l.queue.Less(b) 110 | } 111 | 112 | func (l *UniqueDeque) Hash() int { 113 | return list.Hash(l.queue) 114 | } 115 | 116 | func (l *UniqueDeque) String() string { 117 | return l.queue.String() 118 | } 119 | -------------------------------------------------------------------------------- /tree/util.go: -------------------------------------------------------------------------------- 1 | package tree 2 | 3 | import ( 4 | "github.com/timtadh/data-structures/types" 5 | ) 6 | 7 | func pop(stack []types.TreeNode) ([]types.TreeNode, types.TreeNode) { 8 | if len(stack) <= 0 { 9 | return stack, nil 10 | } else { 11 | return stack[0 : len(stack)-1], stack[len(stack)-1] 12 | } 13 | } 14 | 15 | func btn_expose_nil(node types.BinaryTreeNode) types.BinaryTreeNode { 16 | if types.IsNil(node) { 17 | return nil 18 | } 19 | return node 20 | } 21 | 22 | func tn_expose_nil(node types.TreeNode) types.TreeNode { 23 | if types.IsNil(node) { 24 | return nil 25 | } 26 | return node 27 | } 28 | 29 | func TraverseBinaryTreeInOrder(node types.BinaryTreeNode) types.TreeNodeIterator { 30 | stack := make([]types.TreeNode, 0, 10) 31 | var cur types.TreeNode = btn_expose_nil(node) 32 | var tn_iterator types.TreeNodeIterator 33 | tn_iterator = func() (tn types.TreeNode, next types.TreeNodeIterator) { 34 | if len(stack) > 0 || cur != nil { 35 | for cur != nil { 36 | stack = append(stack, cur) 37 | cur = cur.(types.BinaryTreeNode).Left() 38 | } 39 | stack, cur = pop(stack) 40 | tn = cur 41 | cur = cur.(types.BinaryTreeNode).Right() 42 | return tn, tn_iterator 43 | } else { 44 | return nil, nil 45 | } 46 | } 47 | return tn_iterator 48 | } 49 | 50 | func TraverseTreePreOrder(node types.TreeNode) types.TreeNodeIterator { 51 | stack := append(make([]types.TreeNode, 0, 10), tn_expose_nil(node)) 52 | var tn_iterator types.TreeNodeIterator 53 | tn_iterator = func() (tn types.TreeNode, next types.TreeNodeIterator) { 54 | if len(stack) <= 0 { 55 | return nil, nil 56 | } 57 | stack, tn = pop(stack) 58 | kid_count := 1 59 | if tn.ChildCount() >= 0 { 60 | kid_count = tn.ChildCount() 61 | } 62 | kids := make([]types.TreeNode, 0, kid_count) 63 | for child, next := tn.Children()(); next != nil; child, next = next() { 64 | kids = append(kids, child) 65 | } 66 | for i := len(kids) - 1; i >= 0; i-- { 67 | stack = append(stack, kids[i]) 68 | } 69 | return tn, tn_iterator 70 | } 71 | return tn_iterator 72 | } 73 | 74 | func TraverseTreePostOrder(node types.TreeNode) types.TreeNodeIterator { 75 | type entry struct { 76 | tn types.TreeNode 77 | i int 78 | } 79 | 80 | pop := func(stack []entry) ([]entry, types.TreeNode, int) { 81 | if len(stack) <= 0 { 82 | return stack, nil, 0 83 | } else { 84 | e := stack[len(stack)-1] 85 | return stack[0 : len(stack)-1], e.tn, e.i 86 | } 87 | } 88 | 89 | stack := append(make([]entry, 0, 10), entry{tn_expose_nil(node), 0}) 90 | 91 | var tn_iterator types.TreeNodeIterator 92 | tn_iterator = func() (tn types.TreeNode, next types.TreeNodeIterator) { 93 | var i int 94 | 95 | if len(stack) <= 0 { 96 | return nil, nil 97 | } 98 | 99 | stack, tn, i = pop(stack) 100 | for i < tn.ChildCount() { 101 | kid := tn.GetChild(i) 102 | stack = append(stack, entry{tn, i + 1}) 103 | tn = kid 104 | i = 0 105 | } 106 | return tn, tn_iterator 107 | } 108 | return tn_iterator 109 | } 110 | -------------------------------------------------------------------------------- /set/mapset_test.go: -------------------------------------------------------------------------------- 1 | package set 2 | 3 | import "testing" 4 | 5 | import ( 6 | "fmt" 7 | ) 8 | 9 | import ( 10 | "github.com/timtadh/data-structures/types" 11 | ) 12 | 13 | func TestMapSetAddHasDeleteRandom(x *testing.T) { 14 | t := (*T)(x) 15 | SIZE := 100 16 | a := NewMapSet(NewSortedSet(10)) 17 | items := make([]*types.MapEntry, 0, SIZE) 18 | for i := 0; i < SIZE; i++ { 19 | item := &types.MapEntry{types.Int(rand.Intn(1000)), types.Int(rand.Intn(1000))} 20 | for a.Has(item) { 21 | item = &types.MapEntry{types.Int(rand.Intn(1000)), types.Int(rand.Intn(1000))} 22 | } 23 | items = append(items, item) 24 | t.assert_nil(a.Add(item)) 25 | } 26 | set := NewMapSet(NewSortedSet(10)) 27 | t.assert_nil(set.Extend(a.Items())) 28 | t.assert("set == a", set.Equals(a)) 29 | for i, item := range items { 30 | thing, err := set.Item(item) 31 | t.assert_nil(err) 32 | t.assert(fmt.Sprintf("i %v, thing == item", i), thing.Equals(item)) 33 | t.assert(fmt.Sprintf("i %v, !set.Has(item)", i), set.Has(item)) 34 | } 35 | for _, item := range items { 36 | t.assert_nil(set.Delete(item)) 37 | } 38 | for i, item := range items { 39 | t.assert(fmt.Sprintf("i %v, !set.Has(item)", i), !set.Has(item)) 40 | } 41 | } 42 | 43 | func TestMapSetMapFunc(x *testing.T) { 44 | t := (*T)(x) 45 | SIZE := 100 46 | set := types.Map(NewMapSet(NewSortedSet(10))) 47 | items := make([]*types.MapEntry, 0, SIZE) 48 | for i := 0; i < SIZE; i++ { 49 | item := &types.MapEntry{types.Int(rand.Intn(1000)), types.Int(rand.Intn(1000))} 50 | for set.Has(item.Key) { 51 | item = &types.MapEntry{types.Int(rand.Intn(1000)), types.Int(rand.Intn(1000))} 52 | } 53 | items = append(items, item) 54 | t.assert_nil(set.Put(item.Key, item.Value)) 55 | } 56 | for i, item := range items { 57 | t.assert(fmt.Sprintf("i %v, !set.Has(item, %v)", i, item), set.Has(item.Key)) 58 | } 59 | t.assert("size == 100", set.Size() == 100) 60 | for _, item := range items { 61 | rm, err := set.Remove(item.Key) 62 | t.assert_nil(err) 63 | t.assert("item == rm", item.Value.(types.Int).Equals(rm.(types.Int))) 64 | } 65 | for i, item := range items { 66 | t.assert(fmt.Sprintf("i %v, set.Has(item)", i), !set.Has(item.Key)) 67 | } 68 | } 69 | 70 | func TestMapSetIterators(x *testing.T) { 71 | t := (*T)(x) 72 | SIZE := 100 73 | set := NewMapSet(NewSortedSet(10)) 74 | for i := 0; i < SIZE; i++ { 75 | item := &types.MapEntry{types.Int(rand.Intn(1000)), types.Int(rand.Intn(1000))} 76 | t.assert_nil(set.Put(item.Key, item.Value)) 77 | } 78 | item, items := set.Items()() 79 | key, keys := set.Keys()() 80 | for items != nil && keys != nil { 81 | if !item.(*types.MapEntry).Key.Equals(key) { 82 | t.Fatal("item != key") 83 | } 84 | item, items = items() 85 | key, keys = keys() 86 | } 87 | t.assert("uneven iteration", items == nil && keys == nil) 88 | item, items = set.Items()() 89 | val, vals := set.Values()() 90 | for items != nil && vals != nil { 91 | if !item.(*types.MapEntry).Value.(types.Int).Equals(val.(types.Int)) { 92 | t.Fatal("item != key") 93 | } 94 | item, items = items() 95 | val, vals = vals() 96 | } 97 | t.assert("uneven iteration", items == nil && keys == nil) 98 | } 99 | -------------------------------------------------------------------------------- /hashtable/linhash.go: -------------------------------------------------------------------------------- 1 | package hashtable 2 | 3 | import ( 4 | "github.com/timtadh/data-structures/tree/avl" 5 | . "github.com/timtadh/data-structures/types" 6 | ) 7 | 8 | const ( 9 | UTILIZATION = .75 10 | RECORDS_PER_BLOCK = 16 11 | ) 12 | 13 | type bst struct { 14 | hash int 15 | key Hashable 16 | value interface{} 17 | left *bst 18 | right *bst 19 | } 20 | 21 | type LinearHash struct { 22 | table []*avl.AvlNode 23 | n uint 24 | r uint 25 | i uint 26 | } 27 | 28 | func NewLinearHash() *LinearHash { 29 | N := uint(32) 30 | I := uint(5) 31 | return &LinearHash{ 32 | table: make([]*avl.AvlNode, N), 33 | n: N, 34 | r: 0, 35 | i: I, 36 | } 37 | } 38 | 39 | func (self *LinearHash) bucket(key Hashable) uint { 40 | m := uint(key.Hash() & ((1 << self.i) - 1)) 41 | if m < self.n { 42 | return m 43 | } else { 44 | return m ^ (1 << (self.i - 1)) 45 | } 46 | } 47 | 48 | func (self *LinearHash) Size() int { 49 | return int(self.r) 50 | } 51 | 52 | func (self *LinearHash) Put(key Hashable, value interface{}) (err error) { 53 | var updated bool 54 | bkt_idx := self.bucket(key) 55 | self.table[bkt_idx], updated = self.table[bkt_idx].Put(key, value) 56 | if !updated { 57 | self.r += 1 58 | } 59 | if float64(self.r) > UTILIZATION*float64(self.n)*float64(RECORDS_PER_BLOCK) { 60 | return self.split() 61 | } 62 | return nil 63 | } 64 | 65 | func (self *LinearHash) Get(key Hashable) (value interface{}, err error) { 66 | bkt_idx := self.bucket(key) 67 | return self.table[bkt_idx].Get(key) 68 | } 69 | 70 | func (self *LinearHash) Has(key Hashable) bool { 71 | bkt_idx := self.bucket(key) 72 | return self.table[bkt_idx].Has(key) 73 | } 74 | 75 | func (self *LinearHash) Remove(key Hashable) (value interface{}, err error) { 76 | bkt_idx := self.bucket(key) 77 | self.table[bkt_idx], value, err = self.table[bkt_idx].Remove(key) 78 | if err == nil { 79 | self.r -= 1 80 | } 81 | return 82 | } 83 | 84 | func (self *LinearHash) split() (err error) { 85 | bkt_idx := self.n % (1 << (self.i - 1)) 86 | old_bkt := self.table[bkt_idx] 87 | var bkt_a, bkt_b *avl.AvlNode 88 | self.n += 1 89 | if self.n > (1 << self.i) { 90 | self.i += 1 91 | } 92 | for key, value, next := old_bkt.Iterate()(); next != nil; key, value, next = next() { 93 | if self.bucket(key.(Hashable)) == bkt_idx { 94 | bkt_a, _ = bkt_a.Put(key.(Hashable), value) 95 | } else { 96 | bkt_b, _ = bkt_b.Put(key.(Hashable), value) 97 | } 98 | } 99 | self.table[bkt_idx] = bkt_a 100 | self.table = append(self.table, bkt_b) 101 | return nil 102 | } 103 | 104 | func (self *LinearHash) Iterate() KVIterator { 105 | table := self.table 106 | i := 0 107 | iter := table[i].Iterate() 108 | var kv_iterator KVIterator 109 | kv_iterator = func() (key Hashable, val interface{}, next KVIterator) { 110 | key, val, iter = iter() 111 | for iter == nil { 112 | i++ 113 | if i >= len(table) { 114 | return nil, nil, nil 115 | } 116 | key, val, iter = table[i].Iterate()() 117 | } 118 | return key, val, kv_iterator 119 | } 120 | return kv_iterator 121 | } 122 | 123 | func (self *LinearHash) Items() (vi KIterator) { 124 | return MakeItemsIterator(self) 125 | } 126 | 127 | func (self *LinearHash) Keys() KIterator { 128 | return MakeKeysIterator(self) 129 | } 130 | 131 | func (self *LinearHash) Values() Iterator { 132 | return MakeValuesIterator(self) 133 | } 134 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The data-structures library 2 | 3 | This library is wholly written by the authors below. Please respect all 4 | licensing terms (a BSD 3-clause license). 5 | 6 | Copyright (C) 2013-2017 7 | * Tim Henderson (tim.tadh@gmail.com) 8 | * Case Western Reserve University, Cleveland, Ohio 9 | * Google Inc. 10 | 11 | Redistribution and use in source and binary forms, with or without 12 | modification, are permitted provided that the following conditions are met: 13 | 14 | * Redistributions of source code must retain the above copyright notice, 15 | this list of conditions and the following disclaimer. 16 | * Redistributions in binary form must reproduce the above copyright notice, 17 | this list of conditions and the following disclaimer in the documentation 18 | and/or other materials provided with the distribution. 19 | * Neither the name of the lexmachine nor the names of its contributors may 20 | be used to endorse or promote products derived from this software without 21 | specific prior written permission. 22 | 23 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 24 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 25 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 26 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 27 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 28 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 29 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 30 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 31 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 32 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 | 34 | 35 | 36 | Copyright (C) 2009 The Go Authors (for portions of rand/) 37 | This portion is used under the terms of the Go license: 38 | https://github.com/golang/go/blob/master/LICENSE 39 | (which is a BSD 3-clause license copied below) 40 | 41 | Redistribution and use in source and binary forms, with or without 42 | modification, are permitted provided that the following conditions 43 | are met: 44 | 45 | * Redistributions of source code must retain the above copyright 46 | notice, this list of conditions and the following disclaimer. 47 | * Redistributions in binary form must reproduce the above 48 | copyright notice, this list of conditions and the following 49 | disclaimer in the documentation and/or other materials provided with 50 | the distribution. 51 | * Neither the name of Google Inc. nor the names of its 52 | contributors may be used to endorse or promote products derived from 53 | this software without specific prior written permission. 54 | 55 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 56 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 57 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 58 | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 59 | COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 60 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 61 | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 62 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 63 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 64 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 65 | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 66 | POSSIBILITY OF SUCH DAMAGE. 67 | -------------------------------------------------------------------------------- /hashtable/hashtable.go: -------------------------------------------------------------------------------- 1 | package hashtable 2 | 3 | import . "github.com/timtadh/data-structures/types" 4 | import . "github.com/timtadh/data-structures/errors" 5 | 6 | type entry struct { 7 | key Hashable 8 | value interface{} 9 | next *entry 10 | } 11 | 12 | type Hash struct { 13 | table []*entry 14 | size int 15 | } 16 | 17 | func abs(x int) int { 18 | if x < 0 { 19 | return -x 20 | } else { 21 | return x 22 | } 23 | } 24 | 25 | func (self *entry) Put(key Hashable, value interface{}) (e *entry, appended bool) { 26 | if self == nil { 27 | return &entry{key, value, nil}, true 28 | } 29 | if self.key.Equals(key) { 30 | self.value = value 31 | return self, false 32 | } else { 33 | self.next, appended = self.next.Put(key, value) 34 | return self, appended 35 | } 36 | } 37 | 38 | func (self *entry) Get(key Hashable) (has bool, value interface{}) { 39 | if self == nil { 40 | return false, nil 41 | } else if self.key.Equals(key) { 42 | return true, self.value 43 | } else { 44 | return self.next.Get(key) 45 | } 46 | } 47 | 48 | func (self *entry) Remove(key Hashable) *entry { 49 | if self == nil { 50 | panic(Errors["not-found-in-bucket"](key)) 51 | } 52 | if self.key.Equals(key) { 53 | return self.next 54 | } else { 55 | self.next = self.next.Remove(key) 56 | return self 57 | } 58 | } 59 | 60 | func NewHashTable(initial_size int) *Hash { 61 | return &Hash{ 62 | table: make([]*entry, initial_size), 63 | size: 0, 64 | } 65 | } 66 | 67 | func (self *Hash) bucket(key Hashable) int { 68 | return abs(key.Hash()) % len(self.table) 69 | } 70 | 71 | func (self *Hash) Size() int { return self.size } 72 | 73 | func (self *Hash) Put(key Hashable, value interface{}) (err error) { 74 | bucket := self.bucket(key) 75 | var appended bool 76 | self.table[bucket], appended = self.table[bucket].Put(key, value) 77 | if appended { 78 | self.size += 1 79 | } 80 | if self.size*2 > len(self.table) { 81 | return self.expand() 82 | } 83 | return nil 84 | } 85 | 86 | func (self *Hash) expand() error { 87 | table := self.table 88 | self.table = make([]*entry, len(table)*2) 89 | self.size = 0 90 | for _, E := range table { 91 | for e := E; e != nil; e = e.next { 92 | if err := self.Put(e.key, e.value); err != nil { 93 | return err 94 | } 95 | } 96 | } 97 | return nil 98 | } 99 | 100 | func (self *Hash) Get(key Hashable) (value interface{}, err error) { 101 | bucket := self.bucket(key) 102 | if has, value := self.table[bucket].Get(key); has { 103 | return value, nil 104 | } else { 105 | return nil, Errors["not-found"](key) 106 | } 107 | } 108 | 109 | func (self *Hash) Has(key Hashable) (has bool) { 110 | has, _ = self.table[self.bucket(key)].Get(key) 111 | return 112 | } 113 | 114 | func (self *Hash) Remove(key Hashable) (value interface{}, err error) { 115 | bucket := self.bucket(key) 116 | has, value := self.table[bucket].Get(key) 117 | if !has { 118 | return nil, Errors["not-found"](key) 119 | } 120 | self.table[bucket] = self.table[bucket].Remove(key) 121 | self.size -= 1 122 | return value, nil 123 | } 124 | 125 | func (self *Hash) Iterate() KVIterator { 126 | table := self.table 127 | i := -1 128 | var e *entry 129 | var kv_iterator KVIterator 130 | kv_iterator = func() (key Hashable, val interface{}, next KVIterator) { 131 | for e == nil { 132 | i++ 133 | if i >= len(table) { 134 | return nil, nil, nil 135 | } 136 | e = table[i] 137 | } 138 | key = e.key 139 | val = e.value 140 | e = e.next 141 | return key, val, kv_iterator 142 | } 143 | return kv_iterator 144 | } 145 | 146 | func (self *Hash) Items() (vi KIterator) { 147 | return MakeItemsIterator(self) 148 | } 149 | 150 | func (self *Hash) Keys() KIterator { 151 | return MakeKeysIterator(self) 152 | } 153 | 154 | func (self *Hash) Values() Iterator { 155 | return MakeValuesIterator(self) 156 | } 157 | -------------------------------------------------------------------------------- /heap/pq.go: -------------------------------------------------------------------------------- 1 | package heap 2 | 3 | import ( 4 | "github.com/timtadh/data-structures/errors" 5 | "github.com/timtadh/data-structures/types" 6 | ) 7 | 8 | type entry struct { 9 | item interface{} 10 | priority int 11 | } 12 | 13 | type PriorityQueue interface { 14 | types.Sized 15 | Push(priority int, item interface{}) 16 | Peek() interface{} 17 | Pop() interface{} 18 | } 19 | 20 | // Notes: 21 | // Parent of i : (i+1)/2 - 1 22 | // Left Child of i : (i+1)*2 - 1 23 | // Right Child of i : (i+1)*2 24 | 25 | // A binary heap for Priority Queues. The priorities are modeled 26 | // explicitly as integers. It can work either as a min heap or a max 27 | // heap. 28 | type Heap struct { 29 | min bool 30 | list []entry 31 | } 32 | 33 | // Make a new binary heap. 34 | // size : hint for the size of the heap 35 | // (should estimate the maximal size) 36 | // min : false == max heap, true == min heap 37 | func NewHeap(size int, min bool) *Heap { 38 | return &Heap{ 39 | min: min, 40 | list: make([]entry, 0, size), 41 | } 42 | } 43 | 44 | func NewMinHeap(size int) *Heap { 45 | return &Heap{ 46 | min: true, 47 | list: make([]entry, 0, size), 48 | } 49 | } 50 | 51 | func NewMaxHeap(size int) *Heap { 52 | return &Heap{ 53 | min: false, 54 | list: make([]entry, 0, size), 55 | } 56 | } 57 | 58 | // How many items in the heap? 59 | func (h *Heap) Size() int { 60 | return len(h.list) 61 | } 62 | 63 | // Is this a min heap? 64 | func (h *Heap) MinHeap() bool { 65 | return h.min 66 | } 67 | 68 | // Is this a max heap? 69 | func (h *Heap) MaxHeap() bool { 70 | return !h.min 71 | } 72 | 73 | // Push an item with a priority 74 | func (h *Heap) Push(priority int, item interface{}) { 75 | h.list = append(h.list, entry{item, priority}) 76 | h.fixUp(len(h.list) - 1) 77 | } 78 | 79 | // Pop the highest (or lowest) priority item 80 | func (h *Heap) Pop() interface{} { 81 | if len(h.list) == 0 { 82 | return nil 83 | } 84 | i := h.list[0].item 85 | h.list[0] = h.list[len(h.list)-1] 86 | h.list = h.list[:len(h.list)-1] 87 | h.fixDown(0) 88 | return i 89 | } 90 | 91 | // Peek at the highest (or lowest) priority item 92 | func (h *Heap) Peek() interface{} { 93 | if len(h.list) == 0 { 94 | return nil 95 | } 96 | return h.list[0].item 97 | } 98 | 99 | func (h *Heap) Items() (it types.Iterator) { 100 | i := 0 101 | return func() (item interface{}, next types.Iterator) { 102 | var e entry 103 | if i < len(h.list) { 104 | e = h.list[i] 105 | i++ 106 | return e.item, it 107 | } 108 | return nil, nil 109 | } 110 | } 111 | 112 | func (h *Heap) fixUp(k int) { 113 | parent := (k+1)/2 - 1 114 | for k > 0 { 115 | if h.gte(parent, k) { 116 | return 117 | } 118 | h.list[parent], h.list[k] = h.list[k], h.list[parent] 119 | k = parent 120 | parent = (k+1)/2 - 1 121 | } 122 | } 123 | 124 | func (h *Heap) fixDown(k int) { 125 | kid := (k+1)*2 - 1 126 | for kid < len(h.list) { 127 | if kid+1 < len(h.list) && h.lt(kid, kid+1) { 128 | kid++ 129 | } 130 | if h.gte(k, kid) { 131 | break 132 | } 133 | h.list[kid], h.list[k] = h.list[k], h.list[kid] 134 | k = kid 135 | kid = (k+1)*2 - 1 136 | } 137 | } 138 | 139 | func (h *Heap) gte(i, j int) bool { 140 | if h.min { 141 | return h.list[i].priority <= h.list[j].priority 142 | } else { 143 | return h.list[i].priority >= h.list[j].priority 144 | } 145 | } 146 | 147 | func (h *Heap) lt(i, j int) bool { 148 | if h.min { 149 | return h.list[i].priority > h.list[j].priority 150 | } else { 151 | return h.list[i].priority < h.list[j].priority 152 | } 153 | } 154 | 155 | // Verify the heap is properly structured. 156 | func (h *Heap) Verify() error { 157 | for i := 1; i < len(h.list); i++ { 158 | parent := (i+1)/2 - 1 159 | if h.lt(parent, i) { 160 | return errors.Errorf("parent %v '<' kid %v", h.list[parent], h.list[i]) 161 | } 162 | } 163 | return nil 164 | } 165 | -------------------------------------------------------------------------------- /set/mapset.go: -------------------------------------------------------------------------------- 1 | package set 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | import ( 8 | "github.com/timtadh/data-structures/errors" 9 | "github.com/timtadh/data-structures/types" 10 | ) 11 | 12 | type MapSet struct { 13 | Set types.Set 14 | } 15 | 16 | func mapEntry(item types.Hashable) (*types.MapEntry, error) { 17 | if me, ok := item.(*types.MapEntry); ok { 18 | return me, nil 19 | } else { 20 | return nil, errors.Errorf("Must pass a *types.MapEntry, got %T", item) 21 | } 22 | } 23 | 24 | func asMapEntry(item types.Hashable) *types.MapEntry { 25 | if me, ok := item.(*types.MapEntry); ok { 26 | return me 27 | } else { 28 | return &types.MapEntry{item, nil} 29 | } 30 | } 31 | 32 | func NewMapSet(set types.Set) *MapSet { 33 | return &MapSet{set} 34 | } 35 | 36 | func (m *MapSet) Equals(b types.Equatable) bool { 37 | if o, ok := b.(*MapSet); ok { 38 | return m.Set.Equals(o.Set) 39 | } else { 40 | return false 41 | } 42 | } 43 | 44 | func (m *MapSet) Size() int { 45 | return m.Set.Size() 46 | } 47 | 48 | func (m *MapSet) Keys() types.KIterator { 49 | return types.MakeKeysIterator(m) 50 | } 51 | 52 | func (m *MapSet) Values() types.Iterator { 53 | return types.MakeValuesIterator(m) 54 | } 55 | 56 | func (m *MapSet) Iterate() (kvit types.KVIterator) { 57 | items := m.Items() 58 | kvit = func() (key types.Hashable, value interface{}, _ types.KVIterator) { 59 | var item types.Hashable 60 | item, items = items() 61 | if items == nil { 62 | return nil, nil, nil 63 | } 64 | me := item.(*types.MapEntry) 65 | return me.Key, me.Value, kvit 66 | } 67 | return kvit 68 | } 69 | 70 | func (m *MapSet) Items() types.KIterator { 71 | return m.Set.Items() 72 | } 73 | 74 | func (m *MapSet) Has(key types.Hashable) bool { 75 | return m.Set.Has(asMapEntry(key)) 76 | } 77 | 78 | func (m *MapSet) Add(item types.Hashable) (err error) { 79 | me, err := mapEntry(item) 80 | if err != nil { 81 | return err 82 | } 83 | return m.Set.Add(me) 84 | } 85 | 86 | func (m *MapSet) Put(key types.Hashable, value interface{}) (err error) { 87 | return m.Add(&types.MapEntry{key, value}) 88 | } 89 | 90 | func (m *MapSet) Get(key types.Hashable) (value interface{}, err error) { 91 | item, err := m.Set.Item(asMapEntry(key)) 92 | if err != nil { 93 | return nil, err 94 | } 95 | me, err := mapEntry(item) 96 | if err != nil { 97 | return nil, err 98 | } 99 | return me.Value, nil 100 | } 101 | 102 | func (m *MapSet) Item(key types.Hashable) (me types.Hashable, err error) { 103 | item, err := m.Set.Item(asMapEntry(key)) 104 | if err != nil { 105 | return nil, err 106 | } 107 | me, err = mapEntry(item) 108 | if err != nil { 109 | return nil, err 110 | } 111 | return me, nil 112 | } 113 | 114 | func (m *MapSet) Remove(key types.Hashable) (value interface{}, err error) { 115 | item, err := m.Get(asMapEntry(key)) 116 | if err != nil { 117 | return nil, err 118 | } 119 | err = m.Delete(key) 120 | if err != nil { 121 | return nil, err 122 | } 123 | return item, nil 124 | } 125 | 126 | func (m *MapSet) Delete(item types.Hashable) (err error) { 127 | return m.Set.Delete(asMapEntry(item)) 128 | } 129 | 130 | func (m *MapSet) Extend(items types.KIterator) (err error) { 131 | for item, items := items(); items != nil; item, items = items() { 132 | err := m.Add(item) 133 | if err != nil { 134 | return err 135 | } 136 | } 137 | return nil 138 | } 139 | 140 | func (m *MapSet) Union(b types.Set) (types.Set, error) { 141 | return Union(m, b) 142 | } 143 | 144 | func (m *MapSet) Intersect(b types.Set) (types.Set, error) { 145 | return Intersect(m, b) 146 | } 147 | 148 | func (m *MapSet) Subtract(b types.Set) (types.Set, error) { 149 | return Subtract(m, b) 150 | } 151 | 152 | func (m *MapSet) Subset(b types.Set) bool { 153 | return Subset(m, b) 154 | } 155 | 156 | func (m *MapSet) Superset(b types.Set) bool { 157 | return Superset(m, b) 158 | } 159 | 160 | func (m *MapSet) ProperSubset(b types.Set) bool { 161 | return ProperSubset(m, b) 162 | } 163 | 164 | func (m *MapSet) ProperSuperset(b types.Set) bool { 165 | return ProperSuperset(m, b) 166 | } 167 | 168 | func (m *MapSet) String() string { 169 | return fmt.Sprintf("%v", m.Set) 170 | } 171 | -------------------------------------------------------------------------------- /tree/bptree/bptree.go: -------------------------------------------------------------------------------- 1 | package bptree 2 | 3 | import ( 4 | "github.com/timtadh/data-structures/types" 5 | ) 6 | 7 | /* A BpTree is a B+Tree with support for duplicate keys. This makes it behave as 8 | * a MultiMap. Additionally you can use the Range operator to select k/v in a 9 | * range. If from > to it will iterate backwards. 10 | */ 11 | type BpTree struct { 12 | root *BpNode 13 | size int 14 | } 15 | 16 | type loc_iterator func() (i int, leaf *BpNode, li loc_iterator) 17 | 18 | func NewBpTree(node_size int) *BpTree { 19 | return &BpTree{ 20 | root: NewLeaf(node_size, false), 21 | size: 0, 22 | } 23 | } 24 | 25 | func (self *BpTree) Size() int { 26 | return self.size 27 | } 28 | 29 | func (self *BpTree) Has(key types.Hashable) bool { 30 | if len(self.root.keys) == 0 { 31 | return false 32 | } 33 | j, l := self.root.get_start(key) 34 | return l.keys[j].Equals(key) 35 | } 36 | 37 | func (self *BpTree) Count(key types.Hashable) int { 38 | if len(self.root.keys) == 0 { 39 | return 0 40 | } 41 | j, l := self.root.get_start(key) 42 | count := 0 43 | end := false 44 | for !end && l.keys[j].Equals(key) { 45 | count++ 46 | j, l, end = next_location(j, l) 47 | } 48 | return count 49 | } 50 | 51 | func (self *BpTree) Add(key types.Hashable, value interface{}) (err error) { 52 | new_root, err := self.root.put(key, value) 53 | if err != nil { 54 | return err 55 | } 56 | self.root = new_root 57 | self.size += 1 58 | return nil 59 | } 60 | 61 | func (self *BpTree) Replace(key types.Hashable, where types.WhereFunc, value interface{}) (err error) { 62 | li := self.root.forward(key, key) 63 | for i, leaf, next := li(); next != nil; i, leaf, next = next() { 64 | if where(leaf.values[i]) { 65 | leaf.values[i] = value 66 | } 67 | } 68 | return nil 69 | } 70 | 71 | func (self *BpTree) Find(key types.Hashable) (kvi types.KVIterator) { 72 | return self.Range(key, key) 73 | } 74 | 75 | func (self *BpTree) Range(from, to types.Hashable) (kvi types.KVIterator) { 76 | var li loc_iterator 77 | if !to.Less(from) { 78 | li = self.root.forward(from, to) 79 | } else { 80 | li = self.root.backward(from, to) 81 | } 82 | kvi = func() (key types.Hashable, value interface{}, next types.KVIterator) { 83 | var i int 84 | var leaf *BpNode 85 | i, leaf, li = li() 86 | if li == nil { 87 | return nil, nil, nil 88 | } 89 | return leaf.keys[i], leaf.values[i], kvi 90 | } 91 | return kvi 92 | } 93 | 94 | func (self *BpTree) RemoveWhere(key types.Hashable, where types.WhereFunc) (err error) { 95 | ns := self.root.NodeSize() 96 | new_root, err := self.root.remove(key, where) 97 | if err != nil { 98 | return err 99 | } 100 | if new_root == nil { 101 | self.root = NewLeaf(ns, false) 102 | } else { 103 | self.root = new_root 104 | } 105 | self.size -= 1 106 | return nil 107 | } 108 | 109 | func (self *BpTree) Keys() (ki types.KIterator) { 110 | li := self.root.all() 111 | var prev types.Equatable 112 | ki = func() (key types.Hashable, next types.KIterator) { 113 | var i int 114 | var leaf *BpNode 115 | i, leaf, li = li() 116 | if li == nil { 117 | return nil, nil 118 | } 119 | if leaf.keys[i].Equals(prev) { 120 | return ki() 121 | } 122 | prev = leaf.keys[i] 123 | return leaf.keys[i], ki 124 | } 125 | return ki 126 | } 127 | 128 | func (self *BpTree) Values() (vi types.Iterator) { 129 | return types.MakeValuesIterator(self) 130 | } 131 | 132 | func (self *BpTree) Items() (vi types.KIterator) { 133 | return types.MakeItemsIterator(self) 134 | } 135 | 136 | func (self *BpTree) Iterate() (kvi types.KVIterator) { 137 | li := self.root.all() 138 | kvi = func() (key types.Hashable, value interface{}, next types.KVIterator) { 139 | var i int 140 | var leaf *BpNode 141 | i, leaf, li = li() 142 | if li == nil { 143 | return nil, nil, nil 144 | } 145 | return leaf.keys[i], leaf.values[i], kvi 146 | } 147 | return kvi 148 | } 149 | 150 | func (self *BpTree) Backward() (kvi types.KVIterator) { 151 | li := self.root.all_backward() 152 | kvi = func() (key types.Hashable, value interface{}, next types.KVIterator) { 153 | var i int 154 | var leaf *BpNode 155 | i, leaf, li = li() 156 | if li == nil { 157 | return nil, nil, nil 158 | } 159 | return leaf.keys[i], leaf.values[i], kvi 160 | } 161 | return kvi 162 | } 163 | -------------------------------------------------------------------------------- /exc/doc.go: -------------------------------------------------------------------------------- 1 | // Exceptions for Go as a Library 2 | // 3 | // Explanation: http://hackthology.com/exceptions-for-go-as-a-library.html 4 | // 5 | // Go (golang) lacks support for exceptions found in many other languages. There 6 | // are good reasons for Go to not include exceptions. For instance, by making 7 | // error handling explicit the programmer is forced to think concretely about 8 | // the correct action to take. Fined grained control over the handling of errors 9 | // using multiple return parameters is one of Go's strengths. 10 | // 11 | // However, there are cases where Go programs do not universally benefit from 12 | // the explicit handling of errors. For instance, consider the following code: 13 | // 14 | // func DoStuff(a, b, c interface{}) error { 15 | // x, err := foo(a) 16 | // if err != nil { 17 | // return err 18 | // } 19 | // y, err := bar(b, x) 20 | // if err != nil { 21 | // return err 22 | // } 23 | // z, err := bax(c, x, y) 24 | // if err != nil { 25 | // return err 26 | // } 27 | // return baz(x, y, z) 28 | // } 29 | // 30 | // If Go had exceptions such code could be easily simplified: 31 | // 32 | // func DoStuff(a, b, c interface{}) throws error { 33 | // x := foo(a) 34 | // y := bar(b, x) 35 | // baz(x, y, bax(c, x, y) 36 | // } 37 | // 38 | // This library allow you to write go with exceptions and try-catch-finally 39 | // blocks. It is not appropriate for all situations but can simplify some 40 | // application code. Libraries and external APIs should continue to conform to 41 | // the Go standard of returning error values. 42 | // 43 | // Here is an example of the `DoStuff` function where foo, bar and baz all throw 44 | // exceptions instead of returning errors. (We will look at the case where they 45 | // return errors that you want to turn into exceptions next). We want DoStuff to 46 | // be an public API function and return an error: 47 | // 48 | // func DoStuff(a, b, c interface{}) error { 49 | // return exc.Try(func() { 50 | // x := foo(a) 51 | // y := bar(b, x) 52 | // baz(x, y, bax(c, x, y) 53 | // }).Error() 54 | // } 55 | // 56 | // Now let's consider the case where we want to catch the exception log and 57 | // reraise it: 58 | // 59 | // func DoStuff(a, b, c interface{}) error { 60 | // return exc.Try(func() { 61 | // x := foo(a) 62 | // y := bar(b, x) 63 | // baz(x, y, bax(c, x, y) 64 | // }).Catch(&exc.Exception{}, func(t exc.Throwable) { 65 | // log.Log(t) 66 | // exc.Rethrow(t, exc.Errorf("rethrow after logging")) 67 | // }).Error() 68 | // } 69 | // 70 | // Rethrow will chain the Throwable `t` with the new `*Error` created such that 71 | // if/when the exception reaches the top level you know exactly how it was 72 | // created and where it was rethrown. 73 | // 74 | // Ok, what about interacting with regular Go APIs which return errors? How can 75 | // we turn those errors into exceptions? The easy was is to use the 76 | // `ThrowOnError` function which is a sugar for: 77 | // 78 | // if err != nil { 79 | // ThrowErr(ErrorFrom(err) 80 | // } 81 | // 82 | // So converting out original `DoStuff` function we get 83 | // 84 | // func DoStuff(a, b, c interface{}) { // Throws 85 | // x, err := foo(a) 86 | // exc.ThrowOnError(err) 87 | // y, err := bar(b, x) 88 | // exc.ThrowOnError(err) 89 | // z, err := bax(c, x, y) 90 | // exc.ThrowOnError(err) 91 | // exc.ThrowOnError(baz(x, y, z)) 92 | // } 93 | // 94 | // This package also supports: catching user defined exceptions, catching 95 | // multiple exception types, `Close` which works like the "try with resources" 96 | // construct in Java 7+, (multiple) finally blocks, and a choice between 97 | // propogating exceptions with `Unwind` or retrieving the error/exception with 98 | // `Error` and `Exception` functions. 99 | // 100 | // One Gotcha! The `Try()` function creates a `*Block` struct. To execute the 101 | // block you must either call: `Unwind`, `Error`, or `Exception`. `Unwind` 102 | // executes the block, if there is an exception coming out of the block it 103 | // continues to cause the program stack unwind. `Error` and `Exception` excute 104 | // the block, but return the exception as a value to deal with in the usual Go 105 | // way. 106 | // 107 | package exc 108 | -------------------------------------------------------------------------------- /exc/README.md: -------------------------------------------------------------------------------- 1 | # Exceptions for Go as a Library 2 | 3 | by Tim Henderson (tim.tadh@gmail.com) 4 | 5 | Copyright 2016, Licensed under the GPL version 2. Please reach out to me 6 | directly if you require another licensing option. I am willing to work with you. 7 | 8 | ## Documentation 9 | 10 | - [![GoDoc](https://godoc.org/github.com/timtadh/data-structures/exc?status.svg)](https://godoc.org/github.com/timtadh/data-structures/exc) 11 | - [Explanation of Implementation](http://hackthology.com/exceptions-for-go-as-a-library.html) 12 | - [Explanation of Inheritance](http://hackthology.com/object-oriented-inheritance-in-go.html) 13 | 14 | ## Explanation 15 | 16 | Go (golang) lacks support for exceptions found in many other languages. There 17 | are good reasons for Go to not include exceptions. For instance, by making 18 | error handling explicit the programmer is forced to think concretely about 19 | the correct action to take. Fined grained control over the handling of errors 20 | using multiple return parameters is one of Go's strengths. 21 | 22 | However, there are cases where Go programs do not universally benefit from 23 | the explicit handling of errors. For instance, consider the following code: 24 | 25 | ```go 26 | func DoStuff(a, b, c interface{}) error { 27 | x, err := foo(a) 28 | if err != nil { 29 | return err 30 | } 31 | y, err := bar(b, x) 32 | if err != nil { 33 | return err 34 | } 35 | z, err := bax(c, x, y) 36 | if err != nil { 37 | return err 38 | } 39 | return baz(x, y, z) 40 | } 41 | ``` 42 | 43 | If Go had exceptions such code could be easily simplified: 44 | 45 | ```go 46 | func DoStuff(a, b, c interface{}) throws error { 47 | x := foo(a) 48 | y := bar(b, x) 49 | baz(x, y, bax(c, x, y) 50 | } 51 | ``` 52 | 53 | This library allow you to write go with exceptions and try-catch-finally 54 | blocks. It is not appropriate for all situations but can simplify some 55 | application code. Libraries and external APIs should continue to conform to 56 | the Go standard of returning error values. 57 | 58 | Here is an example of the `DoStuff` function where foo, bar and baz all throw 59 | exceptions instead of returning errors. (We will look at the case where they 60 | return errors that you want to turn into exceptions next). We want DoStuff to 61 | be an public API function and return an error: 62 | 63 | ```go 64 | func DoStuff(a, b, c interface{}) error { 65 | return exc.Try(func() { 66 | x := foo(a) 67 | y := bar(b, x) 68 | baz(x, y, bax(c, x, y) 69 | }).Error() 70 | } 71 | ``` 72 | 73 | Now let's consider the case where we want to catch the exception log and 74 | reraise it: 75 | 76 | ```go 77 | func DoStuff(a, b, c interface{}) error { 78 | return exc.Try(func() { 79 | x := foo(a) 80 | y := bar(b, x) 81 | baz(x, y, bax(c, x, y) 82 | }).Catch(&exc.Exception{}, func(t exc.Throwable) { 83 | log.Log(t) 84 | exc.Rethrow(t, exc.Errorf("rethrow after logging")) 85 | }).Error() 86 | } 87 | ``` 88 | 89 | Rethrow will chain the Throwable `t` with the new `*Error` created such that 90 | if/when the exception reaches the top level you know exactly how it was 91 | created and where it was rethrown. 92 | 93 | Ok, what about interacting with regular Go APIs which return errors? How can 94 | we turn those errors into exceptions? The easy was is to use the 95 | `ThrowOnError` function which is a sugar for: 96 | 97 | ```go 98 | if err != nil { 99 | ThrowErr(ErrorFrom(err) 100 | } 101 | ``` 102 | 103 | So converting out original `DoStuff` function we get 104 | 105 | ```go 106 | func DoStuff(a, b, c interface{}) { // Throws 107 | x, err := foo(a) 108 | exc.ThrowOnError(err) 109 | y, err := bar(b, x) 110 | exc.ThrowOnError(err) 111 | z, err := bax(c, x, y) 112 | exc.ThrowOnError(err) 113 | exc.ThrowOnError(baz(x, y, z)) 114 | } 115 | ``` 116 | 117 | This package also supports: catching user defined exceptions, catching 118 | multiple exception types, `Close` which works like the "try with resources" 119 | construct in Java 7+, (multiple) finally blocks, and a choice between 120 | propogating exceptions with `Unwind` or retrieving the error/exception with 121 | `Error` and `Exception` functions. 122 | 123 | One Gotcha! The `Try()` function creates a `*Block` struct. To execute the 124 | block you must either call: `Unwind`, `Error`, or `Exception`. `Unwind` 125 | executes the block, if there is an exception coming out of the block it 126 | continues to cause the program stack unwind. `Error` and `Exception` excute 127 | the block, but return the exception as a value to deal with in the usual Go 128 | way. 129 | 130 | -------------------------------------------------------------------------------- /exc/exc_test.go: -------------------------------------------------------------------------------- 1 | package exc 2 | 3 | import "testing" 4 | 5 | import "github.com/timtadh/data-structures/test" 6 | 7 | import ( 8 | "io" 9 | "os" 10 | ) 11 | 12 | type myException struct { 13 | Exception 14 | } 15 | 16 | func TestTry(x *testing.T) { 17 | t := (*test.T)(x) 18 | err := Try(func() { 19 | Throwf("%s", "this is a test") 20 | }).Error() 21 | t.Assert(err != nil, "wanted a non nil error got %v", err) 22 | } 23 | 24 | func TestTryPropogate(x *testing.T) { 25 | badfunc := func() { 26 | Try(func() { 27 | Throwf("test: %s", "this is a test") 28 | }).Unwind() 29 | } 30 | t := (*test.T)(x) 31 | err := Try(func() { 32 | badfunc() 33 | }).Error() 34 | t.Assert(err != nil, "wanted a non nil error got %v", err) 35 | } 36 | 37 | func TestTryCatch(x *testing.T) { 38 | t := (*test.T)(x) 39 | err := Try(func() { 40 | Throwf("%s", "this is a test") 41 | }).Catch(&Exception{}, func(e Throwable) { 42 | t.Log("Caught", e) 43 | }).Error() 44 | t.Log(err) 45 | t.Log(err == nil) 46 | t.AssertNil(err) 47 | } 48 | 49 | func TestTryCatchMyExceptionFail(x *testing.T) { 50 | t := (*test.T)(x) 51 | err := Try(func() { 52 | Throwf("%s", "this is a test") 53 | }).Catch(&myException{}, func(e Throwable) { 54 | t.Log("Caught", e) 55 | }).Error() 56 | t.Assert(err != nil, "should not have caught") 57 | } 58 | 59 | func TestTryCatchMyExceptionSuccess(x *testing.T) { 60 | t := (*test.T)(x) 61 | err := Try(func() { 62 | Throw(&myException{*Errorf("this is a test of my Exception").Exception()}) 63 | }).Catch(&myException{}, func(e Throwable) { 64 | t.Log("Caught", e) 65 | }).Error() 66 | t.Assert(err == nil, "should have caught %v", err) 67 | } 68 | 69 | func TestTryCatchMyExceptionWithException(x *testing.T) { 70 | t := (*test.T)(x) 71 | err := Try(func() { 72 | Throw(&myException{*Errorf("this is a test of my Exception").Exception()}) 73 | }).Catch(&Exception{}, func(e Throwable) { 74 | t.Log("Caught", e) 75 | }).Error() 76 | t.Assert(err == nil, "should have caught %v", err) 77 | } 78 | 79 | func TestTryCatchReraise(x *testing.T) { 80 | t := (*test.T)(x) 81 | err := Try(func() { 82 | Throwf("%s", "this is a test") 83 | }).Catch(&Exception{}, func(e Throwable) { 84 | t.Log("Caught", e) 85 | Rethrow(e, Errorf("rethrow")) 86 | }).Exception() 87 | t.Log(err) 88 | t.Assert(err != nil, "wanted a non nil error got %v", err) 89 | t.Assert(len(err.Exc().Errors) == 2, "wanted 2 errors got %v", err) 90 | } 91 | 92 | func TestTryCatchFinally(x *testing.T) { 93 | t := (*test.T)(x) 94 | finally := false 95 | err := Try(func() { 96 | Throwf("%s", "this is a test") 97 | }).Catch(&Exception{}, func(e Throwable) { 98 | t.Log("Caught", e) 99 | }).Finally(func() { 100 | t.Log("finally") 101 | finally = true 102 | }).Error() 103 | t.AssertNil(err) 104 | t.Assert(finally, "finally not run") 105 | } 106 | 107 | func TestTryCatchReraiseFinally(x *testing.T) { 108 | t := (*test.T)(x) 109 | finally := false 110 | err := Try(func() { 111 | Throwf("%s", "this is a test") 112 | }).Catch(&Exception{}, func(e Throwable) { 113 | t.Log("Caught", e) 114 | Rethrow(e, Errorf("rethrow")) 115 | }).Finally(func() { 116 | t.Log("finally") 117 | finally = true 118 | }).Error() 119 | t.Assert(err != nil, "err != nil, %v", err) 120 | t.Assert(finally, "finally not run") 121 | } 122 | 123 | func TestTryFinally(x *testing.T) { 124 | t := (*test.T)(x) 125 | finally := false 126 | err := Try(func() { 127 | Throwf("%s", "this is a test") 128 | }).Finally(func() { 129 | t.Log("finally") 130 | finally = true 131 | }).Error() 132 | t.Assert(err != nil, "err != nil, %v", err) 133 | t.Assert(finally, "finally not run") 134 | } 135 | 136 | func TestCloser(x *testing.T) { 137 | t := (*test.T)(x) 138 | var f *os.File = nil 139 | Close(func() io.Closer { 140 | var err error 141 | f, err = os.Create("/tmp/wizard") 142 | ThrowOnError(err) 143 | return f 144 | }, func(c io.Closer) { 145 | x := c.(*os.File) 146 | t.Log(x) 147 | }).Unwind() 148 | n, err := f.WriteString("hello\n") 149 | t.Log(n, err) 150 | t.Assert(err != nil, "expected err got nil") 151 | } 152 | 153 | func TestCloserError(x *testing.T) { 154 | t := (*test.T)(x) 155 | var f *os.File = nil 156 | e := Close(func() io.Closer { 157 | var err error 158 | f, err = os.Create("/tmp/wizard") 159 | ThrowOnError(err) 160 | return f 161 | }, func(c io.Closer) { 162 | x := c.(*os.File) 163 | ThrowOnError(Errorf("asdf")) 164 | t.Log(x) 165 | }).Error() 166 | t.Assert(e != nil, "expected err got nil") 167 | n, err := f.WriteString("hello\n") 168 | t.Log(n, err) 169 | t.Assert(err != nil, "expected err got nil") 170 | } 171 | -------------------------------------------------------------------------------- /set/sortedset.go: -------------------------------------------------------------------------------- 1 | package set 2 | 3 | import ( 4 | crand "crypto/rand" 5 | "encoding/binary" 6 | "log" 7 | mrand "math/rand" 8 | ) 9 | 10 | import ( 11 | "github.com/timtadh/data-structures/errors" 12 | "github.com/timtadh/data-structures/list" 13 | trand "github.com/timtadh/data-structures/rand" 14 | "github.com/timtadh/data-structures/types" 15 | ) 16 | 17 | var rand *mrand.Rand 18 | 19 | func init() { 20 | seed := make([]byte, 8) 21 | if _, err := crand.Read(seed); err == nil { 22 | rand = trand.ThreadSafeRand(int64(binary.BigEndian.Uint64(seed))) 23 | } else { 24 | panic(err) 25 | } 26 | } 27 | 28 | type MSortedSet struct { 29 | list.MSorted 30 | } 31 | 32 | func NewMSortedSet(s *SortedSet, marshal types.ItemMarshal, unmarshal types.ItemUnmarshal) *MSortedSet { 33 | return &MSortedSet{ 34 | MSorted: *list.NewMSorted(&s.Sorted, marshal, unmarshal), 35 | } 36 | } 37 | 38 | func (m *MSortedSet) SortedSet() *SortedSet { 39 | return &SortedSet{*m.MSorted.Sorted()} 40 | } 41 | 42 | // SortedSet is a list.Sorted and therefore has all of the methods 43 | // that list.Sorted has. So although they do not show up in the generated 44 | // docs you can just do this: 45 | // 46 | // s := NewSortedSet(10) 47 | // s.Add(types.Int(5)) 48 | // s2 = s.Union(FromSlice([]types.Hashable{types.Int(7)})) 49 | // fmt.Println(s2.Has(types.Int(7))) 50 | // fmt.Println(s.Has(types.Int(7))) 51 | // 52 | type SortedSet struct { 53 | list.Sorted 54 | } 55 | 56 | func NewSortedSet(initialSize int) *SortedSet { 57 | return &SortedSet{*list.NewSorted(initialSize, false)} 58 | } 59 | 60 | func FromSlice(items []types.Hashable) *SortedSet { 61 | s := NewSortedSet(len(items)) 62 | for _, item := range items { 63 | err := s.Add(item) 64 | if err != nil { 65 | log.Panic(err) 66 | } 67 | } 68 | return s 69 | } 70 | 71 | func SortedFromSet(s types.Set) *SortedSet { 72 | if s == nil || s.Size() == 0 { 73 | return NewSortedSet(0) 74 | } 75 | n := NewSortedSet(s.Size()) 76 | for i, next := s.Items()(); next != nil; i, next = next() { 77 | n.Add(i) 78 | } 79 | return n 80 | } 81 | 82 | func (s *SortedSet) Copy() *SortedSet { 83 | return &SortedSet{*s.Sorted.Copy()} 84 | } 85 | 86 | func (s *SortedSet) Random() (item types.Hashable, err error) { 87 | if s.Size() <= 0 { 88 | return nil, errors.Errorf("Set is empty") 89 | } else if s.Size() <= 1 { 90 | return s.Get(0) 91 | } 92 | i := rand.Intn(s.Size()) 93 | return s.Get(i) 94 | } 95 | 96 | // Unions s with o and returns a new Sorted Set 97 | func (s *SortedSet) Union(other types.Set) (types.Set, error) { 98 | if o, ok := other.(*SortedSet); ok { 99 | return s.union(o) 100 | } else { 101 | return Union(s, other) 102 | } 103 | } 104 | 105 | func (s *SortedSet) union(o *SortedSet) (n *SortedSet, err error) { 106 | n = NewSortedSet(s.Size() + o.Size() + 10) 107 | cs, si := s.Items()() 108 | co, oi := o.Items()() 109 | for si != nil || oi != nil { 110 | var err error 111 | if si == nil { 112 | err = n.Add(co) 113 | co, oi = oi() 114 | } else if oi == nil { 115 | err = n.Add(cs) 116 | cs, si = si() 117 | } else if cs.Less(co) { 118 | err = n.Add(cs) 119 | cs, si = si() 120 | } else { 121 | err = n.Add(co) 122 | co, oi = oi() 123 | } 124 | if err != nil { 125 | return nil, err 126 | } 127 | } 128 | return n, nil 129 | } 130 | 131 | // Unions s with o and returns a new Sorted Set 132 | func (s *SortedSet) Intersect(other types.Set) (types.Set, error) { 133 | return Intersect(s, other) 134 | } 135 | 136 | // Unions s with o and returns a new Sorted Set 137 | func (s *SortedSet) Subtract(other types.Set) (types.Set, error) { 138 | return Subtract(s, other) 139 | } 140 | 141 | // Are there any overlapping elements? 142 | func (s *SortedSet) Overlap(o *SortedSet) bool { 143 | cs, si := s.Items()() 144 | co, oi := o.Items()() 145 | for si != nil && oi != nil { 146 | s := cs.(types.Hashable) 147 | o := co.(types.Hashable) 148 | if s.Equals(o) { 149 | return true 150 | } else if s.Less(o) { 151 | cs, si = si() 152 | } else { 153 | co, oi = oi() 154 | } 155 | } 156 | return false 157 | } 158 | 159 | // Is s a subset of o? 160 | func (s *SortedSet) Subset(o types.Set) bool { 161 | return Subset(s, o) 162 | } 163 | 164 | // Is s a proper subset of o? 165 | func (s *SortedSet) ProperSubset(o types.Set) bool { 166 | return ProperSubset(s, o) 167 | } 168 | 169 | // Is s a superset of o? 170 | func (s *SortedSet) Superset(o types.Set) bool { 171 | return Superset(s, o) 172 | } 173 | 174 | // Is s a proper superset of o? 175 | func (s *SortedSet) ProperSuperset(o types.Set) bool { 176 | return ProperSuperset(s, o) 177 | } 178 | -------------------------------------------------------------------------------- /linked/linked.go: -------------------------------------------------------------------------------- 1 | package linked 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | ) 7 | 8 | import ( 9 | "github.com/timtadh/data-structures/errors" 10 | "github.com/timtadh/data-structures/list" 11 | "github.com/timtadh/data-structures/types" 12 | ) 13 | 14 | // A doubly linked list node. 15 | type Node struct { 16 | Data types.Hashable 17 | Next, Prev *Node 18 | } 19 | 20 | // Compares the Data of the node to the passed element. 21 | func (n *Node) Equals(b types.Equatable) bool { 22 | switch x := b.(type) { 23 | case *Node: 24 | return n.Data.Equals(x.Data) 25 | default: 26 | return n.Data.Equals(b) 27 | } 28 | } 29 | 30 | // Compares the Data of the node to the passed element. 31 | func (n *Node) Less(b types.Sortable) bool { 32 | switch x := b.(type) { 33 | case *Node: 34 | return n.Data.Less(x.Data) 35 | default: 36 | return n.Data.Less(b) 37 | } 38 | } 39 | 40 | // Hashes the Data of the node to the passed element. 41 | func (n *Node) Hash() int { 42 | return n.Data.Hash() 43 | } 44 | 45 | // A doubly linked list. There is no synchronization. 46 | // The fields are publically accessible to allow for easy customization. 47 | type LinkedList struct { 48 | Length int 49 | Head *Node 50 | Tail *Node 51 | } 52 | 53 | func New() *LinkedList { 54 | return &LinkedList{ 55 | Length: 0, 56 | Head: nil, 57 | Tail: nil, 58 | } 59 | } 60 | 61 | func (l *LinkedList) Size() int { 62 | return l.Length 63 | } 64 | 65 | func (l *LinkedList) Items() (it types.KIterator) { 66 | cur := l.Head 67 | it = func() (item types.Hashable, _ types.KIterator) { 68 | if cur == nil { 69 | return nil, nil 70 | } 71 | item = cur.Data 72 | cur = cur.Next 73 | return item, it 74 | } 75 | return it 76 | } 77 | 78 | func (l *LinkedList) Backwards() (it types.KIterator) { 79 | cur := l.Tail 80 | it = func() (item types.Hashable, _ types.KIterator) { 81 | if cur == nil { 82 | return nil, nil 83 | } 84 | item = cur.Data 85 | cur = cur.Prev 86 | return item, it 87 | } 88 | return it 89 | } 90 | 91 | func (l *LinkedList) Has(item types.Hashable) bool { 92 | for x, next := l.Items()(); next != nil; x, next = next() { 93 | if x.Equals(item) { 94 | return true 95 | } 96 | } 97 | return false 98 | } 99 | 100 | func (l *LinkedList) Push(item types.Hashable) (err error) { 101 | return l.EnqueBack(item) 102 | } 103 | 104 | func (l *LinkedList) Pop() (item types.Hashable, err error) { 105 | return l.DequeBack() 106 | } 107 | 108 | func (l *LinkedList) EnqueFront(item types.Hashable) (err error) { 109 | n := &Node{Data: item, Next: l.Head} 110 | if l.Head != nil { 111 | l.Head.Prev = n 112 | } else { 113 | l.Tail = n 114 | } 115 | l.Head = n 116 | l.Length++ 117 | return nil 118 | } 119 | 120 | func (l *LinkedList) EnqueBack(item types.Hashable) (err error) { 121 | n := &Node{Data: item, Prev: l.Tail} 122 | if l.Tail != nil { 123 | l.Tail.Next = n 124 | } else { 125 | l.Head = n 126 | } 127 | l.Tail = n 128 | l.Length++ 129 | return nil 130 | } 131 | 132 | func (l *LinkedList) DequeFront() (item types.Hashable, err error) { 133 | if l.Head == nil { 134 | return nil, errors.Errorf("List is empty") 135 | } 136 | item = l.Head.Data 137 | l.Head = l.Head.Next 138 | if l.Head != nil { 139 | l.Head.Prev = nil 140 | } else { 141 | l.Tail = nil 142 | } 143 | l.Length-- 144 | return item, nil 145 | } 146 | 147 | func (l *LinkedList) DequeBack() (item types.Hashable, err error) { 148 | if l.Tail == nil { 149 | return nil, errors.Errorf("List is empty") 150 | } 151 | item = l.Tail.Data 152 | l.Tail = l.Tail.Prev 153 | if l.Tail != nil { 154 | l.Tail.Next = nil 155 | } else { 156 | l.Head = nil 157 | } 158 | l.Length-- 159 | return item, nil 160 | } 161 | 162 | func (l *LinkedList) First() (item types.Hashable) { 163 | if l.Head == nil { 164 | return nil 165 | } 166 | return l.Head.Data 167 | } 168 | 169 | func (l *LinkedList) Last() (item types.Hashable) { 170 | if l.Tail == nil { 171 | return nil 172 | } 173 | return l.Tail.Data 174 | } 175 | 176 | // Can be compared to any types.IterableContainer 177 | func (l *LinkedList) Equals(b types.Equatable) bool { 178 | if o, ok := b.(types.IterableContainer); ok { 179 | return list.Equals(l, o) 180 | } else { 181 | return false 182 | } 183 | } 184 | 185 | // Can be compared to any types.IterableContainer 186 | func (l *LinkedList) Less(b types.Sortable) bool { 187 | if o, ok := b.(types.IterableContainer); ok { 188 | return list.Less(l, o) 189 | } else { 190 | return false 191 | } 192 | } 193 | 194 | func (l *LinkedList) Hash() int { 195 | return list.Hash(l) 196 | } 197 | 198 | func (l *LinkedList) String() string { 199 | if l.Length <= 0 { 200 | return "{}" 201 | } 202 | items := make([]string, 0, l.Length) 203 | for item, next := l.Items()(); next != nil; item, next = next() { 204 | items = append(items, fmt.Sprintf("%v", item)) 205 | } 206 | return "{" + strings.Join(items, ", ") + "}" 207 | } 208 | -------------------------------------------------------------------------------- /list/sorted.go: -------------------------------------------------------------------------------- 1 | package list 2 | 3 | import ( 4 | "bytes" 5 | "log" 6 | ) 7 | 8 | import ( 9 | "github.com/timtadh/data-structures/errors" 10 | "github.com/timtadh/data-structures/types" 11 | ) 12 | 13 | type MSorted struct { 14 | MList 15 | AllowDups bool 16 | } 17 | 18 | func NewMSorted(s *Sorted, marshal types.ItemMarshal, unmarshal types.ItemUnmarshal) *MSorted { 19 | return &MSorted{ 20 | MList: *NewMList(&s.list, marshal, unmarshal), 21 | AllowDups: s.allowDups, 22 | } 23 | } 24 | 25 | func (m *MSorted) Sorted() *Sorted { 26 | return &Sorted{m.MList.List, m.AllowDups} 27 | } 28 | 29 | func (m *MSorted) MarshalBinary() ([]byte, error) { 30 | var allowDups byte 31 | if m.AllowDups { 32 | allowDups = 1 33 | } else { 34 | allowDups = 0 35 | } 36 | b, err := m.MList.MarshalBinary() 37 | if err != nil { 38 | return nil, err 39 | } 40 | return bytes.Join([][]byte{[]byte{allowDups}, b}, []byte{}), nil 41 | } 42 | 43 | func (m *MSorted) UnmarshalBinary(bytes []byte) error { 44 | allowDups := bytes[0] 45 | if allowDups == 0 { 46 | m.AllowDups = false 47 | } else { 48 | m.AllowDups = true 49 | } 50 | return m.MList.UnmarshalBinary(bytes[1:]) 51 | } 52 | 53 | type Sorted struct { 54 | list List 55 | allowDups bool 56 | } 57 | 58 | // Creates a sorted list. 59 | func NewSorted(initialSize int, allowDups bool) *Sorted { 60 | return &Sorted{ 61 | list: *New(initialSize), 62 | allowDups: allowDups, 63 | } 64 | } 65 | 66 | // Creates a fixed size sorted list. 67 | func NewFixedSorted(size int, allowDups bool) *Sorted { 68 | return &Sorted{ 69 | list: *Fixed(size), 70 | allowDups: allowDups, 71 | } 72 | } 73 | 74 | func SortedFromSlice(items []types.Hashable, allowDups bool) *Sorted { 75 | s := NewSorted(len(items), allowDups) 76 | for _, item := range items { 77 | err := s.Add(item) 78 | if err != nil { 79 | log.Panic(err) 80 | } 81 | } 82 | return s 83 | } 84 | 85 | func (s *Sorted) Clear() { 86 | s.list.Clear() 87 | } 88 | 89 | func (s *Sorted) Size() int { 90 | return s.list.Size() 91 | } 92 | 93 | func (s *Sorted) Full() bool { 94 | return s.list.Full() 95 | } 96 | 97 | func (s *Sorted) Empty() bool { 98 | return s.list.Empty() 99 | } 100 | 101 | func (s *Sorted) Copy() *Sorted { 102 | return &Sorted{*s.list.Copy(), s.allowDups} 103 | } 104 | 105 | func (s *Sorted) Has(item types.Hashable) (has bool) { 106 | _, has, err := s.Find(item) 107 | if err != nil { 108 | log.Println(err) 109 | return false 110 | } 111 | return has 112 | } 113 | 114 | func (s *Sorted) Extend(other types.KIterator) (err error) { 115 | for item, next := other(); next != nil; item, next = next() { 116 | err := s.Add(item) 117 | if err != nil { 118 | return err 119 | } 120 | } 121 | return nil 122 | } 123 | 124 | func (s *Sorted) Item(item types.Hashable) (types.Hashable, error) { 125 | i, has, err := s.Find(item) 126 | if err != nil { 127 | return nil, err 128 | } else if !has { 129 | return nil, errors.Errorf("Item not found %v", item) 130 | } 131 | return s.Get(i) 132 | } 133 | 134 | func (s *Sorted) Get(i int) (item types.Hashable, err error) { 135 | return s.list.Get(i) 136 | } 137 | 138 | func (s *Sorted) Remove(i int) (err error) { 139 | return s.list.Remove(i) 140 | } 141 | 142 | func (s *Sorted) Add(item types.Hashable) (err error) { 143 | i, has, err := s.Find(item) 144 | if err != nil { 145 | return err 146 | } else if s.allowDups { 147 | return s.list.Insert(i, item) 148 | } else if !has { 149 | return s.list.Insert(i, item) 150 | } 151 | return nil 152 | } 153 | 154 | func (s *Sorted) Delete(item types.Hashable) (err error) { 155 | i, has, err := s.Find(item) 156 | if err != nil { 157 | return err 158 | } else if !has { 159 | return errors.Errorf("item %v not in the table", item) 160 | } 161 | return s.list.Remove(i) 162 | return nil 163 | } 164 | 165 | func (s *Sorted) Equals(b types.Equatable) bool { 166 | return s.list.Equals(b) 167 | } 168 | 169 | func (s *Sorted) Less(b types.Sortable) bool { 170 | return s.list.Less(b) 171 | } 172 | 173 | func (s *Sorted) Hash() int { 174 | return s.list.Hash() 175 | } 176 | 177 | func (s *Sorted) Items() (it types.KIterator) { 178 | return s.list.Items() 179 | } 180 | 181 | func (s *Sorted) ItemsInReverse() (it types.KIterator) { 182 | return s.list.ItemsInReverse() 183 | } 184 | 185 | func (s *Sorted) String() string { 186 | return s.list.String() 187 | } 188 | 189 | func (s *Sorted) Find(item types.Hashable) (int, bool, error) { 190 | var l int = 0 191 | var r int = s.Size() - 1 192 | var m int 193 | for l <= r { 194 | m = ((r - l) >> 1) + l 195 | im, err := s.list.Get(m) 196 | if err != nil { 197 | return -1, false, err 198 | } 199 | if item.Less(im) { 200 | r = m - 1 201 | } else if item.Equals(im) { 202 | for j := m; j > 0; j-- { 203 | ij_1, err := s.list.Get(j - 1) 204 | if err != nil { 205 | return -1, false, err 206 | } 207 | if !item.Equals(ij_1) { 208 | return j, true, nil 209 | } 210 | } 211 | return 0, true, nil 212 | } else { 213 | l = m + 1 214 | } 215 | } 216 | return l, false, nil 217 | } 218 | -------------------------------------------------------------------------------- /types/types.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | type Equatable interface { 4 | Equals(b Equatable) bool 5 | } 6 | 7 | type Sortable interface { 8 | Equatable 9 | Less(b Sortable) bool 10 | } 11 | 12 | type Hashable interface { 13 | Sortable 14 | Hash() int 15 | } 16 | 17 | type Marshaler interface { 18 | MarshalBinary() (data []byte, err error) 19 | UnmarshalBinary(data []byte) error 20 | } 21 | 22 | type MHashable interface { 23 | Hashable 24 | Marshaler 25 | } 26 | 27 | type ItemMarshal func(Hashable) ([]byte, error) 28 | type ItemUnmarshal func([]byte) (Hashable, error) 29 | 30 | type Iterator func() (item interface{}, next Iterator) 31 | type KIterator func() (key Hashable, next KIterator) 32 | type KVIterator func() (key Hashable, value interface{}, next KVIterator) 33 | type Coroutine func(send interface{}) (recv interface{}, next Coroutine) 34 | 35 | type Iterable interface { 36 | Iterate() Iterator 37 | } 38 | 39 | type KIterable interface { 40 | Keys() KIterator 41 | } 42 | 43 | type VIterable interface { 44 | Values() Iterator 45 | } 46 | 47 | type KVIterable interface { 48 | Iterate() KVIterator 49 | } 50 | 51 | type MapIterable interface { 52 | KIterable 53 | VIterable 54 | KVIterable 55 | } 56 | 57 | type Sized interface { 58 | Size() int 59 | } 60 | 61 | type MapOperable interface { 62 | Sized 63 | Has(key Hashable) bool 64 | Put(key Hashable, value interface{}) (err error) 65 | Get(key Hashable) (value interface{}, err error) 66 | Remove(key Hashable) (value interface{}, err error) 67 | } 68 | 69 | type WhereFunc func(value interface{}) bool 70 | 71 | type MultiMapOperable interface { 72 | Sized 73 | Has(key Hashable) bool 74 | Count(key Hashable) int 75 | Add(key Hashable, value interface{}) (err error) 76 | Replace(key Hashable, where WhereFunc, value interface{}) (err error) 77 | Find(key Hashable) KVIterator 78 | RemoveWhere(key Hashable, where WhereFunc) (err error) 79 | } 80 | 81 | type Map interface { 82 | MapIterable 83 | MapOperable 84 | } 85 | 86 | type MultiMap interface { 87 | MapIterable 88 | MultiMapOperable 89 | } 90 | 91 | type ContainerOperable interface { 92 | Has(item Hashable) bool 93 | } 94 | 95 | type ItemsOperable interface { 96 | Sized 97 | ContainerOperable 98 | Item(item Hashable) (Hashable, error) 99 | Add(item Hashable) (err error) 100 | Delete(item Hashable) (err error) 101 | Extend(items KIterator) (err error) 102 | } 103 | 104 | type OrderedOperable interface { 105 | Get(i int) (item Hashable, err error) 106 | Find(item Hashable) (idx int, has bool, err error) 107 | } 108 | 109 | type ListIterable interface { 110 | Items() KIterator 111 | } 112 | 113 | type IterableContainer interface { 114 | Sized 115 | ListIterable 116 | Has(item Hashable) bool 117 | } 118 | 119 | type StackOperable interface { 120 | Push(item Hashable) (err error) 121 | Pop() (item Hashable, err error) 122 | } 123 | 124 | type DequeOperable interface { 125 | EnqueFront(item Hashable) (err error) 126 | EnqueBack(item Hashable) (err error) 127 | DequeFront() (item Hashable, err error) 128 | DequeBack() (item Hashable, err error) 129 | First() (item Hashable) 130 | Last() (item Hashable) 131 | } 132 | 133 | type LinkedOperable interface { 134 | Sized 135 | ContainerOperable 136 | StackOperable 137 | DequeOperable 138 | } 139 | 140 | type ListOperable interface { 141 | Sized 142 | ContainerOperable 143 | Append(item Hashable) (err error) 144 | Get(i int) (item Hashable, err error) 145 | Set(i int, item Hashable) (err error) 146 | Insert(i int, item Hashable) (err error) 147 | Remove(i int) (err error) 148 | } 149 | 150 | type OrderedList interface { 151 | ListIterable 152 | OrderedOperable 153 | } 154 | 155 | type Set interface { 156 | Equatable 157 | ListIterable 158 | ItemsOperable 159 | Union(Set) (Set, error) 160 | Intersect(Set) (Set, error) 161 | Subtract(Set) (Set, error) 162 | Subset(Set) bool 163 | Superset(Set) bool 164 | ProperSubset(Set) bool 165 | ProperSuperset(Set) bool 166 | } 167 | 168 | type List interface { 169 | ListIterable 170 | ListOperable 171 | } 172 | 173 | type HList interface { 174 | Hashable 175 | List 176 | } 177 | 178 | type Stack interface { 179 | Sized 180 | ContainerOperable 181 | StackOperable 182 | } 183 | 184 | type Deque interface { 185 | Sized 186 | ContainerOperable 187 | DequeOperable 188 | } 189 | 190 | type Linked interface { 191 | LinkedOperable 192 | ListIterable 193 | } 194 | 195 | type Tree interface { 196 | Root() TreeNode 197 | } 198 | 199 | type TreeMap interface { 200 | Tree 201 | Map 202 | } 203 | 204 | type TreeNode interface { 205 | Key() Hashable 206 | Value() interface{} 207 | Children() TreeNodeIterator 208 | GetChild(int) TreeNode // if your tree can't support this simply panic 209 | // many of the utility functions do not require this 210 | // however, it is recommended that you implement it 211 | // if possible (for instance, post-order traversal 212 | // requires it). 213 | ChildCount() int // a negative value indicates this tree can't provide 214 | // an accurate count. 215 | } 216 | type TreeNodeIterator func() (node TreeNode, next TreeNodeIterator) 217 | 218 | type BinaryTreeNode interface { 219 | TreeNode 220 | Left() BinaryTreeNode 221 | Right() BinaryTreeNode 222 | } 223 | -------------------------------------------------------------------------------- /exc/exception.go: -------------------------------------------------------------------------------- 1 | package exc 2 | 3 | import ( 4 | "fmt" 5 | "runtime" 6 | "strings" 7 | ) 8 | 9 | import () 10 | 11 | // The *Error struct wraps up a regular error (could be any error) and a stack 12 | // trace. The idea is that it track where the error was created. 13 | type Error struct { 14 | Err error 15 | Stack []byte 16 | } 17 | 18 | // A drop in replacement for either fmt.Errorf or errors.Errorf. Creates and 19 | // *Error with a stack trace from where Errorf() was called from. 20 | func Errorf(format string, args ...interface{}) *Error { 21 | buf := make([]byte, 50000) 22 | n := runtime.Stack(buf, true) 23 | trace := make([]byte, n) 24 | copy(trace, buf) 25 | return &Error{ 26 | Err: fmt.Errorf(format, args...), 27 | Stack: trace, 28 | } 29 | } 30 | 31 | // Create an *Error from an existing error value. It will create a stack trace 32 | // to attach to the error from where FromError() was called from. 33 | func FromError(err error) *Error { 34 | buf := make([]byte, 50000) 35 | n := runtime.Stack(buf, true) 36 | trace := make([]byte, n) 37 | copy(trace, buf) 38 | return &Error{ 39 | Err: err, 40 | Stack: trace, 41 | } 42 | } 43 | 44 | // Format the error and stack trace. 45 | func (e *Error) Error() string { 46 | if e == nil { 47 | return "Error " 48 | } else { 49 | return fmt.Sprintf("%v\n\n%s", e.Err, string(e.Stack)) 50 | } 51 | } 52 | 53 | // Format the error and stack trace. 54 | func (e *Error) String() string { 55 | return e.Error() 56 | } 57 | 58 | // Create an Exception object from the Error. 59 | func (e *Error) Exception() *Exception { 60 | return &Exception{[]*Error{e}} 61 | } 62 | 63 | // The interface that represents what can be thrown (and caught) by this 64 | // library. All Throwables must be convertible to and *Exception, implement the 65 | // error interface and allow chaining on of extra errors so that they can be 66 | // Rethrown. 67 | type Throwable interface { 68 | Exc() *Exception 69 | Error() string 70 | Chain(e *Error) Throwable 71 | } 72 | 73 | // An implementation of Throwable you can base your custom Exception types off 74 | // of. It is also the type of Throwable thrown by Throwf. To "inherit" from 75 | // Exception use this formula: 76 | // 77 | // type MyException struct { 78 | // exc.Exception 79 | // } 80 | // 81 | // This ensures that your new exception will be catchable when *Exception is 82 | // supplied. See *Block.Catch for details. 83 | // 84 | type Exception struct { 85 | Errors []*Error 86 | } 87 | 88 | // Return itself. 89 | func (e *Exception) Exc() *Exception { 90 | return e 91 | } 92 | 93 | // Format an error string from the list of *Error. 94 | func (e *Exception) Error() string { 95 | errs := make([]string, 0, len(e.Errors)) 96 | for _, err := range e.Errors { 97 | errs = append(errs, err.Error()) 98 | } 99 | return fmt.Sprintf("Exception\n\n%v\n\nEnd Exception", strings.Join(errs, "\n---\n")) 100 | } 101 | 102 | // Format an error string from the list of *Error. 103 | func (e *Exception) String() string { 104 | return e.Error() 105 | } 106 | 107 | // Add another *Error to the list of *Error 108 | func (e *Exception) Chain(err *Error) Throwable { 109 | e.Errors = append(e.Errors, err) 110 | return e 111 | } 112 | 113 | // Join this exception with another exception. 114 | func (e *Exception) Join(exc *Exception) *Exception { 115 | errs := make([]*Error, 0, len(e.Errors)+len(exc.Errors)) 116 | errs = append(errs, e.Errors...) 117 | errs = append(errs, exc.Errors...) 118 | return &Exception{ 119 | Errors: errs, 120 | } 121 | } 122 | 123 | // Throw a new *Exception created from an *Error made with Errorf. Basically a 124 | // drop in replacement for everywhere you used fmt.Errorf but would now like to 125 | // throw an exception without creating a custom exception type. 126 | func Throwf(format string, args ...interface{}) { 127 | ThrowErr(Errorf(format, args...)) 128 | } 129 | 130 | // Throw an *Exception created from an *Error. 131 | func ThrowErr(e *Error) { 132 | throw(e.Exception()) 133 | } 134 | 135 | // Throw an *Exception created from a regular error interface object. The stack 136 | // trace for the exception will point to the throw rather than the creation of 137 | // the error object. 138 | func ThrowOnError(err error) { 139 | if err != nil { 140 | ThrowErr(FromError(err)) 141 | } 142 | } 143 | 144 | // Throw a Throwable object. This is how you throw a custom exception: 145 | // 146 | // type MyException struct { 147 | // exc.Exception 148 | // } 149 | // 150 | // exc.Try(func() { 151 | // exc.Throw(&MyException{*Errorf("My Exception").Exception()}) 152 | // }).Catch(&Exception{}, func(t Throwable) { 153 | // log.Log("caught!") 154 | // }).Unwind() 155 | // 156 | func Throw(e Throwable) { 157 | throw(e) 158 | } 159 | 160 | // Rethrow an object. It chains on the *Error as the reason for the rethrow and 161 | // where it occured. If you are inside of a catch block you should use this 162 | // method instead of Throw* 163 | // 164 | // exc.Try(func() { 165 | // exc.Throwf("wat!@!") 166 | // }).Catch(&Exception{}, func(e Throwable) { 167 | // t.Log("Caught", e) 168 | // exc.Rethrow(e, Errorf("rethrow")) 169 | // }).Unwind() 170 | // 171 | func Rethrow(e Throwable, err *Error) { 172 | throw(e.Chain(err)) 173 | } 174 | 175 | func throw(e Throwable) { 176 | panic(e) 177 | } 178 | -------------------------------------------------------------------------------- /trie/tst_node.go: -------------------------------------------------------------------------------- 1 | package trie 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | import ( 8 | "github.com/timtadh/data-structures/errors" 9 | . "github.com/timtadh/data-structures/types" 10 | ) 11 | 12 | const END = 0 13 | 14 | type KV struct { 15 | key ByteSlice 16 | value interface{} 17 | } 18 | 19 | func (self *KV) Key() Hashable { 20 | return self.key 21 | } 22 | 23 | func (self *KV) Value() interface{} { 24 | return self.value 25 | } 26 | 27 | func (self *KV) KeyEq(key ByteSlice) bool { 28 | if len(self.key) != len(key) { 29 | return false 30 | } 31 | for i := range self.key { 32 | if self.key[i] != key[i] { 33 | return false 34 | } 35 | } 36 | return true 37 | } 38 | 39 | type TSTNode struct { 40 | KV 41 | ch byte "byte to check at this node" 42 | l *TSTNode "left, < side" 43 | m *TSTNode "middle, == side" 44 | r *TSTNode "right, > side" 45 | accepting bool "is this an accepting node" 46 | } 47 | 48 | func NewTSTNode(ch byte) *TSTNode { 49 | return &TSTNode{ 50 | ch: ch, 51 | } 52 | } 53 | 54 | func NewAcceptingTSTNode(ch byte, key ByteSlice, value interface{}) *TSTNode { 55 | return &TSTNode{ 56 | KV: KV{ 57 | key: key, 58 | value: value, 59 | }, 60 | ch: ch, 61 | accepting: true, 62 | } 63 | } 64 | 65 | func (self *TSTNode) Copy() *TSTNode { 66 | node := &TSTNode{ 67 | KV: KV{ 68 | key: self.key, 69 | value: self.value, 70 | }, 71 | ch: self.ch, 72 | l: self.l, 73 | m: self.m, 74 | r: self.r, 75 | accepting: self.accepting, 76 | } 77 | return node 78 | } 79 | 80 | func (self *TSTNode) Internal() bool { 81 | return self.l != nil || self.m != nil || self.r != nil 82 | } 83 | 84 | func (self *TSTNode) make_child_slice() []*TSTNode { 85 | nodes := make([]*TSTNode, 0, 3) 86 | if self != nil { 87 | if self.l != nil { 88 | nodes = append(nodes, self.l) 89 | } 90 | if self.m != nil { 91 | nodes = append(nodes, self.m) 92 | } 93 | if self.r != nil { 94 | nodes = append(nodes, self.r) 95 | } 96 | } 97 | return nodes 98 | } 99 | 100 | func (self *TSTNode) Children() TreeNodeIterator { 101 | nodes := self.make_child_slice() 102 | var make_tn_iterator func(int) TreeNodeIterator 103 | make_tn_iterator = func(i int) TreeNodeIterator { 104 | return func() (kid TreeNode, next TreeNodeIterator) { 105 | if i < len(nodes) { 106 | return nodes[i], make_tn_iterator(i + 1) 107 | } 108 | return nil, nil 109 | } 110 | } 111 | return make_tn_iterator(0) 112 | } 113 | 114 | func (self *TSTNode) GetChild(i int) TreeNode { 115 | return self.make_child_slice()[i] 116 | } 117 | 118 | func (self *TSTNode) ChildCount() int { 119 | return len(self.make_child_slice()) 120 | } 121 | 122 | func (self *TSTNode) String() string { 123 | if self == nil { 124 | return "-" 125 | } 126 | ch := fmt.Sprintf("%x", self.ch) 127 | key := "" 128 | if self.ch == END { 129 | ch = "00" 130 | } 131 | if self.key != nil { 132 | key = string(self.key[:len(self.key)-1]) 133 | } 134 | if self.accepting { 135 | return fmt.Sprintf("[%v %x]", ch, key) 136 | } 137 | return fmt.Sprintf("%v(%v, %v, %v)", ch, self.l, self.m, self.r) 138 | } 139 | 140 | func (n *TSTNode) insert(key ByteSlice, val interface{}, d int) (*TSTNode, error) { 141 | if d >= len(key) { 142 | return nil, errors.TSTError("depth exceeds key length") 143 | } 144 | if key[len(key)-1] != END { 145 | return nil, errors.TSTError("key must end in 0") 146 | } 147 | if n == nil { 148 | // if the node is nil we found teh spot, make a new node and return it 149 | return NewAcceptingTSTNode(key[d], key, val), nil 150 | } else if !n.Internal() { 151 | // if it is a leaf node we either have found the symbol or we need to 152 | // split the node 153 | if n.accepting && n.KeyEq(key) { 154 | n = n.Copy() 155 | n.value = val 156 | return n, nil 157 | } else { 158 | return n.split(NewAcceptingTSTNode(key[d], key, val), d) 159 | } 160 | } else { 161 | // it is an internal node 162 | ch := key[d] 163 | n = n.Copy() 164 | if ch < n.ch { 165 | l, err := n.l.insert(key, val, d) 166 | if err != nil { 167 | return nil, err 168 | } 169 | n.l = l 170 | } else if ch == n.ch { 171 | if d+1 == len(key) && ch == END { 172 | n.m = n.m.Copy() 173 | n.m.value = val 174 | } else { 175 | m, err := n.m.insert(key, val, d+1) 176 | if err != nil { 177 | return nil, err 178 | } 179 | n.m = m 180 | } 181 | } else if ch > n.ch { 182 | r, err := n.r.insert(key, val, d) 183 | if err != nil { 184 | return nil, err 185 | } 186 | n.r = r 187 | } 188 | return n, nil 189 | } 190 | } 191 | 192 | /* a is the new (conflicting node) 193 | * b is the node that needs to be split 194 | * d is the depth 195 | * 196 | * both a and b must be accepting nodes. 197 | */ 198 | func (b *TSTNode) split(a *TSTNode, d int) (t *TSTNode, err error) { 199 | if !a.accepting { 200 | return nil, errors.TSTError("`a` must be an accepting node") 201 | } else if !b.accepting { 202 | return nil, errors.TSTError("`b` must be an accepting node") 203 | } 204 | if d >= len(b.key) { 205 | return nil, 206 | errors.TSTError("depth of split exceeds key length of b") 207 | } 208 | t = NewTSTNode(b.ch) 209 | b = b.Copy() 210 | a = a.Copy() 211 | if d+1 < len(b.key) { 212 | b.ch = b.key[d+1] 213 | } 214 | a.ch = a.key[d] 215 | if a.ch < t.ch { 216 | t.m = b 217 | t.l = a 218 | } else if a.ch == t.ch { 219 | m, err := b.split(a, d+1) 220 | if err != nil { 221 | return nil, err 222 | } 223 | t.m = m 224 | } else if a.ch > t.ch { 225 | t.m = b 226 | t.r = a 227 | } 228 | if t.m == nil { 229 | panic("m is nil") 230 | } 231 | return t, nil 232 | } 233 | -------------------------------------------------------------------------------- /list/sorted_test.go: -------------------------------------------------------------------------------- 1 | package list 2 | 3 | import "testing" 4 | 5 | import ( 6 | "fmt" 7 | ) 8 | 9 | import ( 10 | "github.com/timtadh/data-structures/types" 11 | ) 12 | 13 | func TestSortedAddMarshalUnmarshalGet(x *testing.T) { 14 | t := (*T)(x) 15 | SIZE := 100 16 | list := NewSorted(10, false) 17 | items := make([]types.Int, 0, SIZE) 18 | for i := 0; i < SIZE; i++ { 19 | item := types.Int(rand.Intn(10) + 1) 20 | items = append(items, item) 21 | t.assert_nil(list.Add(item)) 22 | } 23 | for _, item := range items { 24 | i, has, err := list.Find(item) 25 | t.assert("has", has) 26 | t.assert_nil(err) 27 | lg, err := list.Get(i) 28 | t.assert_nil(err) 29 | t.assert(fmt.Sprintf("i %v, items[i] == list.Get(i), %v, %v", i, item, lg), lg.Equals(item)) 30 | } 31 | marshal, unmarshal := types.IntMarshals() 32 | mlist1 := NewMSorted(list, marshal, unmarshal) 33 | bytes, err := mlist1.MarshalBinary() 34 | t.assert_nil(err) 35 | mlist2 := &MSorted{MList: MList{MarshalItem: marshal, UnmarshalItem: unmarshal}, AllowDups: false} 36 | t.assert_nil(mlist2.UnmarshalBinary(bytes)) 37 | list2 := mlist2.Sorted() 38 | for _, item := range items { 39 | i, has, err := list2.Find(item) 40 | t.assert("has", has) 41 | t.assert_nil(err) 42 | lg, err := list2.Get(i) 43 | t.assert_nil(err) 44 | t.assert(fmt.Sprintf("i %v, items[i] == list.Get(i), %v, %v", i, item, lg), lg.Equals(item)) 45 | } 46 | } 47 | 48 | func TestSortedAddHasDelete(x *testing.T) { 49 | t := (*T)(x) 50 | SIZE := 100 51 | set := NewSorted(10, false) 52 | items := make([]types.Int, 0, SIZE) 53 | for i := 0; i < SIZE; i++ { 54 | item := types.Int(rand.Intn(1000)) 55 | for set.Has(item) { 56 | item = types.Int(rand.Intn(1000)) 57 | } 58 | items = append(items, item) 59 | t.assert_nil(set.Add(item)) 60 | } 61 | for i, item := range items { 62 | t.assert(fmt.Sprintf("i %v, !set.Has(item)", i), set.Has(item)) 63 | } 64 | for _, item := range items { 65 | t.assert_nil(set.Delete(item)) 66 | } 67 | for i, item := range items { 68 | t.assert(fmt.Sprintf("i %v, !set.Has(item)", i), !set.Has(item)) 69 | } 70 | } 71 | 72 | func TestSortedAddHasCopyDeleteHas(x *testing.T) { 73 | t := (*T)(x) 74 | SIZE := 100 75 | set := NewSorted(10, false) 76 | items := make([]types.Int, 0, SIZE) 77 | for i := 0; i < SIZE; i++ { 78 | item := types.Int(rand.Intn(1000)) 79 | for set.Has(item) { 80 | item = types.Int(rand.Intn(1000)) 81 | } 82 | items = append(items, item) 83 | t.assert_nil(set.Add(item)) 84 | } 85 | for i, item := range items { 86 | t.assert(fmt.Sprintf("i %v, !set.Has(item)", i), set.Has(item)) 87 | } 88 | set2 := set.Copy() 89 | for _, item := range items { 90 | t.assert_nil(set.Delete(item)) 91 | } 92 | for i, item := range items { 93 | t.assert(fmt.Sprintf("i %v, set.Has(item)", i), !set.Has(item)) 94 | } 95 | for i, item := range items { 96 | t.assert(fmt.Sprintf("i %v, %v !set2.Has(item) %v", i, item, set2), set2.Has(item)) 97 | } 98 | } 99 | 100 | func TestSortedExtend(x *testing.T) { 101 | t := (*T)(x) 102 | SIZE := 100 103 | all := NewSorted(10, false) 104 | a := NewSorted(10, false) 105 | b := NewSorted(10, false) 106 | items := make([]types.ByteSlice, 0, SIZE) 107 | for i := 0; i < SIZE; i++ { 108 | item := t.randslice(rand.Intn(10) + 1) 109 | for all.Has(item) { 110 | item = t.randslice(rand.Intn(10) + 1) 111 | } 112 | items = append(items, item) 113 | t.assert_nil(all.Add(item)) 114 | if i < SIZE/2 { 115 | t.assert_nil(a.Add(item)) 116 | } else { 117 | t.assert_nil(b.Add(item)) 118 | } 119 | } 120 | t.assert_nil(a.Extend(b.Items())) 121 | for i := SIZE - 1; i >= 0; i-- { 122 | err := a.Delete(items[i]) 123 | t.assert_nil(err) 124 | t.assert(fmt.Sprintf("i %v, !a.Has(item)", i), !a.Has(items[i])) 125 | } 126 | } 127 | 128 | func TestSortedLess(x *testing.T) { 129 | t := (*T)(x) 130 | a := SortedFromSlice([]types.Hashable{types.Int(1), types.Int(2), types.Int(3)}, false) 131 | b := SortedFromSlice([]types.Hashable{types.Int(3), types.Int(2), types.Int(3)}, false) 132 | c := SortedFromSlice([]types.Hashable{types.Int(1), types.Int(0), types.Int(3)}, false) 133 | d := SortedFromSlice([]types.Hashable{types.Int(1), types.Int(2), types.Int(3)}, false) 134 | e := SortedFromSlice([]types.Hashable{types.Int(1), types.Int(2), types.Int(4)}, false) 135 | small := SortedFromSlice([]types.Hashable{types.Int(2), types.Int(4)}, false) 136 | big := SortedFromSlice([]types.Hashable{types.Int(0), types.Int(1), types.Int(2), types.Int(4)}, false) 137 | t.assert("b < a", b.Less(a)) 138 | t.assert("c < a", c.Less(a)) 139 | t.assert("b < c", b.Less(c)) 140 | t.assert("a !< d", a.Less(d) == false) 141 | t.assert("a !< e", e.Less(a) == false) 142 | t.assert("a < big", a.Less(big)) 143 | t.assert("small < a", small.Less(a)) 144 | t.assert("a !< small", a.Less(small) == false) 145 | } 146 | 147 | func TestSortedEqualsHash(x *testing.T) { 148 | t := (*T)(x) 149 | a := SortedFromSlice([]types.Hashable{types.Int(1), types.Int(2), types.Int(3)}, false) 150 | b := SortedFromSlice([]types.Hashable{types.Int(3), types.Int(2), types.Int(3)}, false) 151 | c := SortedFromSlice([]types.Hashable{types.Int(1), types.Int(0), types.Int(3)}, false) 152 | d := SortedFromSlice([]types.Hashable{types.Int(1), types.Int(2), types.Int(3)}, false) 153 | small := SortedFromSlice([]types.Hashable{types.Int(2), types.Int(4)}, false) 154 | empty := SortedFromSlice([]types.Hashable{}, false) 155 | t.assert("a != b", !a.Equals(b)) 156 | t.assert("c != a", !c.Equals(a)) 157 | t.assert("c != b", !c.Equals(b)) 158 | t.assert("a == d", a.Equals(d)) 159 | t.assert("c != small", !c.Equals(small)) 160 | t.assert("a.Hash() != b.Hash()", a.Hash() != b.Hash()) 161 | t.assert("c.Hash() != b.Hash()", c.Hash() != b.Hash()) 162 | t.assert("a.Hash() != d.Hash()", a.Hash() == d.Hash()) 163 | t.assert("d.Hash() != b.Hash()", d.Hash() != b.Hash()) 164 | t.assert("d.Hash() != empty.Hash()", d.Hash() != empty.Hash()) 165 | } 166 | -------------------------------------------------------------------------------- /exc/block.go: -------------------------------------------------------------------------------- 1 | package exc 2 | 3 | import ( 4 | "io" 5 | "reflect" 6 | ) 7 | 8 | import () 9 | 10 | type catch struct { 11 | exception reflect.Type 12 | catch func(Throwable) 13 | } 14 | 15 | // Represents a Try/Catch/Finally block. Created by a Try or Close function. 16 | // Executed by Unwind, Error, or Exception. You may add multiple Catch and 17 | // Finally expressions to your *Block with the Catch and Finally functions. 18 | // Catch and Finally can be in arbitrary orders unlike in languages with 19 | // syntatic support for Exceptions. I recommend you put your Catch expressions 20 | // before your finally Expressions. Finally and Catch expressions are evaluated 21 | // in the order they are declared. 22 | type Block struct { 23 | try func() 24 | catches []catch 25 | finallies []func() 26 | } 27 | 28 | // Start a Try/Catch/Finally block. Any exception thrown in the Try block can 29 | // be caught by a Catch block (if registered for the Exception type or a parent 30 | // exception type). 31 | func Try(try func()) *Block { 32 | return &Block{try: try} 33 | } 34 | 35 | // Start a Try/Catch/Finally block. You supply to functions, the first one 36 | // creates a closable resource and returns it. This resources is supplied to the 37 | // the second function which acts as a normal try. Whether the try fails or 38 | // succeeds the Close() function is always called on the resource that was 39 | // created (and returned) by the first function. Further, catch and finally 40 | // functions may be chained onto the Close function. However, they will be run 41 | // after the Close function is called on the resource and will not have access 42 | // to it. 43 | // 44 | // Finally, if the function to created the closable object fails, it will not be 45 | // cleaned up if it was partially initialized. This is because it was never 46 | // returned. There are also ways to deal with that situation using an outer 47 | // Try/Finally. 48 | func Close(makeCloser func() io.Closer, try func(io.Closer)) *Block { 49 | var c io.Closer = nil 50 | return Try(func() { 51 | Try(func() { 52 | c = makeCloser() 53 | try(c) 54 | }).Finally(func() { 55 | if c != nil { 56 | ThrowOnError(c.Close()) 57 | } 58 | }).Unwind() 59 | }) 60 | } 61 | 62 | // Add a catch function for a specific Throwable. If your Throwable struct 63 | // "inherits" from another struct like so: 64 | // 65 | // type MyException struct { 66 | // exc.Exception 67 | // } 68 | // 69 | // Then you can catch *MyException with *Exception. eg: 70 | // 71 | // exc.Try(func() { 72 | // Throw(&MyException{*Errorf("My Exception").Exception()}) 73 | // }).Catch(&Exception{}, func(t Throwable) { 74 | // log.Log("caught!") 75 | // }).Unwind() 76 | // 77 | // Catch blocks are only run in the case of an thrown exception. Regular panics 78 | // are ignored and will behave as normal. 79 | // 80 | func (b *Block) Catch(exc Throwable, do func(Throwable)) *Block { 81 | b.catches = append(b.catches, catch{reflect.TypeOf(exc), do}) 82 | return b 83 | } 84 | 85 | // Add a finally block. These will be run whether or not an exception was 86 | // thrown. However, if a regular panic occurs this function will not be run and 87 | // the panic will behave as normal. 88 | func (b *Block) Finally(finally func()) *Block { 89 | b.finallies = append(b.finallies, finally) 90 | return b 91 | } 92 | 93 | // Run the Try/Catch/Finally *Block. If there is an uncaught (or rethrown) 94 | // exception continue to propogate it up the stack (unwinding it). This would be 95 | // the normal behavoir in language which natively support exceptions. 96 | // 97 | // The Block will NOT BE RUN unless this method, Error, or Exception is called. 98 | // This could lead to an difficult to track down bug! 99 | func (b *Block) Unwind() { 100 | err := b.run() 101 | if err != nil { 102 | panic(err) 103 | } 104 | } 105 | 106 | // Run the Try/Catch/Finally *Block. If there is an uncaught (or rethrown) 107 | // exception continue return it as an error. 108 | // 109 | // The Block will NOT BE RUN unless this method, Unwind, or Exception is called. 110 | // This could lead to an difficult to track down bug! 111 | func (b *Block) Error() error { 112 | err := b.run() 113 | if err != nil { 114 | return err 115 | } else { 116 | return nil 117 | } 118 | } 119 | 120 | // Run the Try/Catch/Finally *Block. If there is an uncaught (or rethrown) 121 | // exception continue return it as a Throwable. 122 | // 123 | // The Block will NOT BE RUN unless this method, Unwind, or Error is called. 124 | // This could lead to an difficult to track down bug! 125 | func (b *Block) Exception() Throwable { 126 | t := b.run() 127 | if t != nil { 128 | return t 129 | } else { 130 | return nil 131 | } 132 | } 133 | 134 | func (b *Block) run() Throwable { 135 | err := b.exec() 136 | if err != nil { 137 | t := reflect.TypeOf(err) 138 | for _, c := range b.catches { 139 | // errors.Logf("DEBUG", "trying to catch %v with %v %v %v", t, c.exception, t.ConvertibleTo(c.exception), t.AssignableTo(c.exception)) 140 | if isa(t, c.exception) { 141 | err = Try(func() { c.catch(err) }).exec() 142 | break 143 | } 144 | } 145 | } 146 | for _, finally := range b.finallies { 147 | finally() 148 | } 149 | return err 150 | } 151 | 152 | func (b *Block) exec() (err Throwable) { 153 | defer func() { 154 | if e := recover(); e != nil { 155 | switch exc := e.(type) { 156 | case Throwable: 157 | err = exc 158 | default: 159 | panic(e) 160 | } 161 | } 162 | }() 163 | b.try() 164 | return 165 | } 166 | 167 | func isa(a, b reflect.Type) bool { 168 | // errors.Logf("DEBUG", "isa a %v b %v a.Kind() %v", a, b, a.Kind()) 169 | if is(a, b) { 170 | return true 171 | } 172 | if !(a.Kind() == reflect.Ptr && b.Kind() == reflect.Ptr) { 173 | return false 174 | } 175 | a = a.Elem() 176 | for a.Kind() == reflect.Struct && a.NumField() > 0 { 177 | a = a.Field(0).Type 178 | if is(reflect.PtrTo(a), b) { 179 | return true 180 | } 181 | } 182 | return false 183 | } 184 | 185 | func is(a, b reflect.Type) bool { 186 | // errors.Logf("DEBUG", "is a %v b %v %v %v", a, b, a.ConvertibleTo(b), a.AssignableTo(b)) 187 | if a.AssignableTo(b) { 188 | return true 189 | } 190 | return false 191 | } 192 | -------------------------------------------------------------------------------- /tree/avl/avltree_test.go: -------------------------------------------------------------------------------- 1 | package avl 2 | 3 | import ( 4 | "testing" 5 | 6 | crand "crypto/rand" 7 | "encoding/binary" 8 | mrand "math/rand" 9 | 10 | trand "github.com/timtadh/data-structures/rand" 11 | "github.com/timtadh/data-structures/test" 12 | "github.com/timtadh/data-structures/types" 13 | ) 14 | 15 | var rand *mrand.Rand 16 | 17 | func init() { 18 | seed := make([]byte, 8) 19 | if _, err := crand.Read(seed); err == nil { 20 | rand = trand.ThreadSafeRand(int64(binary.BigEndian.Uint64(seed))) 21 | } else { 22 | panic(err) 23 | } 24 | } 25 | 26 | func randstr(length int) types.String { 27 | return types.String(test.RandStr(length)) 28 | } 29 | 30 | func TestAvlPutHasGetRemove(t *testing.T) { 31 | 32 | type record struct { 33 | key types.String 34 | value types.String 35 | } 36 | 37 | records := make([]*record, 400) 38 | var tree *AvlNode 39 | var err error 40 | var val interface{} 41 | var updated bool 42 | 43 | ranrec := func() *record { 44 | return &record{randstr(20), randstr(20)} 45 | } 46 | 47 | for i := range records { 48 | r := ranrec() 49 | records[i] = r 50 | tree, updated = tree.Put(r.key, types.String("")) 51 | if updated { 52 | t.Error("should have not been updated") 53 | } 54 | tree, updated = tree.Put(r.key, r.value) 55 | if !updated { 56 | t.Error("should have been updated") 57 | } 58 | if tree.Size() != (i + 1) { 59 | t.Error("size was wrong", tree.Size(), i+1) 60 | } 61 | } 62 | 63 | for _, r := range records { 64 | if has := tree.Has(r.key); !has { 65 | t.Error("Missing key") 66 | } 67 | if has := tree.Has(randstr(12)); has { 68 | t.Error("Table has extra key") 69 | } 70 | if val, err := tree.Get(r.key); err != nil { 71 | t.Error(err, val.(types.String), r.value) 72 | } else if !(val.(types.String)).Equals(r.value) { 73 | t.Error("wrong value") 74 | } 75 | } 76 | 77 | for i, x := range records { 78 | if tree, val, err = tree.Remove(x.key); err != nil { 79 | t.Error(err) 80 | } else if !(val.(types.String)).Equals(x.value) { 81 | t.Error("wrong value") 82 | } 83 | for _, r := range records[i+1:] { 84 | if has := tree.Has(r.key); !has { 85 | t.Error("Missing key") 86 | } 87 | if has := tree.Has(randstr(12)); has { 88 | t.Error("Table has extra key") 89 | } 90 | if val, err := tree.Get(r.key); err != nil { 91 | t.Error(err) 92 | } else if !(val.(types.String)).Equals(r.value) { 93 | t.Error("wrong value") 94 | } 95 | } 96 | if tree.Size() != (len(records) - (i + 1)) { 97 | t.Error("size was wrong", tree.Size(), (len(records) - (i + 1))) 98 | } 99 | } 100 | } 101 | 102 | func TestImmutableAvlPutHasGetRemove(t *testing.T) { 103 | 104 | type record struct { 105 | key types.String 106 | value types.String 107 | } 108 | 109 | records := make([]*record, 400) 110 | var tree *ImmutableAvlNode 111 | var err error 112 | var val interface{} 113 | var updated bool 114 | 115 | ranrec := func() *record { 116 | return &record{randstr(20), randstr(20)} 117 | } 118 | 119 | for i := range records { 120 | r := ranrec() 121 | records[i] = r 122 | tree, updated = tree.Put(r.key, types.String("")) 123 | if updated { 124 | t.Error("should have not been updated") 125 | } 126 | tree, updated = tree.Put(r.key, r.value) 127 | if !updated { 128 | t.Error("should have been updated") 129 | } 130 | if tree.Size() != (i + 1) { 131 | t.Error("size was wrong", tree.Size(), i+1) 132 | } 133 | } 134 | 135 | for _, r := range records { 136 | if has := tree.Has(r.key); !has { 137 | t.Error("Missing key") 138 | } 139 | if has := tree.Has(randstr(12)); has { 140 | t.Error("Table has extra key") 141 | } 142 | if val, err := tree.Get(r.key); err != nil { 143 | t.Error(err, val.(types.String), r.value) 144 | } else if !(val.(types.String)).Equals(r.value) { 145 | t.Error("wrong value") 146 | } 147 | } 148 | 149 | for i, x := range records { 150 | if tree, val, err = tree.Remove(x.key); err != nil { 151 | t.Error(err) 152 | } else if !(val.(types.String)).Equals(x.value) { 153 | t.Error("wrong value") 154 | } 155 | for _, r := range records[i+1:] { 156 | if has := tree.Has(r.key); !has { 157 | t.Error("Missing key") 158 | } 159 | if has := tree.Has(randstr(12)); has { 160 | t.Error("Table has extra key") 161 | } 162 | if val, err := tree.Get(r.key); err != nil { 163 | t.Error(err) 164 | } else if !(val.(types.String)).Equals(r.value) { 165 | t.Error("wrong value") 166 | } 167 | } 168 | if tree.Size() != (len(records) - (i + 1)) { 169 | t.Error("size was wrong", tree.Size(), (len(records) - (i + 1))) 170 | } 171 | } 172 | } 173 | 174 | func TestIterators(t *testing.T) { 175 | var data []int = []int{ 176 | 1, 5, 7, 9, 12, 13, 17, 18, 19, 20, 177 | } 178 | var order []int = []int{ 179 | 6, 1, 8, 2, 4, 9, 5, 7, 0, 3, 180 | } 181 | 182 | test := func(tree types.TreeMap) { 183 | t.Logf("%T", tree) 184 | for j := range order { 185 | if err := tree.Put(types.Int(data[order[j]]), order[j]); err != nil { 186 | t.Error(err) 187 | } 188 | } 189 | 190 | j := 0 191 | for k, v, next := tree.Iterate()(); next != nil; k, v, next = next() { 192 | if !k.Equals(types.Int(data[j])) { 193 | t.Error("Wrong key") 194 | } 195 | if v.(int) != j { 196 | t.Error("Wrong value") 197 | } 198 | j += 1 199 | } 200 | 201 | j = 0 202 | for k, next := tree.Keys()(); next != nil; k, next = next() { 203 | if !k.Equals(types.Int(data[j])) { 204 | t.Error("Wrong key") 205 | } 206 | j += 1 207 | } 208 | 209 | j = 0 210 | for v, next := tree.Values()(); next != nil; v, next = next() { 211 | if v.(int) != j { 212 | t.Error("Wrong value") 213 | } 214 | j += 1 215 | } 216 | } 217 | test(NewAvlTree()) 218 | test(NewImmutableAvlTree()) 219 | } 220 | 221 | func BenchmarkAvlTree(b *testing.B) { 222 | b.StopTimer() 223 | 224 | type record struct { 225 | key types.String 226 | value types.String 227 | } 228 | 229 | records := make([]*record, 100) 230 | 231 | ranrec := func() *record { 232 | return &record{randstr(20), randstr(20)} 233 | } 234 | 235 | for i := range records { 236 | records[i] = ranrec() 237 | } 238 | 239 | b.StartTimer() 240 | for i := 0; i < b.N; i++ { 241 | t := NewAvlTree() 242 | for _, r := range records { 243 | t.Put(r.key, r.value) 244 | } 245 | for _, r := range records { 246 | t.Remove(r.key) 247 | } 248 | } 249 | } 250 | 251 | func BenchmarkImmutableAvlTree(b *testing.B) { 252 | b.StopTimer() 253 | 254 | type record struct { 255 | key types.String 256 | value types.String 257 | } 258 | 259 | records := make([]*record, 100) 260 | 261 | ranrec := func() *record { 262 | return &record{randstr(20), randstr(20)} 263 | } 264 | 265 | for i := range records { 266 | records[i] = ranrec() 267 | } 268 | 269 | b.StartTimer() 270 | for i := 0; i < b.N; i++ { 271 | t := NewImmutableAvlTree() 272 | for _, r := range records { 273 | t.Put(r.key, r.value) 274 | } 275 | for _, r := range records { 276 | t.Remove(r.key) 277 | } 278 | } 279 | } 280 | -------------------------------------------------------------------------------- /hashtable/hashtable_test.go: -------------------------------------------------------------------------------- 1 | package hashtable 2 | 3 | import ( 4 | "testing" 5 | 6 | crand "crypto/rand" 7 | "encoding/binary" 8 | mrand "math/rand" 9 | 10 | trand "github.com/timtadh/data-structures/rand" 11 | "github.com/timtadh/data-structures/test" 12 | "github.com/timtadh/data-structures/tree/avl" 13 | . "github.com/timtadh/data-structures/types" 14 | ) 15 | 16 | var rand *mrand.Rand 17 | 18 | func init() { 19 | seed := make([]byte, 8) 20 | if _, err := crand.Read(seed); err == nil { 21 | rand = trand.ThreadSafeRand(int64(binary.BigEndian.Uint64(seed))) 22 | } else { 23 | panic(err) 24 | } 25 | } 26 | 27 | func randstr(length int) String { 28 | return String(test.RandStr(length)) 29 | } 30 | 31 | func TestMake(t *testing.T) { 32 | NewHashTable(12) 33 | } 34 | 35 | func TestHashable(t *testing.T) { 36 | a := String("asdf") 37 | b := String("asdf") 38 | c := String("csfd") 39 | if !a.Equals(b) { 40 | t.Error("a != b") 41 | } 42 | if a.Hash() != b.Hash() { 43 | t.Error("hash(a) != hash(b)") 44 | } 45 | if a.Equals(c) { 46 | t.Error("a == c") 47 | } 48 | if a.Hash() == c.Hash() { 49 | t.Error("hash(a) == hash(c)") 50 | } 51 | } 52 | 53 | func TestPutHasGetRemove(t *testing.T) { 54 | 55 | type record struct { 56 | key String 57 | value String 58 | } 59 | 60 | ranrec := func() *record { 61 | return &record{ 62 | String(randstr(20)), 63 | String(randstr(20)), 64 | } 65 | } 66 | 67 | test := func(table MapOperable) { 68 | records := make([]*record, 400) 69 | for i := range records { 70 | r := ranrec() 71 | records[i] = r 72 | err := table.Put(r.key, String("")) 73 | if err != nil { 74 | t.Error(err) 75 | } 76 | err = table.Put(r.key, r.value) 77 | if err != nil { 78 | t.Error(err) 79 | } 80 | if table.Size() != (i + 1) { 81 | t.Error("size was wrong", table.Size(), i+1) 82 | } 83 | } 84 | 85 | for _, r := range records { 86 | if has := table.Has(r.key); !has { 87 | t.Error(table, "Missing key") 88 | } 89 | if has := table.Has(randstr(12)); has { 90 | t.Error("Table has extra key") 91 | } 92 | if val, err := table.Get(r.key); err != nil { 93 | t.Error(err) 94 | } else if !(val.(String)).Equals(r.value) { 95 | t.Error("wrong value") 96 | } 97 | } 98 | 99 | for i, x := range records { 100 | if val, err := table.Remove(x.key); err != nil { 101 | t.Error(err) 102 | } else if !(val.(String)).Equals(x.value) { 103 | t.Error("wrong value") 104 | } 105 | for _, r := range records[i+1:] { 106 | if has := table.Has(r.key); !has { 107 | t.Error("Missing key") 108 | } 109 | if has := table.Has(randstr(12)); has { 110 | t.Error("Table has extra key") 111 | } 112 | if val, err := table.Get(r.key); err != nil { 113 | t.Error(err) 114 | } else if !(val.(String)).Equals(r.value) { 115 | t.Error("wrong value") 116 | } 117 | } 118 | if table.Size() != (len(records) - (i + 1)) { 119 | t.Error("size was wrong", table.Size(), (len(records) - (i + 1))) 120 | } 121 | } 122 | } 123 | 124 | test(NewHashTable(64)) 125 | test(NewLinearHash()) 126 | } 127 | 128 | func TestIterate(t *testing.T) { 129 | 130 | test := func(table Map) { 131 | t.Logf("%T", table) 132 | for k, v, next := table.Iterate()(); next != nil; k, v, next = next() { 133 | t.Errorf("Should never reach here %v %v %v", k, v, next) 134 | } 135 | records := make(map[String]String) 136 | for i := 0; i < 100; i++ { 137 | k := randstr(8) 138 | v := randstr(8) 139 | records[k] = v 140 | err := table.Put(k, String("")) 141 | if err != nil { 142 | t.Error(err) 143 | } 144 | err = table.Put(k, v) 145 | if err != nil { 146 | t.Error(err) 147 | } 148 | if table.Size() != (i + 1) { 149 | t.Error("size was wrong", table.Size(), i+1) 150 | } 151 | } 152 | newrecs := make(map[String]String) 153 | for k, v, next := table.Iterate()(); next != nil; k, v, next = next() { 154 | if v2, has := records[k.(String)]; !has { 155 | t.Error("bad key in table") 156 | } else if !v2.Equals(v.(Equatable)) { 157 | t.Error("values don't agree") 158 | } 159 | newrecs[k.(String)] = v.(String) 160 | } 161 | if len(records) != len(newrecs) { 162 | t.Error("iterate missed records") 163 | } 164 | for k, v := range records { 165 | if v2, has := newrecs[k]; !has { 166 | t.Error("key went missing") 167 | } else if !v2.Equals(v) { 168 | t.Error("values don't agree") 169 | } 170 | } 171 | } 172 | test(NewHashTable(64)) 173 | test(NewLinearHash()) 174 | test(avl.NewAvlTree()) 175 | test(avl.NewImmutableAvlTree()) 176 | } 177 | 178 | func BenchmarkGoMap(b *testing.B) { 179 | b.StopTimer() 180 | 181 | type record struct { 182 | key string 183 | value string 184 | } 185 | 186 | records := make([]*record, 100) 187 | 188 | ranrec := func() *record { 189 | return &record{string(randstr(20)), string(randstr(20))} 190 | } 191 | 192 | for i := range records { 193 | records[i] = ranrec() 194 | } 195 | 196 | b.StartTimer() 197 | for i := 0; i < b.N; i++ { 198 | m := make(map[string]string) 199 | for _, r := range records { 200 | m[r.key] = r.value 201 | } 202 | for _, r := range records { 203 | delete(m, r.key) 204 | } 205 | } 206 | } 207 | 208 | func BenchmarkHash(b *testing.B) { 209 | b.StopTimer() 210 | 211 | type record struct { 212 | key String 213 | value String 214 | } 215 | 216 | records := make([]*record, 100) 217 | 218 | ranrec := func() *record { 219 | return &record{randstr(20), randstr(20)} 220 | } 221 | 222 | for i := range records { 223 | records[i] = ranrec() 224 | } 225 | 226 | b.StartTimer() 227 | for i := 0; i < b.N; i++ { 228 | t := NewHashTable(128) 229 | for _, r := range records { 230 | t.Put(r.key, r.value) 231 | } 232 | for _, r := range records { 233 | t.Remove(r.key) 234 | } 235 | } 236 | } 237 | 238 | func BenchmarkMLHash(b *testing.B) { 239 | b.StopTimer() 240 | 241 | type record struct { 242 | key String 243 | value String 244 | } 245 | 246 | records := make([]*record, 100) 247 | 248 | ranrec := func() *record { 249 | return &record{randstr(20), randstr(20)} 250 | } 251 | 252 | for i := range records { 253 | records[i] = ranrec() 254 | } 255 | 256 | b.StartTimer() 257 | for i := 0; i < b.N; i++ { 258 | t := NewLinearHash() 259 | for _, r := range records { 260 | t.Put(r.key, r.value) 261 | } 262 | for _, r := range records { 263 | t.Remove(r.key) 264 | } 265 | } 266 | } 267 | 268 | func BenchmarkMLHashBetter(b *testing.B) { 269 | b.StopTimer() 270 | 271 | type record struct { 272 | key String 273 | value String 274 | } 275 | 276 | records := make([]*record, 100) 277 | 278 | ranrec := func() *record { 279 | return &record{randstr(20), randstr(20)} 280 | } 281 | 282 | for i := range records { 283 | records[i] = ranrec() 284 | } 285 | 286 | b.StartTimer() 287 | for i := 0; i < b.N; i++ { 288 | t := NewLinearHash() 289 | for _, r := range records { 290 | t.Put(r.key, r.value) 291 | } 292 | for _, _, next := t.Iterate()(); next != nil; _, _, next = next() { 293 | } 294 | for _, next := t.Keys()(); next != nil; _, next = next() { 295 | } 296 | for _, next := t.Values()(); next != nil; _, next = next() { 297 | } 298 | for _, next := t.Values()(); next != nil; _, next = next() { 299 | } 300 | for _, next := t.Values()(); next != nil; _, next = next() { 301 | } 302 | for _, r := range records { 303 | t.Remove(r.key) 304 | } 305 | } 306 | } 307 | -------------------------------------------------------------------------------- /trie/tst.go: -------------------------------------------------------------------------------- 1 | package trie 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | ) 7 | 8 | import ( 9 | "github.com/timtadh/data-structures/errors" 10 | "github.com/timtadh/data-structures/tree" 11 | . "github.com/timtadh/data-structures/types" 12 | ) 13 | 14 | type TST struct { 15 | heads [256]*TSTNode 16 | } 17 | 18 | func New() *TST { 19 | return &TST{} 20 | } 21 | 22 | func (self *TST) ValidateKey(key []byte) error { 23 | if key == nil { 24 | return errors.InvalidKey(key, "key is nil") 25 | } 26 | if len(key) == 0 { 27 | return errors.InvalidKey(key, "len(key) == 0") 28 | } 29 | for _, ch := range key { 30 | if ch == 0 { 31 | return errors.InvalidKey(key, "key contains a null byte") 32 | } 33 | } 34 | return nil 35 | } 36 | 37 | func (self *TST) Put(key []byte, value interface{}) (err error) { 38 | if err := self.ValidateKey(key); err != nil { 39 | return err 40 | } 41 | symbol := append(key, END) 42 | node, err := self.heads[symbol[0]].insert(symbol, value, 1) 43 | if err != nil { 44 | return err 45 | } 46 | self.heads[symbol[0]] = node 47 | return nil 48 | } 49 | 50 | func (self *TST) Has(key []byte) bool { 51 | if _, err := self.Get(key); err != nil { 52 | return false 53 | } 54 | return true 55 | } 56 | 57 | func (self *TST) Get(key []byte) (value interface{}, err error) { 58 | type entry struct { 59 | n *TSTNode 60 | d int 61 | } 62 | if err := self.ValidateKey(key); err != nil { 63 | return nil, err 64 | } 65 | symbol := append(key, END) 66 | next := &entry{self.heads[symbol[0]], 1} 67 | for next != nil { 68 | if next.n == nil { 69 | return nil, errors.NotFound(key) 70 | } else if next.n.Internal() { 71 | ch := symbol[next.d] 72 | if ch < next.n.ch { 73 | next = &entry{next.n.l, next.d} 74 | } else if ch == next.n.ch { 75 | next = &entry{next.n.m, next.d + 1} 76 | } else if ch > next.n.ch { 77 | next = &entry{next.n.r, next.d} 78 | } 79 | } else if next.n.KeyEq(symbol) { 80 | return next.n.value, nil 81 | } else { 82 | return nil, errors.NotFound(key) 83 | } 84 | } 85 | // should never reach ... 86 | return nil, errors.NotFound(key) 87 | } 88 | 89 | func (self *TST) Remove(key []byte) (value interface{}, err error) { 90 | if err := self.ValidateKey(key); err != nil { 91 | return nil, err 92 | } 93 | symbol := ByteSlice(append(key, END)) 94 | check := func(n *TSTNode, err error) (*TSTNode, error) { 95 | if err != nil { 96 | return nil, err 97 | } else if n == nil { 98 | return nil, nil 99 | } else if !n.Internal() && n.key == nil { 100 | return nil, nil 101 | } 102 | return n, nil 103 | } 104 | var remove func(n *TSTNode, d int) (*TSTNode, error) 105 | remove = func(n *TSTNode, d int) (*TSTNode, error) { 106 | if n == nil { 107 | return nil, errors.NotFound(key) 108 | } else if n.Internal() { 109 | n = n.Copy() 110 | ch := symbol[d] 111 | if ch < n.ch { 112 | l, err := check(remove(n.l, d)) 113 | if err != nil { 114 | return nil, err 115 | } 116 | n.l = l 117 | } else if ch == n.ch { 118 | m, err := check(remove(n.m, d+1)) 119 | if err != nil { 120 | return nil, err 121 | } 122 | n.m = m 123 | } else if ch > n.ch { 124 | r, err := check(remove(n.r, d)) 125 | if err != nil { 126 | return nil, err 127 | } 128 | n.r = r 129 | } 130 | } else if n.key.Equals(symbol) { 131 | // found it 132 | value = n.value 133 | return nil, nil 134 | } else { 135 | return nil, errors.NotFound(key) 136 | } 137 | return n, nil 138 | } 139 | n, err := remove(self.heads[symbol[0]], 1) 140 | if err != nil { 141 | return nil, err 142 | } 143 | self.heads[symbol[0]] = n 144 | return value, nil 145 | } 146 | 147 | func (self *TST) PrefixFind(prefix ByteSlice) KVIterator { 148 | if len(prefix) == 0 { 149 | return self.Iterate() 150 | } 151 | type entry struct { 152 | n *TSTNode 153 | d int 154 | } 155 | var root *TSTNode = nil 156 | next := &entry{self.heads[prefix[0]], 1} 157 | for { 158 | if next.n == nil { 159 | break 160 | } else if next.n.Internal() { 161 | if next.d == len(prefix) { 162 | root = next.n 163 | break 164 | } 165 | ch := prefix[next.d] 166 | if ch < next.n.ch { 167 | next = &entry{next.n.l, next.d} 168 | } else if ch == next.n.ch { 169 | next = &entry{next.n.m, next.d + 1} 170 | } else if ch > next.n.ch { 171 | next = &entry{next.n.r, next.d} 172 | } 173 | } else if next.n.accepting && next.n.key[:len(prefix)].Equals(prefix) { 174 | root = next.n 175 | break 176 | } else { 177 | break 178 | } 179 | } 180 | if root == nil { 181 | return func() (Hashable, interface{}, KVIterator) { 182 | return nil, nil, nil 183 | } 184 | } 185 | tni := tree.TraverseTreePreOrder(root) 186 | var kv_iterator KVIterator 187 | kv_iterator = func() (key Hashable, value interface{}, next KVIterator) { 188 | var tn TreeNode 189 | for { 190 | tn, tni = tni() 191 | if tni == nil { 192 | return nil, nil, nil 193 | } 194 | n := tn.(*TSTNode) 195 | if n.accepting { 196 | return n.key[:len(n.key)-1], n.value, kv_iterator 197 | } 198 | } 199 | } 200 | return kv_iterator 201 | } 202 | 203 | func (self *TST) Iterate() KVIterator { 204 | tnis := make([]TreeNodeIterator, 0, 256) 205 | for _, n := range self.heads { 206 | if n != nil { 207 | tnis = append(tnis, tree.TraverseTreePreOrder(n)) 208 | } 209 | } 210 | tni := ChainTreeNodeIterators(tnis...) 211 | var kv_iterator KVIterator 212 | kv_iterator = func() (key Hashable, value interface{}, next KVIterator) { 213 | var tn TreeNode 214 | for { 215 | if tni == nil { 216 | return nil, nil, nil 217 | } 218 | tn, tni = tni() 219 | if tni == nil { 220 | return nil, nil, nil 221 | } 222 | n := tn.(*TSTNode) 223 | if n.accepting { 224 | return n.key[:len(n.key)-1], n.value, kv_iterator 225 | } 226 | } 227 | } 228 | return kv_iterator 229 | } 230 | 231 | func (self *TST) Items() (vi KIterator) { 232 | return MakeItemsIterator(self) 233 | } 234 | 235 | func (self *TST) Keys() KIterator { 236 | return MakeKeysIterator(self) 237 | } 238 | 239 | func (self *TST) Values() Iterator { 240 | return MakeValuesIterator(self) 241 | } 242 | 243 | func (self *TST) String() string { 244 | var nodes []string 245 | for i, n := range self.heads { 246 | if n == nil { 247 | continue 248 | } 249 | nodes = append(nodes, fmt.Sprintf("%x:(%v)", i, n)) 250 | } 251 | return fmt.Sprintf("TST<%v>", strings.Join(nodes, ", ")) 252 | } 253 | 254 | func (self *TST) Dotty() string { 255 | header := "digraph TST {\nrankdir=LR;\n" 256 | node_root := "%v[label=\"%v\", shape=\"rect\"];" 257 | node := 258 | "%s[label=\"%v\", shape=\"circle\", fillcolor=\"#aaffff\", style=\"filled\"];" 259 | node_acc := "%v[label=\"%v\", fillcolor=\"#aaffaa\" style=\"filled\"];" 260 | edge := "%v -> %v [label=\"%v\"];" 261 | footer := "\n}\n" 262 | 263 | var nodes []string 264 | var edges []string 265 | 266 | name := func() string { 267 | return fmt.Sprintf("n%d", len(nodes)) 268 | } 269 | 270 | var dotnode func(cur *TSTNode, parent, ch string) 271 | dotnode = func(cur *TSTNode, parent, ch string) { 272 | n := name() 273 | if cur.accepting { 274 | nodes = append( 275 | nodes, 276 | fmt.Sprintf(node_acc, n, string(cur.key[:len(cur.key)-1])), 277 | ) 278 | } else if cur.ch == END { 279 | nodes = append( 280 | nodes, 281 | fmt.Sprintf(node, n, "\\\\0"), 282 | ) 283 | } else { 284 | nodes = append( 285 | nodes, 286 | fmt.Sprintf(node, n, fmt.Sprintf("%c", cur.ch)), 287 | ) 288 | } 289 | edges = append( 290 | edges, 291 | fmt.Sprintf(edge, parent, n, ch), 292 | ) 293 | if cur.l != nil { 294 | dotnode(cur.l, n, "<") 295 | } 296 | if cur.m != nil { 297 | dotnode(cur.m, n, "=") 298 | } 299 | if cur.r != nil { 300 | dotnode(cur.r, n, ">") 301 | } 302 | } 303 | 304 | root := name() 305 | nodes = append(nodes, fmt.Sprintf(node_root, root, "heads")) 306 | 307 | for k, head := range self.heads { 308 | if head == nil { 309 | continue 310 | } 311 | dotnode(head, root, fmt.Sprintf("%c", byte(k))) 312 | } 313 | 314 | ret := header + strings.Join(nodes, "\n") 315 | ret += "\n" + strings.Join(edges, "\n") 316 | ret += footer 317 | return ret 318 | } 319 | -------------------------------------------------------------------------------- /types/int.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "encoding/binary" 5 | ) 6 | 7 | import ( 8 | "github.com/timtadh/data-structures/errors" 9 | ) 10 | 11 | type Int8 int8 12 | type UInt8 uint8 13 | type Int16 int16 14 | type UInt16 uint16 15 | type Int32 int32 16 | type UInt32 uint32 17 | type Int64 int64 18 | type UInt64 uint64 19 | type Int int 20 | type UInt uint 21 | 22 | func (self *Int8) MarshalBinary() ([]byte, error) { 23 | bytes := make([]byte, 0) 24 | bytes[0] = uint8(*self) 25 | return bytes, nil 26 | } 27 | 28 | func (self *Int8) UnmarshalBinary(data []byte) error { 29 | if len(data) != 1 { 30 | return errors.Errorf("data wrong size") 31 | } 32 | *self = Int8(data[0]) 33 | return nil 34 | } 35 | 36 | func (self Int8) Equals(other Equatable) bool { 37 | if o, ok := other.(Int8); ok { 38 | return self == o 39 | } else { 40 | return false 41 | } 42 | } 43 | 44 | func (self Int8) Less(other Sortable) bool { 45 | if o, ok := other.(Int8); ok { 46 | return self < o 47 | } else { 48 | return false 49 | } 50 | } 51 | 52 | func (self Int8) Hash() int { 53 | return int(self) 54 | } 55 | 56 | func (self *UInt8) MarshalBinary() ([]byte, error) { 57 | bytes := make([]byte, 0) 58 | bytes[0] = uint8(*self) 59 | return bytes, nil 60 | } 61 | 62 | func (self *UInt8) UnmarshalBinary(data []byte) error { 63 | if len(data) != 1 { 64 | return errors.Errorf("data wrong size") 65 | } 66 | *self = UInt8(data[0]) 67 | return nil 68 | } 69 | 70 | func (self UInt8) Equals(other Equatable) bool { 71 | if o, ok := other.(UInt8); ok { 72 | return self == o 73 | } else { 74 | return false 75 | } 76 | } 77 | 78 | func (self UInt8) Less(other Sortable) bool { 79 | if o, ok := other.(UInt8); ok { 80 | return self < o 81 | } else { 82 | return false 83 | } 84 | } 85 | 86 | func (self UInt8) Hash() int { 87 | return int(self) 88 | } 89 | 90 | func (self *Int16) MarshalBinary() ([]byte, error) { 91 | bytes := make([]byte, 2) 92 | binary.BigEndian.PutUint16(bytes, uint16(*self)) 93 | return bytes, nil 94 | } 95 | 96 | func (self *Int16) UnmarshalBinary(data []byte) error { 97 | if len(data) != 2 { 98 | return errors.Errorf("data wrong size") 99 | } 100 | *self = Int16(binary.BigEndian.Uint16(data)) 101 | return nil 102 | } 103 | 104 | func (self Int16) Equals(other Equatable) bool { 105 | if o, ok := other.(Int16); ok { 106 | return self == o 107 | } else { 108 | return false 109 | } 110 | } 111 | 112 | func (self Int16) Less(other Sortable) bool { 113 | if o, ok := other.(Int16); ok { 114 | return self < o 115 | } else { 116 | return false 117 | } 118 | } 119 | 120 | func (self Int16) Hash() int { 121 | return int(self) 122 | } 123 | 124 | func (self *UInt16) MarshalBinary() ([]byte, error) { 125 | bytes := make([]byte, 2) 126 | binary.BigEndian.PutUint16(bytes, uint16(*self)) 127 | return bytes, nil 128 | } 129 | 130 | func (self *UInt16) UnmarshalBinary(data []byte) error { 131 | if len(data) != 2 { 132 | return errors.Errorf("data wrong size") 133 | } 134 | *self = UInt16(binary.BigEndian.Uint16(data)) 135 | return nil 136 | } 137 | 138 | func (self UInt16) Equals(other Equatable) bool { 139 | if o, ok := other.(UInt16); ok { 140 | return self == o 141 | } else { 142 | return false 143 | } 144 | } 145 | 146 | func (self UInt16) Less(other Sortable) bool { 147 | if o, ok := other.(UInt16); ok { 148 | return self < o 149 | } else { 150 | return false 151 | } 152 | } 153 | 154 | func (self UInt16) Hash() int { 155 | return int(self) 156 | } 157 | 158 | func (self *Int32) MarshalBinary() ([]byte, error) { 159 | bytes := make([]byte, 4) 160 | binary.BigEndian.PutUint32(bytes, uint32(*self)) 161 | return bytes, nil 162 | } 163 | 164 | func (self *Int32) UnmarshalBinary(data []byte) error { 165 | if len(data) != 4 { 166 | return errors.Errorf("data wrong size") 167 | } 168 | *self = Int32(binary.BigEndian.Uint32(data)) 169 | return nil 170 | } 171 | 172 | func (self Int32) Equals(other Equatable) bool { 173 | if o, ok := other.(Int32); ok { 174 | return self == o 175 | } else { 176 | return false 177 | } 178 | } 179 | 180 | func (self Int32) Less(other Sortable) bool { 181 | if o, ok := other.(Int32); ok { 182 | return self < o 183 | } else { 184 | return false 185 | } 186 | } 187 | 188 | func (self *UInt32) MarshalBinary() ([]byte, error) { 189 | bytes := make([]byte, 4) 190 | binary.BigEndian.PutUint32(bytes, uint32(*self)) 191 | return bytes, nil 192 | } 193 | 194 | func (self *UInt32) UnmarshalBinary(data []byte) error { 195 | if len(data) != 4 { 196 | return errors.Errorf("data wrong size") 197 | } 198 | *self = UInt32(binary.BigEndian.Uint32(data)) 199 | return nil 200 | } 201 | 202 | func (self Int32) Hash() int { 203 | return int(self) 204 | } 205 | 206 | func (self UInt32) Equals(other Equatable) bool { 207 | if o, ok := other.(UInt32); ok { 208 | return self == o 209 | } else { 210 | return false 211 | } 212 | } 213 | 214 | func (self UInt32) Less(other Sortable) bool { 215 | if o, ok := other.(UInt32); ok { 216 | return self < o 217 | } else { 218 | return false 219 | } 220 | } 221 | 222 | func (self UInt32) Hash() int { 223 | return int(self) 224 | } 225 | 226 | func (self *Int64) MarshalBinary() ([]byte, error) { 227 | bytes := make([]byte, 8) 228 | binary.BigEndian.PutUint64(bytes, uint64(*self)) 229 | return bytes, nil 230 | } 231 | 232 | func (self *Int64) UnmarshalBinary(data []byte) error { 233 | if len(data) != 8 { 234 | return errors.Errorf("data wrong size") 235 | } 236 | *self = Int64(binary.BigEndian.Uint64(data)) 237 | return nil 238 | } 239 | 240 | func (self Int64) Equals(other Equatable) bool { 241 | if o, ok := other.(Int64); ok { 242 | return self == o 243 | } else { 244 | return false 245 | } 246 | } 247 | 248 | func (self Int64) Less(other Sortable) bool { 249 | if o, ok := other.(Int64); ok { 250 | return self < o 251 | } else { 252 | return false 253 | } 254 | } 255 | 256 | func (self Int64) Hash() int { 257 | return int(self>>32) ^ int(self) 258 | } 259 | 260 | func (self *UInt64) MarshalBinary() ([]byte, error) { 261 | bytes := make([]byte, 8) 262 | binary.BigEndian.PutUint64(bytes, uint64(*self)) 263 | return bytes, nil 264 | } 265 | 266 | func (self *UInt64) UnmarshalBinary(data []byte) error { 267 | if len(data) != 8 { 268 | return errors.Errorf("data wrong size") 269 | } 270 | *self = UInt64(binary.BigEndian.Uint64(data)) 271 | return nil 272 | } 273 | 274 | func (self UInt64) Equals(other Equatable) bool { 275 | if o, ok := other.(UInt64); ok { 276 | return self == o 277 | } else { 278 | return false 279 | } 280 | } 281 | 282 | func (self UInt64) Less(other Sortable) bool { 283 | if o, ok := other.(UInt64); ok { 284 | return self < o 285 | } else { 286 | return false 287 | } 288 | } 289 | 290 | func (self UInt64) Hash() int { 291 | return int(self>>32) ^ int(self) 292 | } 293 | 294 | func (self *Int) MarshalBinary() ([]byte, error) { 295 | bytes := make([]byte, 4) 296 | binary.BigEndian.PutUint32(bytes, uint32(*self)) 297 | return bytes, nil 298 | } 299 | 300 | func (self *Int) UnmarshalBinary(data []byte) error { 301 | if len(data) != 4 { 302 | return errors.Errorf("data wrong size") 303 | } 304 | *self = Int(binary.BigEndian.Uint32(data)) 305 | return nil 306 | } 307 | 308 | func (self Int) Equals(other Equatable) bool { 309 | if o, ok := other.(Int); ok { 310 | return self == o 311 | } else { 312 | return false 313 | } 314 | } 315 | 316 | func (self Int) Less(other Sortable) bool { 317 | if o, ok := other.(Int); ok { 318 | return self < o 319 | } else { 320 | return false 321 | } 322 | } 323 | 324 | func (self Int) Hash() int { 325 | return int(self) 326 | } 327 | 328 | func (self *UInt) MarshalBinary() ([]byte, error) { 329 | bytes := make([]byte, 4) 330 | binary.BigEndian.PutUint32(bytes, uint32(*self)) 331 | return bytes, nil 332 | } 333 | 334 | func (self *UInt) UnmarshalBinary(data []byte) error { 335 | if len(data) != 4 { 336 | return errors.Errorf("data wrong size") 337 | } 338 | *self = UInt(binary.BigEndian.Uint32(data)) 339 | return nil 340 | } 341 | 342 | func (self UInt) Equals(other Equatable) bool { 343 | if o, ok := other.(UInt); ok { 344 | return self == o 345 | } else { 346 | return false 347 | } 348 | } 349 | 350 | func (self UInt) Less(other Sortable) bool { 351 | if o, ok := other.(UInt); ok { 352 | return self < o 353 | } else { 354 | return false 355 | } 356 | } 357 | 358 | func (self UInt) Hash() int { 359 | return int(self) 360 | } 361 | -------------------------------------------------------------------------------- /tree/avl/avltree.go: -------------------------------------------------------------------------------- 1 | package avl 2 | 3 | import ( 4 | "github.com/timtadh/data-structures/errors" 5 | "github.com/timtadh/data-structures/tree" 6 | "github.com/timtadh/data-structures/types" 7 | ) 8 | 9 | func abs(i int) int { 10 | if i < 0 { 11 | return -i 12 | } 13 | return i 14 | } 15 | 16 | func max(a, b int) int { 17 | if a > b { 18 | return a 19 | } 20 | return b 21 | } 22 | 23 | type AvlTree struct { 24 | root *AvlNode 25 | } 26 | 27 | func NewAvlTree() *AvlTree { 28 | return &AvlTree{} 29 | } 30 | 31 | func (self *AvlTree) Root() types.TreeNode { 32 | return self.root 33 | } 34 | 35 | func (self *AvlTree) Size() int { 36 | return self.root.Size() 37 | } 38 | 39 | func (self *AvlTree) Has(key types.Hashable) bool { 40 | return self.root.Has(key) 41 | } 42 | 43 | func (self *AvlTree) Put(key types.Hashable, value interface{}) (err error) { 44 | self.root, _ = self.root.Put(key, value) 45 | return nil 46 | } 47 | 48 | func (self *AvlTree) Get(key types.Hashable) (value interface{}, err error) { 49 | return self.root.Get(key) 50 | } 51 | 52 | func (self *AvlTree) Remove(key types.Hashable) (value interface{}, err error) { 53 | new_root, value, err := self.root.Remove(key) 54 | if err != nil { 55 | return nil, err 56 | } 57 | self.root = new_root 58 | return value, nil 59 | } 60 | 61 | func (self *AvlTree) Iterate() types.KVIterator { 62 | return self.root.Iterate() 63 | } 64 | 65 | func (self *AvlTree) Items() (vi types.KIterator) { 66 | return types.MakeItemsIterator(self) 67 | } 68 | 69 | func (self *AvlTree) Values() types.Iterator { 70 | return self.root.Values() 71 | } 72 | 73 | func (self *AvlTree) Keys() types.KIterator { 74 | return self.root.Keys() 75 | } 76 | 77 | type AvlNode struct { 78 | key types.Hashable 79 | value interface{} 80 | height int 81 | left *AvlNode 82 | right *AvlNode 83 | } 84 | 85 | func (self *AvlNode) Has(key types.Hashable) (has bool) { 86 | if self == nil { 87 | return false 88 | } 89 | if self.key.Equals(key) { 90 | return true 91 | } else if key.Less(self.key) { 92 | return self.left.Has(key) 93 | } else { 94 | return self.right.Has(key) 95 | } 96 | } 97 | 98 | func (self *AvlNode) Get(key types.Hashable) (value interface{}, err error) { 99 | if self == nil { 100 | return nil, errors.NotFound(key) 101 | } 102 | if self.key.Equals(key) { 103 | return self.value, nil 104 | } else if key.Less(self.key) { 105 | return self.left.Get(key) 106 | } else { 107 | return self.right.Get(key) 108 | } 109 | } 110 | 111 | func (self *AvlNode) pop_node(node *AvlNode) *AvlNode { 112 | if node == nil { 113 | panic("node can't be nil") 114 | } else if node.left != nil && node.right != nil { 115 | panic("node must not have both left and right") 116 | } 117 | 118 | if self == nil { 119 | return nil 120 | } else if self == node { 121 | var n *AvlNode 122 | if node.left != nil { 123 | n = node.left 124 | } else if node.right != nil { 125 | n = node.right 126 | } else { 127 | n = nil 128 | } 129 | node.left = nil 130 | node.right = nil 131 | return n 132 | } 133 | 134 | if node.key.Less(self.key) { 135 | self.left = self.left.pop_node(node) 136 | } else { 137 | self.right = self.right.pop_node(node) 138 | } 139 | 140 | self.height = max(self.left.Height(), self.right.Height()) + 1 141 | return self 142 | } 143 | 144 | func (self *AvlNode) push_node(node *AvlNode) *AvlNode { 145 | if node == nil { 146 | panic("node can't be nil") 147 | } else if node.left != nil || node.right != nil { 148 | panic("node now be a leaf") 149 | } 150 | 151 | if self == nil { 152 | node.height = 1 153 | return node 154 | } else if node.key.Less(self.key) { 155 | self.left = self.left.push_node(node) 156 | } else { 157 | self.right = self.right.push_node(node) 158 | } 159 | self.height = max(self.left.Height(), self.right.Height()) + 1 160 | return self 161 | } 162 | 163 | func (self *AvlNode) rotate_right() *AvlNode { 164 | if self == nil { 165 | return self 166 | } 167 | if self.left == nil { 168 | return self 169 | } 170 | new_root := self.left.rmd() 171 | self = self.pop_node(new_root) 172 | new_root.left = self.left 173 | new_root.right = self.right 174 | self.left = nil 175 | self.right = nil 176 | return new_root.push_node(self) 177 | } 178 | 179 | func (self *AvlNode) rotate_left() *AvlNode { 180 | if self == nil { 181 | return self 182 | } 183 | if self.right == nil { 184 | return self 185 | } 186 | new_root := self.right.lmd() 187 | self = self.pop_node(new_root) 188 | new_root.left = self.left 189 | new_root.right = self.right 190 | self.left = nil 191 | self.right = nil 192 | return new_root.push_node(self) 193 | } 194 | 195 | func (self *AvlNode) balance() *AvlNode { 196 | if self == nil { 197 | return self 198 | } 199 | for abs(self.left.Height()-self.right.Height()) > 2 { 200 | if self.left.Height() > self.right.Height() { 201 | self = self.rotate_right() 202 | } else { 203 | self = self.rotate_left() 204 | } 205 | } 206 | return self 207 | } 208 | 209 | func (self *AvlNode) Put(key types.Hashable, value interface{}) (_ *AvlNode, updated bool) { 210 | if self == nil { 211 | return &AvlNode{key: key, value: value, height: 1}, false 212 | } 213 | 214 | if self.key.Equals(key) { 215 | self.value = value 216 | return self, true 217 | } 218 | 219 | if key.Less(self.key) { 220 | self.left, updated = self.left.Put(key, value) 221 | } else { 222 | self.right, updated = self.right.Put(key, value) 223 | } 224 | if !updated { 225 | self.height += 1 226 | return self.balance(), updated 227 | } 228 | return self, updated 229 | } 230 | 231 | func (self *AvlNode) Remove(key types.Hashable) (_ *AvlNode, value interface{}, err error) { 232 | if self == nil { 233 | return nil, nil, errors.NotFound(key) 234 | } 235 | 236 | if self.key.Equals(key) { 237 | if self.left != nil && self.right != nil { 238 | if self.left.Size() < self.right.Size() { 239 | lmd := self.right.lmd() 240 | lmd.left = self.left 241 | return self.right, self.value, nil 242 | } else { 243 | rmd := self.left.rmd() 244 | rmd.right = self.right 245 | return self.left, self.value, nil 246 | } 247 | } else if self.left == nil { 248 | return self.right, self.value, nil 249 | } else if self.right == nil { 250 | return self.left, self.value, nil 251 | } else { 252 | return nil, self.value, nil 253 | } 254 | } 255 | if key.Less(self.key) { 256 | self.left, value, err = self.left.Remove(key) 257 | } else { 258 | self.right, value, err = self.right.Remove(key) 259 | } 260 | if err != nil { 261 | return self.balance(), value, err 262 | } 263 | return self, value, err 264 | } 265 | 266 | func (self *AvlNode) Height() int { 267 | if self == nil { 268 | return 0 269 | } 270 | return self.height 271 | } 272 | 273 | func (self *AvlNode) Size() int { 274 | if self == nil { 275 | return 0 276 | } 277 | return 1 + self.left.Size() + self.right.Size() 278 | } 279 | 280 | func (self *AvlNode) Key() types.Hashable { 281 | return self.key 282 | } 283 | 284 | func (self *AvlNode) Value() interface{} { 285 | return self.value 286 | } 287 | 288 | func (self *AvlNode) Left() types.BinaryTreeNode { 289 | if self.left == nil { 290 | return nil 291 | } 292 | return self.left 293 | } 294 | 295 | func (self *AvlNode) Right() types.BinaryTreeNode { 296 | if self.right == nil { 297 | return nil 298 | } 299 | return self.right 300 | } 301 | 302 | func (self *AvlNode) GetChild(i int) types.TreeNode { 303 | return types.DoGetChild(self, i) 304 | } 305 | 306 | func (self *AvlNode) ChildCount() int { 307 | return types.DoChildCount(self) 308 | } 309 | 310 | func (self *AvlNode) Children() types.TreeNodeIterator { 311 | return types.MakeChildrenIterator(self) 312 | } 313 | 314 | func (self *AvlNode) Iterate() types.KVIterator { 315 | tni := tree.TraverseBinaryTreeInOrder(self) 316 | return types.MakeKVIteratorFromTreeNodeIterator(tni) 317 | } 318 | 319 | func (self *AvlNode) Keys() types.KIterator { 320 | return types.MakeKeysIterator(self) 321 | } 322 | 323 | func (self *AvlNode) Values() types.Iterator { 324 | return types.MakeValuesIterator(self) 325 | } 326 | 327 | func (self *AvlNode) _md(side func(*AvlNode) *AvlNode) *AvlNode { 328 | if self == nil { 329 | return nil 330 | } else if side(self) != nil { 331 | return side(self)._md(side) 332 | } else { 333 | return self 334 | } 335 | } 336 | 337 | func (self *AvlNode) lmd() *AvlNode { 338 | return self._md(func(node *AvlNode) *AvlNode { return node.left }) 339 | } 340 | 341 | func (self *AvlNode) rmd() *AvlNode { 342 | return self._md(func(node *AvlNode) *AvlNode { return node.right }) 343 | } 344 | -------------------------------------------------------------------------------- /list/array_list_test.go: -------------------------------------------------------------------------------- 1 | package list 2 | 3 | import "testing" 4 | 5 | import ( 6 | crand "crypto/rand" 7 | "encoding/binary" 8 | "fmt" 9 | mrand "math/rand" 10 | "runtime/debug" 11 | ) 12 | 13 | import ( 14 | trand "github.com/timtadh/data-structures/rand" 15 | "github.com/timtadh/data-structures/types" 16 | ) 17 | 18 | var rand *mrand.Rand 19 | 20 | func init() { 21 | seed := make([]byte, 8) 22 | if _, err := crand.Read(seed); err == nil { 23 | rand = trand.ThreadSafeRand(int64(binary.BigEndian.Uint64(seed))) 24 | } else { 25 | panic(err) 26 | } 27 | } 28 | 29 | type T testing.T 30 | 31 | func (t *T) assert(msg string, oks ...bool) { 32 | for _, ok := range oks { 33 | if !ok { 34 | t.Log("\n" + string(debug.Stack())) 35 | t.Error(msg) 36 | t.Fatal("assert failed") 37 | } 38 | } 39 | } 40 | 41 | func (t *T) assert_nil(errors ...error) { 42 | for _, err := range errors { 43 | if err != nil { 44 | t.Log("\n" + string(debug.Stack())) 45 | t.Fatal(err) 46 | } 47 | } 48 | } 49 | 50 | func (t *T) randslice(length int) types.ByteSlice { 51 | slice := make([]byte, length) 52 | if _, err := crand.Read(slice); err != nil { 53 | t.Fatal(err) 54 | } 55 | return types.ByteSlice(slice) 56 | } 57 | 58 | func TestAppendGet(x *testing.T) { 59 | t := (*T)(x) 60 | SIZE := 100 61 | list := New(10) 62 | items := make([]types.ByteSlice, 0, SIZE) 63 | for i := 0; i < SIZE; i++ { 64 | item := t.randslice(rand.Intn(10) + 1) 65 | items = append(items, item) 66 | t.assert_nil(list.Append(item)) 67 | } 68 | for i, item := range items { 69 | lg, err := list.Get(i) 70 | t.assert_nil(err) 71 | t.assert(fmt.Sprintf("i %v, items[i] == list.Get(i)", i), lg.Equals(item)) 72 | } 73 | } 74 | 75 | func TestAppendGetCopy(x *testing.T) { 76 | t := (*T)(x) 77 | SIZE := 100 78 | list := New(10) 79 | items := make([]types.ByteSlice, 0, SIZE) 80 | for i := 0; i < SIZE; i++ { 81 | item := t.randslice(rand.Intn(10) + 1) 82 | items = append(items, item) 83 | t.assert_nil(list.Append(item)) 84 | } 85 | for i, item := range items { 86 | lg, err := list.Get(i) 87 | t.assert_nil(err) 88 | t.assert(fmt.Sprintf("i %v, items[i] == list.Get(i)", i), lg.Equals(item)) 89 | } 90 | list2 := list.Copy() 91 | for i, item := range items { 92 | lg, err := list2.Get(i) 93 | t.assert_nil(err) 94 | t.assert(fmt.Sprintf("i %v, items[i] == list2.Get(i)", i), lg.Equals(item)) 95 | } 96 | } 97 | 98 | func TestAppendMarshalUnmarshalGet(x *testing.T) { 99 | t := (*T)(x) 100 | SIZE := 100 101 | list := New(10) 102 | items := make([]types.Int, 0, SIZE) 103 | for i := 0; i < SIZE; i++ { 104 | item := types.Int(rand.Intn(10) + 1) 105 | items = append(items, item) 106 | t.assert_nil(list.Append(item)) 107 | } 108 | for i, item := range items { 109 | lg, err := list.Get(i) 110 | t.assert_nil(err) 111 | t.assert(fmt.Sprintf("i %v, items[i] == list.Get(i)", i), lg.Equals(item)) 112 | } 113 | marshal, unmarshal := types.IntMarshals() 114 | mlist1 := NewMList(list, marshal, unmarshal) 115 | bytes, err := mlist1.MarshalBinary() 116 | t.assert_nil(err) 117 | mlist2 := &MList{MarshalItem: marshal, UnmarshalItem: unmarshal} 118 | t.assert_nil(mlist2.UnmarshalBinary(bytes)) 119 | for i, item := range items { 120 | lg, err := mlist2.Get(i) 121 | t.assert_nil(err) 122 | t.assert(fmt.Sprintf("i %v, items[i] == list.Get(i)", i), lg.Equals(item)) 123 | } 124 | } 125 | 126 | func TestInsertGetSet(x *testing.T) { 127 | t := (*T)(x) 128 | SIZE := 100 129 | list := New(10) 130 | items := make([]types.Int, 0, SIZE) 131 | order := make([]int, 0, SIZE) 132 | { 133 | item := types.Int(0) 134 | items = append(items, item) 135 | order = append(order, 3) 136 | t.assert_nil(list.Insert(0, item)) 137 | // [0] 138 | } 139 | { 140 | item := types.Int(1) 141 | items = append(items, item) 142 | order = append(order, 0) 143 | t.assert_nil(list.Insert(0, item)) 144 | // [1, 0] 145 | } 146 | { 147 | item := types.Int(2) 148 | items = append(items, item) 149 | order = append(order, 1) 150 | t.assert_nil(list.Insert(1, item)) 151 | // [1, 2, 0] 152 | } 153 | { 154 | item := types.Int(3) 155 | items = append(items, item) 156 | order = append(order, 4) 157 | t.assert_nil(list.Insert(3, item)) 158 | // [1, 2, 0, 3] 159 | } 160 | { 161 | item := types.Int(4) 162 | items = append(items, item) 163 | order = append(order, 2) 164 | t.assert_nil(list.Insert(2, item)) 165 | // [1, 2, 4, 0, 3] 166 | } 167 | for j, i := range order { 168 | item := items[j] 169 | lg, err := list.Get(i) 170 | t.assert_nil(err) 171 | t.assert(fmt.Sprintf("j %v, i %v, items[i], %v != %v, list.Get(i)", j, i, item, lg), lg.Equals(item)) 172 | } 173 | _, err := list.Get(-1) 174 | t.assert(fmt.Sprintf("err != nil, err == %v", err), err != nil) 175 | _, err = list.Get(5) 176 | t.assert(fmt.Sprintf("err != nil, err == %v", err), err != nil) 177 | err = list.Set(5, nil) 178 | t.assert(fmt.Sprintf("err != nil, err == %v", err), err != nil) 179 | err = list.Insert(500, nil) 180 | t.assert(fmt.Sprintf("err != nil, err == %v", err), err != nil) 181 | err = list.Remove(500) 182 | t.assert(fmt.Sprintf("err != nil, err == %v", err), err != nil) 183 | for i := 0; i < list.Size(); i++ { 184 | list.Set(i, types.Int(i)) 185 | } 186 | for i := 0; i < list.Size(); i++ { 187 | lg, err := list.Get(i) 188 | t.assert_nil(err) 189 | t.assert(fmt.Sprintf("i %v, items[i] == list.Get(i)", i), lg.Equals(types.Int(i))) 190 | } 191 | list.Clear() 192 | t.assert(fmt.Sprintf("size != 0, %v", list.Size()), list.Size() == 0) 193 | } 194 | 195 | func TestAppendPop(x *testing.T) { 196 | t := (*T)(x) 197 | SIZE := 100 198 | list := New(10) 199 | items := make([]types.ByteSlice, 0, SIZE) 200 | for i := 0; i < SIZE; i++ { 201 | item := t.randslice(rand.Intn(10) + 1) 202 | items = append(items, item) 203 | t.assert_nil(list.Append(item)) 204 | } 205 | for i := SIZE - 1; i >= 0; i-- { 206 | item, err := list.Pop() 207 | t.assert_nil(err) 208 | t.assert(fmt.Sprintf("i %v, items[i] == list.Pop()", i), item.Equals(items[i])) 209 | } 210 | } 211 | 212 | func TestExtend(x *testing.T) { 213 | t := (*T)(x) 214 | SIZE := 100 215 | a := New(10) 216 | b := New(10) 217 | items := make([]types.ByteSlice, 0, SIZE) 218 | for i := 0; i < SIZE; i++ { 219 | item := t.randslice(rand.Intn(10) + 1) 220 | items = append(items, item) 221 | if i < SIZE/2 { 222 | t.assert_nil(a.Append(item)) 223 | } else { 224 | t.assert_nil(b.Append(item)) 225 | } 226 | } 227 | t.assert_nil(a.Extend(b.Items())) 228 | for i := SIZE - 1; i >= 0; i-- { 229 | item, err := a.Pop() 230 | t.assert_nil(err) 231 | t.assert(fmt.Sprintf("i %v, items[i] == list.Pop()", i), item.Equals(items[i])) 232 | } 233 | } 234 | 235 | func TestLess(x *testing.T) { 236 | t := (*T)(x) 237 | a := FromSlice([]types.Hashable{types.Int(1), types.Int(2), types.Int(3)}) 238 | b := FromSlice([]types.Hashable{types.Int(3), types.Int(2), types.Int(3)}) 239 | c := FromSlice([]types.Hashable{types.Int(1), types.Int(0), types.Int(3)}) 240 | d := FromSlice([]types.Hashable{types.Int(1), types.Int(2), types.Int(3)}) 241 | e := FromSlice([]types.Hashable{types.Int(1), types.Int(2), types.Int(4)}) 242 | small := FromSlice([]types.Hashable{types.Int(2), types.Int(4)}) 243 | big := FromSlice([]types.Hashable{types.Int(0), types.Int(1), types.Int(2), types.Int(4)}) 244 | t.assert("a < b", a.Less(b)) 245 | t.assert("c < a", c.Less(a)) 246 | t.assert("c < b", c.Less(b)) 247 | t.assert("a !< d", a.Less(d) == false) 248 | t.assert("a !< e", e.Less(a) == false) 249 | t.assert("a < big", a.Less(big)) 250 | t.assert("small < a", small.Less(a)) 251 | t.assert("a !< small", a.Less(small) == false) 252 | } 253 | 254 | func TestEqualsHash(x *testing.T) { 255 | t := (*T)(x) 256 | a := FromSlice([]types.Hashable{types.Int(1), types.Int(2), types.Int(3)}) 257 | b := FromSlice([]types.Hashable{types.Int(3), types.Int(2), types.Int(3)}) 258 | c := FromSlice([]types.Hashable{types.Int(1), types.Int(0), types.Int(3)}) 259 | d := FromSlice([]types.Hashable{types.Int(1), types.Int(2), types.Int(3)}) 260 | small := FromSlice([]types.Hashable{types.Int(2), types.Int(4)}) 261 | empty := FromSlice([]types.Hashable{}) 262 | t.assert("a != b", !a.Equals(b)) 263 | t.assert("c != a", !c.Equals(a)) 264 | t.assert("c != b", !c.Equals(b)) 265 | t.assert("a == d", a.Equals(d)) 266 | t.assert("c != small", !c.Equals(small)) 267 | t.assert("a.Hash() != b.Hash()", a.Hash() != b.Hash()) 268 | t.assert("c.Hash() != b.Hash()", c.Hash() != b.Hash()) 269 | t.assert("a.Hash() != d.Hash()", a.Hash() == d.Hash()) 270 | t.assert("d.Hash() != b.Hash()", d.Hash() != b.Hash()) 271 | t.assert("d.Hash() != empty.Hash()", d.Hash() != empty.Hash()) 272 | } 273 | -------------------------------------------------------------------------------- /trie/tst_test.go: -------------------------------------------------------------------------------- 1 | package trie 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "sort" 7 | "testing" 8 | 9 | crand "crypto/rand" 10 | "encoding/binary" 11 | mrand "math/rand" 12 | 13 | trand "github.com/timtadh/data-structures/rand" 14 | "github.com/timtadh/data-structures/test" 15 | "github.com/timtadh/data-structures/types" 16 | ) 17 | 18 | var rand *mrand.Rand 19 | 20 | func init() { 21 | seed := make([]byte, 8) 22 | if _, err := crand.Read(seed); err == nil { 23 | rand = trand.ThreadSafeRand(int64(binary.BigEndian.Uint64(seed))) 24 | } else { 25 | panic(err) 26 | } 27 | } 28 | 29 | func randslice(length int) []byte { 30 | return test.RandSlice(length) 31 | } 32 | 33 | func randstr(length int) types.String { 34 | return types.String(test.RandStr(length)) 35 | } 36 | 37 | func has_zero(bytes []byte) bool { 38 | for _, ch := range bytes { 39 | if ch == 0 { 40 | return true 41 | } 42 | } 43 | return false 44 | } 45 | 46 | func randslice_nonzero(length int) []byte { 47 | slice := randslice(length) 48 | for ; has_zero(slice); slice = randslice(length) { 49 | } 50 | return slice 51 | } 52 | 53 | func write(name, contents string) { 54 | file, _ := os.Create(name) 55 | fmt.Fprintln(file, contents) 56 | file.Close() 57 | } 58 | 59 | type ByteSlices []types.ByteSlice 60 | 61 | func (self ByteSlices) Len() int { 62 | return len(self) 63 | } 64 | 65 | func (self ByteSlices) Less(i, j int) bool { 66 | return self[i].Less(self[j]) 67 | } 68 | 69 | func (self ByteSlices) Swap(i, j int) { 70 | self[i], self[j] = self[j], self[i] 71 | } 72 | 73 | func TestEmptyIter(t *testing.T) { 74 | table := New() 75 | for _, _, next := table.Iterate()(); next != nil; _, _, next = next() { 76 | t.Errorf("should have been empty") 77 | } 78 | 79 | } 80 | 81 | func TestIteratorPrefixFindDotty(t *testing.T) { 82 | items := ByteSlices{ 83 | types.ByteSlice("0:java.io.File;"), 84 | types.ByteSlice("cat"), 85 | types.ByteSlice("catty"), 86 | types.ByteSlice("car"), 87 | types.ByteSlice("cow"), 88 | types.ByteSlice("candy"), 89 | types.ByteSlice("coo"), 90 | types.ByteSlice("coon"), 91 | types.ByteSlice("0:java.io.File;1:new,0:java.util.ArrayList;"), 92 | types.ByteSlice("andy"), 93 | types.ByteSlice("alex"), 94 | types.ByteSlice("andrie"), 95 | types.ByteSlice("alexander"), 96 | types.ByteSlice("alexi"), 97 | types.ByteSlice("bob"), 98 | types.ByteSlice("0:java.io.File;"), 99 | types.ByteSlice("bobcat"), 100 | types.ByteSlice("barnaby"), 101 | types.ByteSlice("baskin"), 102 | types.ByteSlice("balm"), 103 | } 104 | table := New() 105 | for _, key := range items { 106 | if err := table.Put(key, nil); err != nil { 107 | t.Error(table, err) 108 | } 109 | if has := table.Has(key); !has { 110 | t.Error(table, "Missing key") 111 | } 112 | } 113 | write("TestDotty.dot", table.Dotty()) 114 | sort.Sort(items) 115 | i := 0 116 | for k, _, next := table.Iterate()(); next != nil; k, _, next = next() { 117 | if !k.Equals(types.ByteSlice(items[i])) { 118 | t.Error(string(k.(types.ByteSlice)), "!=", string(items[i])) 119 | } 120 | i++ 121 | for i < len(items) && items[i].Equals(items[i-1]) { 122 | i++ 123 | } 124 | } 125 | co_items := ByteSlices{ 126 | types.ByteSlice("coo"), 127 | types.ByteSlice("coon"), 128 | types.ByteSlice("cow"), 129 | } 130 | i = 0 131 | for k, _, next := table.PrefixFind([]byte("co"))(); next != nil; k, _, next = next() { 132 | if !k.Equals(types.ByteSlice(co_items[i])) { 133 | t.Error(string(k.(types.ByteSlice)), "!=", string(co_items[i])) 134 | } 135 | i++ 136 | } 137 | } 138 | 139 | func TestComplete4(t *testing.T) { 140 | items := ByteSlices{ 141 | types.ByteSlice("abaa"), 142 | types.ByteSlice("abab"), 143 | types.ByteSlice("abac"), 144 | types.ByteSlice("abad"), 145 | types.ByteSlice("abba"), 146 | types.ByteSlice("abbb"), 147 | types.ByteSlice("abbc"), 148 | types.ByteSlice("abbd"), 149 | types.ByteSlice("abca"), 150 | types.ByteSlice("abcb"), 151 | types.ByteSlice("abcc"), 152 | types.ByteSlice("abcd"), 153 | types.ByteSlice("abda"), 154 | types.ByteSlice("abdb"), 155 | types.ByteSlice("abdc"), 156 | types.ByteSlice("abdd"), 157 | types.ByteSlice("aaaa"), 158 | types.ByteSlice("aaab"), 159 | types.ByteSlice("aaac"), 160 | types.ByteSlice("aaad"), 161 | types.ByteSlice("aaba"), 162 | types.ByteSlice("aabb"), 163 | types.ByteSlice("aabc"), 164 | types.ByteSlice("aabd"), 165 | types.ByteSlice("aaca"), 166 | types.ByteSlice("aacb"), 167 | types.ByteSlice("aacc"), 168 | types.ByteSlice("aacd"), 169 | types.ByteSlice("aada"), 170 | types.ByteSlice("aadb"), 171 | types.ByteSlice("aadc"), 172 | types.ByteSlice("aadd"), 173 | types.ByteSlice("adaa"), 174 | types.ByteSlice("adab"), 175 | types.ByteSlice("adac"), 176 | types.ByteSlice("adad"), 177 | types.ByteSlice("adba"), 178 | types.ByteSlice("adbb"), 179 | types.ByteSlice("adbc"), 180 | types.ByteSlice("adbd"), 181 | types.ByteSlice("adca"), 182 | types.ByteSlice("adcb"), 183 | types.ByteSlice("adcc"), 184 | types.ByteSlice("adcd"), 185 | types.ByteSlice("adda"), 186 | types.ByteSlice("addb"), 187 | types.ByteSlice("addc"), 188 | types.ByteSlice("addd"), 189 | types.ByteSlice("acaa"), 190 | types.ByteSlice("acab"), 191 | types.ByteSlice("acac"), 192 | types.ByteSlice("acad"), 193 | types.ByteSlice("acba"), 194 | types.ByteSlice("acbb"), 195 | types.ByteSlice("acbc"), 196 | types.ByteSlice("acbd"), 197 | types.ByteSlice("acca"), 198 | types.ByteSlice("accb"), 199 | types.ByteSlice("accc"), 200 | types.ByteSlice("accd"), 201 | types.ByteSlice("acda"), 202 | types.ByteSlice("acdb"), 203 | types.ByteSlice("acdc"), 204 | types.ByteSlice("addd"), 205 | } 206 | table := new(TST) 207 | for _, key := range items { 208 | if err := table.Put(key, nil); err != nil { 209 | t.Error(table, err) 210 | } 211 | if has := table.Has(key); !has { 212 | t.Error(table, "Missing key") 213 | } 214 | } 215 | write("TestComplete4.dot", table.Dotty()) 216 | sort.Sort(items) 217 | i := 0 218 | for k, _, next := table.Iterate()(); next != nil; k, _, next = next() { 219 | if !k.Equals(types.ByteSlice(items[i])) { 220 | t.Error(string(k.(types.ByteSlice)), "!=", string(items[i])) 221 | } 222 | i++ 223 | for i+1 < len(items) && items[i].Equals(items[i-1]) { 224 | i++ 225 | } 226 | } 227 | } 228 | 229 | func TestPutHasGetRemove(t *testing.T) { 230 | 231 | type record struct { 232 | key types.ByteSlice 233 | value types.ByteSlice 234 | } 235 | 236 | ranrec := func() *record { 237 | return &record{randslice_nonzero(3), randslice(3)} 238 | } 239 | 240 | test := func(table *TST) { 241 | records := make([]*record, 500) 242 | for i := range records { 243 | r := ranrec() 244 | records[i] = r 245 | err := table.Put(r.key, "") 246 | if err != nil { 247 | t.Error(err) 248 | } 249 | err = table.Put(r.key, r.value) 250 | if err != nil { 251 | t.Error(err) 252 | } 253 | } 254 | 255 | for _, r := range records { 256 | if has := table.Has(r.key); !has { 257 | t.Error(table, "Missing key") 258 | } 259 | if has := table.Has(randslice(12)); has { 260 | t.Error("Table has extra key") 261 | } 262 | if val, err := table.Get(r.key); err != nil { 263 | t.Error(err) 264 | } else if !(val.(types.ByteSlice)).Equals(r.value) { 265 | t.Error("wrong value") 266 | } 267 | } 268 | rs := randslice(12) 269 | for i, x := range records { 270 | if val, err := table.Remove(x.key); err != nil { 271 | t.Error(err) 272 | } else if !(val.(types.ByteSlice)).Equals(x.value) { 273 | t.Error("wrong value") 274 | } 275 | for _, r := range records[i+1:] { 276 | if has := table.Has(r.key); !has { 277 | t.Error("Missing key") 278 | } 279 | if has := table.Has(rs); has { 280 | t.Error("Table has extra key") 281 | } 282 | if val, err := table.Get(r.key); err != nil { 283 | t.Error(err) 284 | } else if !(val.(types.ByteSlice)).Equals(r.value) { 285 | t.Error("wrong value") 286 | } 287 | } 288 | } 289 | } 290 | 291 | test(new(TST)) 292 | } 293 | 294 | func BenchmarkTST(b *testing.B) { 295 | b.StopTimer() 296 | 297 | type record struct { 298 | key types.ByteSlice 299 | value types.ByteSlice 300 | } 301 | 302 | records := make([]*record, 100) 303 | 304 | ranrec := func() *record { 305 | return &record{randslice(20), randslice(20)} 306 | } 307 | 308 | for i := range records { 309 | records[i] = ranrec() 310 | } 311 | 312 | b.StartTimer() 313 | for i := 0; i < b.N; i++ { 314 | t := new(TST) 315 | for _, r := range records { 316 | t.Put(r.key, r.value) 317 | } 318 | for _, r := range records { 319 | t.Remove(r.key) 320 | } 321 | } 322 | } 323 | -------------------------------------------------------------------------------- /types/util.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "reflect" 5 | ) 6 | 7 | func IsNil(object interface{}) bool { 8 | return object == nil || reflect.ValueOf(object).IsNil() 9 | } 10 | 11 | func MakeKVIteratorFromTreeNodeIterator(tni TreeNodeIterator) KVIterator { 12 | var kv_iterator KVIterator 13 | kv_iterator = func() (key Hashable, value interface{}, next KVIterator) { 14 | var tn TreeNode 15 | tn, tni = tni() 16 | if tni == nil { 17 | return nil, nil, nil 18 | } 19 | return tn.Key(), tn.Value(), kv_iterator 20 | } 21 | return kv_iterator 22 | } 23 | 24 | func ChainTreeNodeIterators(tnis ...TreeNodeIterator) TreeNodeIterator { 25 | var make_tni func(int) TreeNodeIterator 26 | make_tni = func(i int) (tni_iterator TreeNodeIterator) { 27 | if i >= len(tnis) { 28 | return nil 29 | } 30 | var next TreeNodeIterator = tnis[i] 31 | tni_iterator = func() (TreeNode, TreeNodeIterator) { 32 | var tn TreeNode 33 | tn, next = next() 34 | if next == nil { 35 | tni := make_tni(i + 1) 36 | if tni == nil { 37 | return nil, nil 38 | } else { 39 | return tni() 40 | } 41 | } 42 | return tn, tni_iterator 43 | } 44 | return tni_iterator 45 | } 46 | return make_tni(0) 47 | } 48 | 49 | func MakeKeysIterator(obj KVIterable) KIterator { 50 | kv_iterator := obj.Iterate() 51 | var k_iterator KIterator 52 | k_iterator = func() (key Hashable, next KIterator) { 53 | key, _, kv_iterator = kv_iterator() 54 | if kv_iterator == nil { 55 | return nil, nil 56 | } 57 | return key, k_iterator 58 | } 59 | return k_iterator 60 | } 61 | 62 | func MakeValuesIterator(obj KVIterable) Iterator { 63 | kv_iterator := obj.Iterate() 64 | var v_iterator Iterator 65 | v_iterator = func() (value interface{}, next Iterator) { 66 | _, value, kv_iterator = kv_iterator() 67 | if kv_iterator == nil { 68 | return nil, nil 69 | } 70 | return value, v_iterator 71 | } 72 | return v_iterator 73 | } 74 | 75 | func MakeItemsIterator(obj KVIterable) (kit KIterator) { 76 | kv_iterator := obj.Iterate() 77 | kit = func() (item Hashable, next KIterator) { 78 | var key Hashable 79 | var value interface{} 80 | key, value, kv_iterator = kv_iterator() 81 | if kv_iterator == nil { 82 | return nil, nil 83 | } 84 | return &MapEntry{key, value}, kit 85 | } 86 | return kit 87 | } 88 | 89 | func make_child_slice(node BinaryTreeNode) []BinaryTreeNode { 90 | nodes := make([]BinaryTreeNode, 0, 2) 91 | if !IsNil(node) { 92 | if !IsNil(node.Left()) { 93 | nodes = append(nodes, node.Left()) 94 | } 95 | if !IsNil(node.Right()) { 96 | nodes = append(nodes, node.Right()) 97 | } 98 | } 99 | return nodes 100 | } 101 | 102 | func DoGetChild(node BinaryTreeNode, i int) TreeNode { 103 | return make_child_slice(node)[i] 104 | } 105 | 106 | func DoChildCount(node BinaryTreeNode) int { 107 | return len(make_child_slice(node)) 108 | } 109 | 110 | func MakeChildrenIterator(node BinaryTreeNode) TreeNodeIterator { 111 | nodes := make_child_slice(node) 112 | var make_tn_iterator func(int) TreeNodeIterator 113 | make_tn_iterator = func(i int) TreeNodeIterator { 114 | return func() (kid TreeNode, next TreeNodeIterator) { 115 | if i < len(nodes) { 116 | return nodes[i], make_tn_iterator(i + 1) 117 | } 118 | return nil, nil 119 | } 120 | } 121 | return make_tn_iterator(0) 122 | } 123 | 124 | func MakeMarshals(empty func() MHashable) (ItemMarshal, ItemUnmarshal) { 125 | marshal := func(item Hashable) ([]byte, error) { 126 | i := item.(Marshaler) 127 | return i.MarshalBinary() 128 | } 129 | unmarshal := func(bytes []byte) (Hashable, error) { 130 | i := empty() 131 | err := i.UnmarshalBinary(bytes) 132 | if err != nil { 133 | return nil, err 134 | } 135 | return i, nil 136 | } 137 | return marshal, unmarshal 138 | } 139 | 140 | func Int8Marshals() (ItemMarshal, ItemUnmarshal) { 141 | marshal := func(item Hashable) ([]byte, error) { 142 | i := item.(Int8) 143 | return i.MarshalBinary() 144 | } 145 | unmarshal := func(bytes []byte) (Hashable, error) { 146 | i := Int8(0) 147 | err := i.UnmarshalBinary(bytes) 148 | if err != nil { 149 | return nil, err 150 | } 151 | return i, nil 152 | } 153 | return marshal, unmarshal 154 | } 155 | 156 | func UInt8Marshals() (ItemMarshal, ItemUnmarshal) { 157 | marshal := func(item Hashable) ([]byte, error) { 158 | i := item.(UInt8) 159 | return i.MarshalBinary() 160 | } 161 | unmarshal := func(bytes []byte) (Hashable, error) { 162 | i := UInt8(0) 163 | err := i.UnmarshalBinary(bytes) 164 | if err != nil { 165 | return nil, err 166 | } 167 | return i, nil 168 | } 169 | return marshal, unmarshal 170 | } 171 | 172 | func Int16Marshals() (ItemMarshal, ItemUnmarshal) { 173 | marshal := func(item Hashable) ([]byte, error) { 174 | i := item.(Int16) 175 | return i.MarshalBinary() 176 | } 177 | unmarshal := func(bytes []byte) (Hashable, error) { 178 | i := Int16(0) 179 | err := i.UnmarshalBinary(bytes) 180 | if err != nil { 181 | return nil, err 182 | } 183 | return i, nil 184 | } 185 | return marshal, unmarshal 186 | } 187 | 188 | func UInt16Marshals() (ItemMarshal, ItemUnmarshal) { 189 | marshal := func(item Hashable) ([]byte, error) { 190 | i := item.(UInt16) 191 | return i.MarshalBinary() 192 | } 193 | unmarshal := func(bytes []byte) (Hashable, error) { 194 | i := UInt16(0) 195 | err := i.UnmarshalBinary(bytes) 196 | if err != nil { 197 | return nil, err 198 | } 199 | return i, nil 200 | } 201 | return marshal, unmarshal 202 | } 203 | 204 | func Int32Marshals() (ItemMarshal, ItemUnmarshal) { 205 | marshal := func(item Hashable) ([]byte, error) { 206 | i := item.(Int32) 207 | return i.MarshalBinary() 208 | } 209 | unmarshal := func(bytes []byte) (Hashable, error) { 210 | i := Int32(0) 211 | err := i.UnmarshalBinary(bytes) 212 | if err != nil { 213 | return nil, err 214 | } 215 | return i, nil 216 | } 217 | return marshal, unmarshal 218 | } 219 | 220 | func UInt32Marshals() (ItemMarshal, ItemUnmarshal) { 221 | marshal := func(item Hashable) ([]byte, error) { 222 | i := item.(UInt32) 223 | return i.MarshalBinary() 224 | } 225 | unmarshal := func(bytes []byte) (Hashable, error) { 226 | i := UInt32(0) 227 | err := i.UnmarshalBinary(bytes) 228 | if err != nil { 229 | return nil, err 230 | } 231 | return i, nil 232 | } 233 | return marshal, unmarshal 234 | } 235 | 236 | func Int64Marshals() (ItemMarshal, ItemUnmarshal) { 237 | marshal := func(item Hashable) ([]byte, error) { 238 | i := item.(Int64) 239 | return i.MarshalBinary() 240 | } 241 | unmarshal := func(bytes []byte) (Hashable, error) { 242 | i := Int64(0) 243 | err := i.UnmarshalBinary(bytes) 244 | if err != nil { 245 | return nil, err 246 | } 247 | return i, nil 248 | } 249 | return marshal, unmarshal 250 | } 251 | 252 | func UInt64Marshals() (ItemMarshal, ItemUnmarshal) { 253 | marshal := func(item Hashable) ([]byte, error) { 254 | i := item.(UInt64) 255 | return i.MarshalBinary() 256 | } 257 | unmarshal := func(bytes []byte) (Hashable, error) { 258 | i := UInt64(0) 259 | err := i.UnmarshalBinary(bytes) 260 | if err != nil { 261 | return nil, err 262 | } 263 | return i, nil 264 | } 265 | return marshal, unmarshal 266 | } 267 | 268 | func IntMarshals() (ItemMarshal, ItemUnmarshal) { 269 | marshal := func(item Hashable) ([]byte, error) { 270 | i := item.(Int) 271 | return i.MarshalBinary() 272 | } 273 | unmarshal := func(bytes []byte) (Hashable, error) { 274 | i := Int(0) 275 | err := i.UnmarshalBinary(bytes) 276 | if err != nil { 277 | return nil, err 278 | } 279 | return i, nil 280 | } 281 | return marshal, unmarshal 282 | } 283 | 284 | func UIntMarshals() (ItemMarshal, ItemUnmarshal) { 285 | marshal := func(item Hashable) ([]byte, error) { 286 | i := item.(UInt) 287 | return i.MarshalBinary() 288 | } 289 | unmarshal := func(bytes []byte) (Hashable, error) { 290 | i := UInt(0) 291 | err := i.UnmarshalBinary(bytes) 292 | if err != nil { 293 | return nil, err 294 | } 295 | return i, nil 296 | } 297 | return marshal, unmarshal 298 | } 299 | 300 | func StringMarshals() (ItemMarshal, ItemUnmarshal) { 301 | marshal := func(item Hashable) ([]byte, error) { 302 | i := item.(String) 303 | return i.MarshalBinary() 304 | } 305 | unmarshal := func(bytes []byte) (Hashable, error) { 306 | i := String("") 307 | err := i.UnmarshalBinary(bytes) 308 | if err != nil { 309 | return nil, err 310 | } 311 | return i, nil 312 | } 313 | return marshal, unmarshal 314 | } 315 | 316 | func ByteSliceMarshals() (ItemMarshal, ItemUnmarshal) { 317 | marshal := func(item Hashable) ([]byte, error) { 318 | return []byte(item.(ByteSlice)), nil 319 | } 320 | unmarshal := func(bytes []byte) (Hashable, error) { 321 | return ByteSlice(bytes), nil 322 | } 323 | return marshal, unmarshal 324 | } 325 | -------------------------------------------------------------------------------- /set/sortedset_test.go: -------------------------------------------------------------------------------- 1 | package set 2 | 3 | import "testing" 4 | 5 | import ( 6 | "fmt" 7 | "runtime/debug" 8 | ) 9 | 10 | import ( 11 | "github.com/timtadh/data-structures/list" 12 | "github.com/timtadh/data-structures/types" 13 | ) 14 | 15 | type T testing.T 16 | 17 | func (t *T) assert(msg string, oks ...bool) { 18 | for _, ok := range oks { 19 | if !ok { 20 | t.Log("\n" + string(debug.Stack())) 21 | t.Error(msg) 22 | t.Fatal("assert failed") 23 | } 24 | } 25 | } 26 | 27 | func (t *T) assert_set(set types.Set, err error) types.Set { 28 | t.assert_nil(err) 29 | return set 30 | } 31 | 32 | func (t *T) assert_nil(errors ...error) { 33 | for _, err := range errors { 34 | if err != nil { 35 | t.Log("\n" + string(debug.Stack())) 36 | t.Fatal(err) 37 | } 38 | } 39 | } 40 | 41 | func TestAddMarshalUnmarshalHas(x *testing.T) { 42 | t := (*T)(x) 43 | SIZE := 100 44 | set := NewSortedSet(10) 45 | items := make([]types.Int, 0, SIZE) 46 | for i := 0; i < SIZE; i++ { 47 | item := types.Int(rand.Intn(10) + 1) 48 | items = append(items, item) 49 | t.assert_nil(set.Add(item)) 50 | } 51 | for i, item := range items { 52 | t.assert(fmt.Sprintf("!set.Has(%v) ", i), set.Has(item)) 53 | } 54 | marshal, unmarshal := types.IntMarshals() 55 | mset1 := NewMSortedSet(set, marshal, unmarshal) 56 | bytes, err := mset1.MarshalBinary() 57 | t.assert_nil(err) 58 | mset2 := &MSortedSet{MSorted: list.MSorted{MList: list.MList{MarshalItem: marshal, UnmarshalItem: unmarshal}}} 59 | t.assert_nil(mset2.UnmarshalBinary(bytes)) 60 | set2 := mset2.SortedSet() 61 | for i, item := range items { 62 | t.assert(fmt.Sprintf("!set.Has(%v)", i), set2.Has(item)) 63 | } 64 | } 65 | 66 | func TestAddHasDeleteRandom(x *testing.T) { 67 | t := (*T)(x) 68 | SIZE := 100 69 | set := NewSortedSet(10) 70 | items := make([]types.Int, 0, SIZE) 71 | for i := 0; i < SIZE; i++ { 72 | item := types.Int(rand.Intn(1000)) 73 | for set.Has(item) { 74 | item = types.Int(rand.Intn(1000)) 75 | } 76 | items = append(items, item) 77 | t.assert_nil(set.Add(item)) 78 | } 79 | for i, item := range items { 80 | t.assert(fmt.Sprintf("i %v, !set.Has(item)", i), set.Has(item)) 81 | } 82 | for i := 0; i < 10; i++ { 83 | item, err := set.Random() 84 | t.assert_nil(err) 85 | t.assert(fmt.Sprintf("!set.Has(%v)", i), set.Has(item)) 86 | } 87 | for _, item := range items { 88 | t.assert_nil(set.Delete(item)) 89 | } 90 | for i, item := range items { 91 | t.assert(fmt.Sprintf("i %v, !set.Has(item)", i), !set.Has(item)) 92 | } 93 | _, err := set.Random() 94 | t.assert(fmt.Sprintf("err == nil"), err != nil) 95 | t.assert_nil(set.Add(types.Int(1))) 96 | item, err := set.Random() 97 | t.assert_nil(err) 98 | t.assert(fmt.Sprintf("item == 1"), item.Equals(types.Int(1))) 99 | } 100 | 101 | func TestAddHasDelete(x *testing.T) { 102 | t := (*T)(x) 103 | SIZE := 100 104 | set := NewSortedSet(10) 105 | items := make([]types.Int, 0, SIZE) 106 | for i := 0; i < SIZE; i++ { 107 | item := types.Int(rand.Intn(1000)) 108 | for set.Has(item) { 109 | item = types.Int(rand.Intn(1000)) 110 | } 111 | items = append(items, item) 112 | t.assert_nil(set.Add(item)) 113 | } 114 | for i, item := range items { 115 | t.assert(fmt.Sprintf("i %v, !set.Has(item)", i), set.Has(item)) 116 | } 117 | for _, item := range items { 118 | t.assert_nil(set.Delete(item)) 119 | } 120 | for i, item := range items { 121 | t.assert(fmt.Sprintf("i %v, !set.Has(item)", i), !set.Has(item)) 122 | } 123 | } 124 | 125 | func TestLess(x *testing.T) { 126 | t := (*T)(x) 127 | a := FromSlice([]types.Hashable{types.Int(1), types.Int(2), types.Int(3)}) 128 | b := FromSlice([]types.Hashable{types.Int(3), types.Int(2), types.Int(3)}) 129 | c := FromSlice([]types.Hashable{types.Int(1), types.Int(0), types.Int(3)}) 130 | d := FromSlice([]types.Hashable{types.Int(1), types.Int(2), types.Int(3)}) 131 | e := FromSlice([]types.Hashable{types.Int(1), types.Int(2), types.Int(4)}) 132 | small := FromSlice([]types.Hashable{types.Int(2), types.Int(4)}) 133 | big := FromSlice([]types.Hashable{types.Int(0), types.Int(1), types.Int(2), types.Int(4)}) 134 | t.assert("b < a", b.Less(a)) 135 | t.assert("c < a", c.Less(a)) 136 | t.assert("b < c", b.Less(c)) 137 | t.assert("a !< d", a.Less(d) == false) 138 | t.assert("a !< e", e.Less(a) == false) 139 | t.assert("a < big", a.Less(big)) 140 | t.assert("small < a", small.Less(a)) 141 | t.assert("a !< small", a.Less(small) == false) 142 | } 143 | 144 | func TestEqualsHash(x *testing.T) { 145 | t := (*T)(x) 146 | a := FromSlice([]types.Hashable{types.Int(1), types.Int(2), types.Int(3)}) 147 | b := FromSlice([]types.Hashable{types.Int(3), types.Int(2), types.Int(3)}) 148 | c := FromSlice([]types.Hashable{types.Int(1), types.Int(0), types.Int(3)}) 149 | d := FromSlice([]types.Hashable{types.Int(1), types.Int(2), types.Int(3)}) 150 | small := FromSlice([]types.Hashable{types.Int(2), types.Int(4)}) 151 | empty := FromSlice([]types.Hashable{}) 152 | t.assert("a != b", !a.Equals(b)) 153 | t.assert("c != a", !c.Equals(a)) 154 | t.assert("c != b", !c.Equals(b)) 155 | t.assert("a == d", a.Equals(d)) 156 | t.assert("c != small", !c.Equals(small)) 157 | t.assert("a.Hash() != b.Hash()", a.Hash() != b.Hash()) 158 | t.assert("c.Hash() != b.Hash()", c.Hash() != b.Hash()) 159 | t.assert("a.Hash() != d.Hash()", a.Hash() == d.Hash()) 160 | t.assert("d.Hash() != b.Hash()", d.Hash() != b.Hash()) 161 | t.assert("d.Hash() != empty.Hash()", d.Hash() != empty.Hash()) 162 | } 163 | 164 | func TestUnion(x *testing.T) { 165 | t := (*T)(x) 166 | a := FromSlice([]types.Hashable{types.Int(0), types.Int(1), types.Int(2), types.Int(3)}) 167 | b := FromSlice([]types.Hashable{types.Int(1), types.Int(2), types.Int(4)}) 168 | c := FromSlice([]types.Hashable{types.Int(0), types.Int(1), types.Int(2), types.Int(3), types.Int(4)}) 169 | t.assert("a | b == c", t.assert_set(a.Union(b)).Equals(c)) 170 | t.assert("b | a == c", t.assert_set(b.Union(a)).Equals(c)) 171 | t.assert("a | b == c", t.assert_set(Union(a, b)).Equals(c)) 172 | t.assert("b | a == c", t.assert_set(Union(b, a)).Equals(c)) 173 | } 174 | 175 | func TestIntersect(x *testing.T) { 176 | t := (*T)(x) 177 | a := FromSlice([]types.Hashable{types.Int(0), types.Int(1), types.Int(2), types.Int(3)}) 178 | b := FromSlice([]types.Hashable{types.Int(1), types.Int(2), types.Int(4)}) 179 | c := FromSlice([]types.Hashable{types.Int(1), types.Int(2)}) 180 | d := FromSlice([]types.Hashable{types.Int(50), types.Int(20), types.Int(30), types.Int(40), types.Int(10)}) 181 | e := FromSlice([]types.Hashable{}) 182 | t.assert("a & b == c", t.assert_set(a.Intersect(b)).Equals(c)) 183 | t.assert("b & a == c", t.assert_set(b.Intersect(a)).Equals(c)) 184 | t.assert("a & d == e", t.assert_set(a.Intersect(d)).Equals(e)) 185 | t.assert("d & a == e", t.assert_set(d.Intersect(a)).Equals(e)) 186 | } 187 | 188 | func TestSubtract(x *testing.T) { 189 | t := (*T)(x) 190 | a := FromSlice([]types.Hashable{types.Int(0), types.Int(1), types.Int(2), types.Int(3)}) 191 | b := FromSlice([]types.Hashable{types.Int(1), types.Int(2), types.Int(4)}) 192 | c := FromSlice([]types.Hashable{types.Int(0), types.Int(3)}) 193 | d := FromSlice([]types.Hashable{types.Int(4)}) 194 | t.assert("a - b == c", t.assert_set(a.Subtract(b)).Equals(c)) 195 | t.assert("b - a == d", t.assert_set(b.Subtract(a)).Equals(d)) 196 | } 197 | 198 | func TestOverlap(x *testing.T) { 199 | t := (*T)(x) 200 | a := FromSlice([]types.Hashable{types.Int(0), types.Int(1), types.Int(2), types.Int(3)}) 201 | b := FromSlice([]types.Hashable{types.Int(1), types.Int(2), types.Int(4)}) 202 | t.assert("a & b != 0", a.Overlap(b)) 203 | c := FromSlice([]types.Hashable{types.Int(5), types.Int(4)}) 204 | t.assert("a & c == 0", !a.Overlap(c)) 205 | d := FromSlice([]types.Hashable{types.Int(-2), types.Int(4)}) 206 | t.assert("a & d == 0", !a.Overlap(d)) 207 | } 208 | 209 | func TestSubsetSuperset(x *testing.T) { 210 | t := (*T)(x) 211 | a := FromSlice([]types.Hashable{types.Int(0), types.Int(1), types.Int(2), types.Int(3)}) 212 | b := FromSlice([]types.Hashable{types.Int(1), types.Int(2), types.Int(4)}) 213 | c := FromSlice([]types.Hashable{types.Int(1), types.Int(2)}) 214 | t.assert("a not subset b", !a.Subset(b)) 215 | t.assert("b not subset a", !b.Subset(a)) 216 | t.assert("c subset a", c.Subset(a)) 217 | t.assert("c subset b", c.Subset(b)) 218 | t.assert("c proper subset a", c.ProperSubset(a)) 219 | t.assert("c proper subset b", c.ProperSubset(b)) 220 | t.assert("a subset a", a.Subset(a)) 221 | t.assert("a not proper subset a", !a.ProperSubset(a)) 222 | t.assert("a superset a", a.Superset(a)) 223 | t.assert("a not proper superset a", !a.ProperSuperset(a)) 224 | t.assert("a superset c", a.Superset(c)) 225 | t.assert("b superset c", b.Superset(c)) 226 | t.assert("a superset c", a.ProperSuperset(c)) 227 | t.assert("b superset c", b.ProperSuperset(c)) 228 | } 229 | -------------------------------------------------------------------------------- /tree/avl/imm_avltree.go: -------------------------------------------------------------------------------- 1 | package avl 2 | 3 | import ( 4 | "github.com/timtadh/data-structures/errors" 5 | "github.com/timtadh/data-structures/tree" 6 | "github.com/timtadh/data-structures/types" 7 | ) 8 | 9 | type ImmutableAvlTree struct { 10 | root *ImmutableAvlNode 11 | } 12 | 13 | func NewImmutableAvlTree() *ImmutableAvlTree { 14 | return &ImmutableAvlTree{} 15 | } 16 | 17 | func (self *ImmutableAvlTree) Root() types.TreeNode { 18 | return self.root.Copy() 19 | } 20 | 21 | func (self *ImmutableAvlTree) Size() int { 22 | return self.root.Size() 23 | } 24 | 25 | func (self *ImmutableAvlTree) Has(key types.Hashable) bool { 26 | return self.root.Has(key) 27 | } 28 | 29 | func (self *ImmutableAvlTree) Put(key types.Hashable, value interface{}) (err error) { 30 | self.root, _ = self.root.Put(key, value) 31 | return nil 32 | } 33 | 34 | func (self *ImmutableAvlTree) Get(key types.Hashable) (value interface{}, err error) { 35 | return self.root.Get(key) 36 | } 37 | 38 | func (self *ImmutableAvlTree) Remove(key types.Hashable) (value interface{}, err error) { 39 | new_root, value, err := self.root.Remove(key) 40 | if err != nil { 41 | return nil, err 42 | } 43 | self.root = new_root 44 | return value, nil 45 | } 46 | 47 | func (self *ImmutableAvlTree) Iterate() types.KVIterator { 48 | return self.root.Iterate() 49 | } 50 | 51 | func (self *ImmutableAvlTree) Items() (vi types.KIterator) { 52 | return types.MakeItemsIterator(self) 53 | } 54 | 55 | func (self *ImmutableAvlTree) Values() types.Iterator { 56 | return self.root.Values() 57 | } 58 | 59 | func (self *ImmutableAvlTree) Keys() types.KIterator { 60 | return self.root.Keys() 61 | } 62 | 63 | type ImmutableAvlNode struct { 64 | key types.Hashable 65 | value interface{} 66 | height int 67 | left *ImmutableAvlNode 68 | right *ImmutableAvlNode 69 | } 70 | 71 | func (self *ImmutableAvlNode) Copy() *ImmutableAvlNode { 72 | if self == nil { 73 | return nil 74 | } 75 | return &ImmutableAvlNode{ 76 | key: self.key, 77 | value: self.value, 78 | height: self.height, 79 | left: self.left, 80 | right: self.right, 81 | } 82 | } 83 | 84 | func (self *ImmutableAvlNode) Has(key types.Hashable) (has bool) { 85 | if self == nil { 86 | return false 87 | } 88 | if self.key.Equals(key) { 89 | return true 90 | } else if key.Less(self.key) { 91 | return self.left.Has(key) 92 | } else { 93 | return self.right.Has(key) 94 | } 95 | } 96 | 97 | func (self *ImmutableAvlNode) Get(key types.Hashable) (value interface{}, err error) { 98 | if self == nil { 99 | return nil, errors.NotFound(key) 100 | } 101 | if self.key.Equals(key) { 102 | return self.value, nil 103 | } else if key.Less(self.key) { 104 | return self.left.Get(key) 105 | } else { 106 | return self.right.Get(key) 107 | } 108 | } 109 | 110 | func (self *ImmutableAvlNode) pop_node(node *ImmutableAvlNode) (new_self, new_node *ImmutableAvlNode) { 111 | if node == nil { 112 | panic("node can't be nil") 113 | } else if node.left != nil && node.right != nil { 114 | panic("node must not have both left and right") 115 | } 116 | 117 | if self == nil { 118 | return nil, node.Copy() 119 | } else if self == node { 120 | var n *ImmutableAvlNode 121 | if node.left != nil { 122 | n = node.left 123 | } else if node.right != nil { 124 | n = node.right 125 | } else { 126 | n = nil 127 | } 128 | node = node.Copy() 129 | node.left = nil 130 | node.right = nil 131 | return n, node 132 | } 133 | 134 | self = self.Copy() 135 | 136 | if node.key.Less(self.key) { 137 | self.left, node = self.left.pop_node(node) 138 | } else { 139 | self.right, node = self.right.pop_node(node) 140 | } 141 | 142 | self.height = max(self.left.Height(), self.right.Height()) + 1 143 | return self, node 144 | } 145 | 146 | func (self *ImmutableAvlNode) push_node(node *ImmutableAvlNode) *ImmutableAvlNode { 147 | if node == nil { 148 | panic("node can't be nil") 149 | } else if node.left != nil || node.right != nil { 150 | panic("node must now be a leaf") 151 | } 152 | 153 | self = self.Copy() 154 | 155 | if self == nil { 156 | node.height = 1 157 | return node 158 | } else if node.key.Less(self.key) { 159 | self.left = self.left.push_node(node) 160 | } else { 161 | self.right = self.right.push_node(node) 162 | } 163 | self.height = max(self.left.Height(), self.right.Height()) + 1 164 | return self 165 | } 166 | 167 | func (self *ImmutableAvlNode) rotate_right() *ImmutableAvlNode { 168 | if self == nil { 169 | return self 170 | } 171 | if self.left == nil { 172 | return self 173 | } 174 | return self.rotate(self.left.rmd) 175 | } 176 | 177 | func (self *ImmutableAvlNode) rotate_left() *ImmutableAvlNode { 178 | if self == nil { 179 | return self 180 | } 181 | if self.right == nil { 182 | return self 183 | } 184 | return self.rotate(self.right.lmd) 185 | } 186 | 187 | func (self *ImmutableAvlNode) rotate(get_new_root func() *ImmutableAvlNode) *ImmutableAvlNode { 188 | self, new_root := self.pop_node(get_new_root()) 189 | new_root.left = self.left 190 | new_root.right = self.right 191 | self.left = nil 192 | self.right = nil 193 | return new_root.push_node(self) 194 | } 195 | 196 | func (self *ImmutableAvlNode) balance() *ImmutableAvlNode { 197 | if self == nil { 198 | return self 199 | } 200 | for abs(self.left.Height()-self.right.Height()) > 2 { 201 | if self.left.Height() > self.right.Height() { 202 | self = self.rotate_right() 203 | } else { 204 | self = self.rotate_left() 205 | } 206 | } 207 | return self 208 | } 209 | 210 | func (self *ImmutableAvlNode) Put(key types.Hashable, value interface{}) (_ *ImmutableAvlNode, updated bool) { 211 | if self == nil { 212 | return &ImmutableAvlNode{key: key, value: value, height: 1}, false 213 | } 214 | 215 | self = self.Copy() 216 | 217 | if self.key.Equals(key) { 218 | self.value = value 219 | return self, true 220 | } 221 | 222 | if key.Less(self.key) { 223 | self.left, updated = self.left.Put(key, value) 224 | } else { 225 | self.right, updated = self.right.Put(key, value) 226 | } 227 | self.height = max(self.left.Height(), self.right.Height()) + 1 228 | 229 | if !updated { 230 | self.height += 1 231 | return self.balance(), updated 232 | } 233 | return self, updated 234 | } 235 | 236 | func (self *ImmutableAvlNode) Remove(key types.Hashable) (_ *ImmutableAvlNode, value interface{}, err error) { 237 | if self == nil { 238 | return nil, nil, errors.NotFound(key) 239 | } 240 | 241 | if self.key.Equals(key) { 242 | if self.left != nil && self.right != nil { 243 | var new_root *ImmutableAvlNode 244 | if self.left.Size() < self.right.Size() { 245 | self, new_root = self.pop_node(self.right.lmd()) 246 | } else { 247 | self, new_root = self.pop_node(self.left.rmd()) 248 | } 249 | new_root.left = self.left 250 | new_root.right = self.right 251 | return new_root, self.value, nil 252 | } else if self.left == nil { 253 | return self.right, self.value, nil 254 | } else if self.right == nil { 255 | return self.left, self.value, nil 256 | } else { 257 | return nil, self.value, nil 258 | } 259 | } 260 | 261 | self = self.Copy() 262 | 263 | if key.Less(self.key) { 264 | self.left, value, err = self.left.Remove(key) 265 | } else { 266 | self.right, value, err = self.right.Remove(key) 267 | } 268 | self.height = max(self.left.Height(), self.right.Height()) + 1 269 | if err != nil { 270 | return self.balance(), value, err 271 | } 272 | return self, value, err 273 | } 274 | 275 | func (self *ImmutableAvlNode) Height() int { 276 | if self == nil { 277 | return 0 278 | } 279 | return self.height 280 | } 281 | 282 | func (self *ImmutableAvlNode) Size() int { 283 | if self == nil { 284 | return 0 285 | } 286 | return 1 + self.left.Size() + self.right.Size() 287 | } 288 | 289 | func (self *ImmutableAvlNode) Key() types.Hashable { 290 | return self.key 291 | } 292 | 293 | func (self *ImmutableAvlNode) Value() interface{} { 294 | return self.value 295 | } 296 | 297 | func (self *ImmutableAvlNode) Left() types.BinaryTreeNode { 298 | if self.left == nil { 299 | return nil 300 | } 301 | return self.left 302 | } 303 | 304 | func (self *ImmutableAvlNode) Right() types.BinaryTreeNode { 305 | if self.right == nil { 306 | return nil 307 | } 308 | return self.right 309 | } 310 | 311 | func (self *ImmutableAvlNode) GetChild(i int) types.TreeNode { 312 | return types.DoGetChild(self, i) 313 | } 314 | 315 | func (self *ImmutableAvlNode) ChildCount() int { 316 | return types.DoChildCount(self) 317 | } 318 | 319 | func (self *ImmutableAvlNode) Children() types.TreeNodeIterator { 320 | return types.MakeChildrenIterator(self) 321 | } 322 | 323 | func (self *ImmutableAvlNode) Iterate() types.KVIterator { 324 | tni := tree.TraverseBinaryTreeInOrder(self) 325 | return types.MakeKVIteratorFromTreeNodeIterator(tni) 326 | } 327 | 328 | func (self *ImmutableAvlNode) Keys() types.KIterator { 329 | return types.MakeKeysIterator(self) 330 | } 331 | 332 | func (self *ImmutableAvlNode) Values() types.Iterator { 333 | return types.MakeValuesIterator(self) 334 | } 335 | 336 | func (self *ImmutableAvlNode) _md(side func(*ImmutableAvlNode) *ImmutableAvlNode) *ImmutableAvlNode { 337 | if self == nil { 338 | return nil 339 | } else if side(self) != nil { 340 | return side(self)._md(side) 341 | } else { 342 | return self 343 | } 344 | } 345 | 346 | func (self *ImmutableAvlNode) lmd() *ImmutableAvlNode { 347 | return self._md(func(node *ImmutableAvlNode) *ImmutableAvlNode { return node.left }) 348 | } 349 | 350 | func (self *ImmutableAvlNode) rmd() *ImmutableAvlNode { 351 | return self._md(func(node *ImmutableAvlNode) *ImmutableAvlNode { return node.right }) 352 | } 353 | -------------------------------------------------------------------------------- /list/array_list.go: -------------------------------------------------------------------------------- 1 | package list 2 | 3 | import ( 4 | "bytes" 5 | "encoding/binary" 6 | "fmt" 7 | "hash/fnv" 8 | "log" 9 | "sort" 10 | "strings" 11 | ) 12 | 13 | import ( 14 | "github.com/timtadh/data-structures/errors" 15 | "github.com/timtadh/data-structures/types" 16 | ) 17 | 18 | type MList struct { 19 | List 20 | MarshalItem types.ItemMarshal 21 | UnmarshalItem types.ItemUnmarshal 22 | } 23 | 24 | func NewMList(list *List, marshal types.ItemMarshal, unmarshal types.ItemUnmarshal) *MList { 25 | return &MList{ 26 | List: *list, 27 | MarshalItem: marshal, 28 | UnmarshalItem: unmarshal, 29 | } 30 | } 31 | 32 | func (m *MList) MarshalBinary() ([]byte, error) { 33 | items := make([][]byte, 0, m.Size()) 34 | _cap := make([]byte, 4) 35 | size := make([]byte, 4) 36 | binary.LittleEndian.PutUint32(size, uint32(m.Size())) 37 | if m.List.fixed { 38 | binary.LittleEndian.PutUint32(_cap, uint32(cap(m.List.list))) 39 | items = append(items, []byte{1}) 40 | } else { 41 | binary.LittleEndian.PutUint32(_cap, uint32(m.Size())) 42 | items = append(items, []byte{0}) 43 | } 44 | items = append(items, _cap) 45 | items = append(items, size) 46 | for item, next := m.Items()(); next != nil; item, next = next() { 47 | b, err := m.MarshalItem(item) 48 | if err != nil { 49 | return nil, err 50 | } 51 | size := make([]byte, 4) 52 | binary.LittleEndian.PutUint32(size, uint32(len(b))) 53 | items = append(items, size, b) 54 | } 55 | return bytes.Join(items, []byte{}), nil 56 | } 57 | 58 | func (m *MList) UnmarshalBinary(bytes []byte) error { 59 | m.List.fixed = bytes[0] == 1 60 | _cap := int(binary.LittleEndian.Uint32(bytes[1:5])) 61 | size := int(binary.LittleEndian.Uint32(bytes[5:9])) 62 | off := 9 63 | m.list = make([]types.Hashable, 0, _cap) 64 | for i := 0; i < size; i++ { 65 | s := off 66 | e := off + 4 67 | size := int(binary.LittleEndian.Uint32(bytes[s:e])) 68 | s = e 69 | e = s + size 70 | item, err := m.UnmarshalItem(bytes[s:e]) 71 | if err != nil { 72 | return err 73 | } 74 | m.Append(item) 75 | off = e 76 | } 77 | return nil 78 | } 79 | 80 | type Sortable struct { 81 | List 82 | } 83 | 84 | func NewSortable(list *List) sort.Interface { 85 | return &Sortable{*list} 86 | } 87 | 88 | func (s *Sortable) Len() int { 89 | return s.Size() 90 | } 91 | 92 | func (s *Sortable) Less(i, j int) bool { 93 | a, err := s.Get(i) 94 | if err != nil { 95 | log.Panic(err) 96 | } 97 | b, err := s.Get(j) 98 | if err != nil { 99 | log.Panic(err) 100 | } 101 | return a.Less(b) 102 | } 103 | 104 | func (s *Sortable) Swap(i, j int) { 105 | a, err := s.Get(i) 106 | if err != nil { 107 | log.Panic(err) 108 | } 109 | b, err := s.Get(j) 110 | if err != nil { 111 | log.Panic(err) 112 | } 113 | err = s.Set(i, b) 114 | if err != nil { 115 | log.Panic(err) 116 | } 117 | err = s.Set(j, a) 118 | if err != nil { 119 | log.Panic(err) 120 | } 121 | } 122 | 123 | type List struct { 124 | list []types.Hashable 125 | fixed bool 126 | } 127 | 128 | // Creates a list. 129 | func New(initialSize int) *List { 130 | return newList(initialSize, false) 131 | } 132 | 133 | // Creates a Fixed Size list. 134 | func Fixed(size int) *List { 135 | return newList(size, true) 136 | } 137 | 138 | func newList(initialSize int, fixedSize bool) *List { 139 | return &List{ 140 | list: make([]types.Hashable, 0, initialSize), 141 | fixed: fixedSize, 142 | } 143 | } 144 | 145 | func FromSlice(list []types.Hashable) *List { 146 | l := &List{ 147 | list: make([]types.Hashable, len(list)), 148 | } 149 | copy(l.list, list) 150 | return l 151 | } 152 | 153 | func (l *List) Copy() *List { 154 | list := make([]types.Hashable, len(l.list), cap(l.list)) 155 | copy(list, l.list) 156 | return &List{list, l.fixed} 157 | } 158 | 159 | func (l *List) Clear() { 160 | l.list = l.list[:0] 161 | } 162 | 163 | func (l *List) Size() int { 164 | return len(l.list) 165 | } 166 | 167 | func (l *List) Full() bool { 168 | return l.fixed && cap(l.list) == len(l.list) 169 | } 170 | 171 | func (l *List) Empty() bool { 172 | return len(l.list) == 0 173 | } 174 | 175 | func (l *List) Has(item types.Hashable) (has bool) { 176 | for i := range l.list { 177 | if l.list[i].Equals(item) { 178 | return true 179 | } 180 | } 181 | return false 182 | } 183 | 184 | func (l *List) Equals(b types.Equatable) bool { 185 | if o, ok := b.(types.IterableContainer); ok { 186 | return Equals(l, o) 187 | } else { 188 | return false 189 | } 190 | } 191 | 192 | func Equals(a, b types.IterableContainer) bool { 193 | if a.Size() != b.Size() { 194 | return false 195 | } 196 | ca, ai := a.Items()() 197 | cb, bi := b.Items()() 198 | for ai != nil || bi != nil { 199 | if !ca.Equals(cb) { 200 | return false 201 | } 202 | ca, ai = ai() 203 | cb, bi = bi() 204 | } 205 | return true 206 | } 207 | 208 | func (l *List) Less(b types.Sortable) bool { 209 | if o, ok := b.(types.IterableContainer); ok { 210 | return Less(l, o) 211 | } else { 212 | return false 213 | } 214 | } 215 | 216 | func Less(a, b types.IterableContainer) bool { 217 | if a.Size() < b.Size() { 218 | return true 219 | } else if a.Size() > b.Size() { 220 | return false 221 | } 222 | ca, ai := a.Items()() 223 | cb, bi := b.Items()() 224 | for ai != nil || bi != nil { 225 | if ca.Less(cb) { 226 | return true 227 | } else if !ca.Equals(cb) { 228 | return false 229 | } 230 | ca, ai = ai() 231 | cb, bi = bi() 232 | } 233 | return false 234 | } 235 | 236 | func (l *List) Hash() int { 237 | h := fnv.New32a() 238 | if len(l.list) == 0 { 239 | return 0 240 | } 241 | bs := make([]byte, 4) 242 | for _, item := range l.list { 243 | binary.LittleEndian.PutUint32(bs, uint32(item.Hash())) 244 | h.Write(bs) 245 | } 246 | return int(h.Sum32()) 247 | } 248 | 249 | func Hash(a types.ListIterable) int { 250 | h := fnv.New32a() 251 | bs := make([]byte, 4) 252 | for item, next := a.Items()(); next != nil; item, next = next() { 253 | binary.LittleEndian.PutUint32(bs, uint32(item.Hash())) 254 | h.Write(bs) 255 | } 256 | return int(h.Sum32()) 257 | } 258 | 259 | func (l *List) Items() (it types.KIterator) { 260 | i := 0 261 | return func() (item types.Hashable, next types.KIterator) { 262 | if i < len(l.list) { 263 | item = l.list[i] 264 | i++ 265 | return item, it 266 | } 267 | return nil, nil 268 | } 269 | } 270 | 271 | func (l *List) ItemsInReverse() (it types.KIterator) { 272 | i := len(l.list) - 1 273 | return func() (item types.Hashable, next types.KIterator) { 274 | if i >= 0 { 275 | item = l.list[i] 276 | i-- 277 | return item, it 278 | } 279 | return nil, nil 280 | } 281 | } 282 | 283 | func (l *List) Get(i int) (item types.Hashable, err error) { 284 | if i < 0 || i >= len(l.list) { 285 | return nil, errors.Errorf("Access out of bounds. len(*List) = %v, idx = %v", len(l.list), i) 286 | } 287 | return l.list[i], nil 288 | } 289 | 290 | func (l *List) Set(i int, item types.Hashable) (err error) { 291 | if i < 0 || i >= len(l.list) { 292 | return errors.Errorf("Access out of bounds. len(*List) = %v, idx = %v", len(l.list), i) 293 | } 294 | l.list[i] = item 295 | return nil 296 | } 297 | 298 | func (l *List) Push(item types.Hashable) error { 299 | return l.Append(item) 300 | } 301 | 302 | func (l *List) Append(item types.Hashable) error { 303 | return l.Insert(len(l.list), item) 304 | } 305 | 306 | func (l *List) Insert(i int, item types.Hashable) error { 307 | if i < 0 || i > len(l.list) { 308 | return errors.Errorf("Access out of bounds. len(*List) = %v, idx = %v", len(l.list), i) 309 | } 310 | if len(l.list) == cap(l.list) { 311 | if err := l.expand(); err != nil { 312 | return err 313 | } 314 | } 315 | l.list = l.list[:len(l.list)+1] 316 | for j := len(l.list) - 1; j > 0; j-- { 317 | if j == i { 318 | l.list[i] = item 319 | break 320 | } 321 | l.list[j] = l.list[j-1] 322 | } 323 | if i == 0 { 324 | l.list[i] = item 325 | } 326 | return nil 327 | } 328 | 329 | func (l *List) Extend(it types.KIterator) (err error) { 330 | for item, next := it(); next != nil; item, next = next() { 331 | if err := l.Append(item); err != nil { 332 | return err 333 | } 334 | } 335 | return nil 336 | } 337 | 338 | func (l *List) Pop() (item types.Hashable, err error) { 339 | item, err = l.Get(len(l.list) - 1) 340 | if err != nil { 341 | return nil, err 342 | } 343 | err = l.Remove(len(l.list) - 1) 344 | if err != nil { 345 | return nil, err 346 | } 347 | return item, nil 348 | } 349 | 350 | func (l *List) Remove(i int) error { 351 | if i < 0 || i >= len(l.list) { 352 | return errors.Errorf("Access out of bounds. len(*List) = %v, idx = %v", len(l.list), i) 353 | } 354 | dst := l.list[i : len(l.list)-1] 355 | src := l.list[i+1 : len(l.list)] 356 | copy(dst, src) 357 | l.list = l.list[:len(l.list)-1] 358 | if err := l.shrink(); err != nil { 359 | return err 360 | } 361 | return nil 362 | } 363 | 364 | func (l *List) String() string { 365 | if len(l.list) <= 0 { 366 | return "{}" 367 | } 368 | items := make([]string, 0, len(l.list)) 369 | for _, item := range l.list { 370 | items = append(items, fmt.Sprintf("%v", item)) 371 | } 372 | return "{" + strings.Join(items, ", ") + "}" 373 | } 374 | 375 | func (l *List) expand() error { 376 | if l.fixed { 377 | return errors.Errorf("Fixed size list is full!") 378 | } 379 | list := l.list 380 | if cap(list) < 100 && cap(list) != 0 { 381 | l.list = make([]types.Hashable, len(list), cap(list)*2) 382 | } else { 383 | l.list = make([]types.Hashable, len(list), cap(list)+100) 384 | } 385 | copy(l.list, list) 386 | return nil 387 | } 388 | 389 | func (l *List) shrink() error { 390 | if l.fixed { 391 | return nil 392 | } 393 | if (len(l.list)-1)*2 >= cap(l.list) || cap(l.list)/2 <= 10 { 394 | return nil 395 | } 396 | list := l.list 397 | l.list = make([]types.Hashable, len(list), cap(list)/2+1) 398 | copy(l.list, list) 399 | return nil 400 | } 401 | --------------------------------------------------------------------------------