├── README.md ├── array_deque ├── array_deque.go └── array_deque_test.go ├── array_queue ├── array_queue.go └── array_queue_test.go ├── array_stack ├── array_stack.go └── array_stack_test.go ├── binary_heap ├── binary_heap.go └── binary_heap_test.go ├── binary_search_tree ├── binary_search_tree.go └── binary_search_tree_test.go ├── binary_tree ├── binary_tree.go └── binary_tree_test.go ├── chained_hash_table ├── chained_hash_table.go └── chained_hash_table_test.go ├── dllist ├── dllist.go └── dllist_test.go ├── dual_array_deque ├── dual_array_deque.go └── dual_array_deque_test.go ├── fast_array_stack ├── fast_array_stack.go └── fast_array_stack_test.go ├── linear_hash_table ├── linear_hash_table.go └── linear_hash_table_test.go ├── meldable_heap ├── meldable_heap.go └── meldable_heap_test.go ├── rootish_array_stack ├── rootish_array_stack.go └── rootish_array_stack_test.go ├── scapegoat_tree ├── scapegoat_tree.go └── scapegoat_tree_test.go ├── skiplistlist ├── skiplistlist.go └── skiplistlist_test.go ├── skiplistsset ├── skiplistsset.go └── skiplistsset_test.go ├── sllist ├── sllist.go └── sllist_test.go ├── sort ├── sort.go └── sort_test.go ├── test.sh ├── treap ├── treap.go └── treap_test.go └── utils ├── utils.go └── utils_test.go /README.md: -------------------------------------------------------------------------------- 1 | # ods-go 2 | 3 | Go implementation of [data structures in Open Data Structures (ODS)](https://sites.google.com/view/open-data-structures-ja/home) 4 | 5 | [みんなのデータ構造](https://sites.google.com/view/open-data-structures-ja/home)に載っている主なデータ構造の実装と、その簡単なテストコードが入っています。 6 | 7 | 翻訳しているときに、理解の正しさを確認するため、コードを書いてテストするために作ったレポジトリです。 8 | -------------------------------------------------------------------------------- /array_deque/array_deque.go: -------------------------------------------------------------------------------- 1 | package array_deque 2 | 3 | import "github.com/spinute/ods-go/utils" 4 | 5 | type ArrayDeque struct { 6 | n, cap, i int 7 | buf []utils.V 8 | } 9 | 10 | func New() ArrayDeque { 11 | return ArrayDeque{} 12 | } 13 | 14 | func (ad ArrayDeque) buf_i(i int) int { 15 | return (ad.i + i) % ad.cap 16 | } 17 | func (ad ArrayDeque) buf_get(i int) utils.V { 18 | return ad.buf[ad.buf_i(i)] 19 | } 20 | func (ad *ArrayDeque) buf_set(i int, v utils.V) { 21 | ad.buf[ad.buf_i(i)] = v 22 | } 23 | 24 | func (ad ArrayDeque) Get(i int) utils.V { 25 | return ad.buf_get(i) 26 | } 27 | 28 | func (ad *ArrayDeque) Set(i int, v utils.V) utils.V { 29 | ret := ad.buf_get(i) 30 | ad.buf_set(i, v) 31 | return ret 32 | } 33 | 34 | func mod_pred(i, mod int) int { 35 | if i == 0 { 36 | return mod - 1 37 | } else { 38 | return i - 1 39 | } 40 | } 41 | 42 | func (ad *ArrayDeque) Add(i int, v utils.V) { 43 | if ad.is_full() { 44 | ad.resize() 45 | } 46 | 47 | if i < ad.n/2 { 48 | ad.i = mod_pred(ad.i, ad.cap) 49 | for j := 0; j < i; j++ { 50 | ad.buf_set(j, ad.buf_get(j+1)) 51 | } 52 | } else { 53 | for j := ad.n; j > i; j-- { 54 | ad.buf_set(j, ad.buf_get(j-1)) 55 | } 56 | } 57 | ad.buf_set(i, v) 58 | ad.n++ 59 | } 60 | 61 | func mod_succ(i, mod int) int { 62 | return (i + 1) % mod 63 | } 64 | 65 | func (ad *ArrayDeque) Remove(i int) utils.V { 66 | ret := ad.buf_get(i) 67 | if i < ad.n/2 { 68 | for j := i; j > 0; j-- { 69 | ad.buf_set(j, ad.buf_get(j-1)) 70 | } 71 | ad.i = mod_succ(ad.i, ad.cap) 72 | } else { 73 | for j := i; j < ad.n-1; j++ { 74 | ad.buf_set(j, ad.buf_get(j+1)) 75 | } 76 | } 77 | ad.n-- 78 | if ad.is_sparse() { 79 | ad.resize() 80 | } 81 | return ret 82 | } 83 | 84 | func (ad ArrayDeque) is_full() bool { 85 | return ad.n == ad.cap 86 | } 87 | 88 | func (ad ArrayDeque) is_sparse() bool { 89 | return len(ad.buf) >= 3*ad.n 90 | } 91 | 92 | func (ad *ArrayDeque) resize() { 93 | cap_new := utils.Max(2*ad.n, 1) 94 | buf_new := make([]utils.V, cap_new) 95 | for i := 0; i < ad.n; i++ { 96 | buf_new[i] = ad.buf_get(i) 97 | } 98 | ad.i = 0 99 | ad.buf = buf_new 100 | ad.cap = cap_new 101 | } 102 | -------------------------------------------------------------------------------- /array_deque/array_deque_test.go: -------------------------------------------------------------------------------- 1 | package array_deque 2 | 3 | import ( 4 | "github.com/spinute/ods-go/utils" 5 | "testing" 6 | ) 7 | 8 | func TestNew(t *testing.T) { 9 | if ret := New().n; ret != 0 { 10 | t.Errorf("ArrayDeque.New().n = %v", ret) 11 | } 12 | } 13 | 14 | func TestAddHead(t *testing.T) { 15 | n := 10 16 | ad := New() 17 | 18 | for i := 0; i < n; i++ { 19 | ad.Add(0, utils.V(i)) 20 | if ad.n != i+1 { 21 | t.Errorf("ad.n = %v at %v th Add", ad.n, i+1) 22 | } 23 | } 24 | } 25 | 26 | func TestAddMid(t *testing.T) { 27 | n := 10 28 | ad := New() 29 | for i := 0; i < n; i++ { 30 | ad.Add(0, utils.V(i)) 31 | } 32 | 33 | for i := 0; i < n; i++ { 34 | mid := n / 2 35 | ad.Add(mid, utils.V(i)) 36 | if ad.n != n+i+1 { 37 | t.Errorf("ad.n = %v at %v th Add", ad.n, n+i+1) 38 | } 39 | } 40 | } 41 | 42 | func TestAddLast(t *testing.T) { 43 | n := 10 44 | ad := New() 45 | 46 | for i := 0; i < n; i++ { 47 | ad.Add(i, utils.V(i)) 48 | if ad.n != i+1 { 49 | t.Errorf("ad.n = %v at %v th Add", ad.n, i+1) 50 | } 51 | } 52 | } 53 | 54 | func TestGet(t *testing.T) { 55 | n := 10 56 | ad := New() 57 | for i := 0; i < n; i++ { 58 | ad.Add(i, utils.V(i)) 59 | } 60 | 61 | for i := 0; i < n; i++ { 62 | if ret := ad.Get(i); ret != utils.V(i) { 63 | t.Errorf("ad.Get(%v) = %v", i, ret) 64 | } 65 | } 66 | } 67 | 68 | func TestSet(t *testing.T) { 69 | n := 10 70 | ad := New() 71 | for i := 0; i < n; i++ { 72 | ad.Add(0, utils.V(i)) 73 | } 74 | 75 | ofs := 1000 76 | for i := 0; i < n; i++ { 77 | if ret := ad.Set(i, utils.V(ofs+i)); ret != utils.V(n-i-1) { 78 | t.Errorf("ad.Set(%v) = %v", i, ret) 79 | } 80 | } 81 | for i := 0; i < n; i++ { 82 | if ret := ad.Get(i); ret != utils.V(ofs+i) { 83 | t.Errorf("ad.Get(%v) = %v", i, ret) 84 | } 85 | } 86 | } 87 | 88 | func TestRemove(t *testing.T) { 89 | n := 10 90 | ad := New() 91 | for i := 0; i < n; i++ { 92 | ad.Add(0, utils.V(i)) 93 | } 94 | 95 | mid := n / 2 96 | for i := mid; i < n; i++ { 97 | if ret := ad.Remove(mid); ret != utils.V(n-i-1) { 98 | t.Errorf("%v th ad.Remove(mid) = %v", i-mid+1, ret) 99 | } 100 | } 101 | for i := 0; i < mid; i++ { 102 | if ret := ad.Remove(0); ret != utils.V(n-i-1) { 103 | t.Errorf("ad.Remove(head) = %v", ret) 104 | } 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /array_queue/array_queue.go: -------------------------------------------------------------------------------- 1 | package array_queue 2 | 3 | import "github.com/spinute/ods-go/utils" 4 | 5 | type ArrayQueue struct { 6 | n, cap, i int 7 | buf []utils.V 8 | } 9 | 10 | func New() ArrayQueue { 11 | return ArrayQueue{} 12 | } 13 | 14 | func (as *ArrayQueue) Add(v utils.V) { 15 | if as.is_full() { 16 | as.resize() 17 | } 18 | as.buf[(as.i+as.n)%as.cap] = v 19 | as.n++ 20 | } 21 | 22 | func (as *ArrayQueue) Remove() utils.V { 23 | ret := as.buf[as.i] 24 | as.i = (as.i + 1) % as.cap 25 | as.n-- 26 | if as.is_sparse() { 27 | as.resize() 28 | } 29 | return ret 30 | } 31 | 32 | func (as ArrayQueue) is_full() bool { 33 | return as.n == as.cap 34 | } 35 | 36 | func (as ArrayQueue) is_sparse() bool { 37 | return len(as.buf) >= 3*as.n 38 | } 39 | 40 | func (as *ArrayQueue) resize() { 41 | cap_new := utils.Max(2*as.n, 1) 42 | buf_new := make([]utils.V, cap_new) 43 | for i := 0; i < as.n; i++ { 44 | buf_new[i] = as.buf[(i+as.i)%as.cap] 45 | } 46 | as.buf = buf_new 47 | as.cap = cap_new 48 | as.i = 0 49 | } 50 | -------------------------------------------------------------------------------- /array_queue/array_queue_test.go: -------------------------------------------------------------------------------- 1 | package array_queue 2 | 3 | import ( 4 | "github.com/spinute/ods-go/utils" 5 | "testing" 6 | ) 7 | 8 | func TestNew(t *testing.T) { 9 | if ret := New().n; ret != 0 { 10 | t.Errorf("ArrayQueue.New().n = %v", ret) 11 | } 12 | } 13 | 14 | func TestAdd(t *testing.T) { 15 | tests := []utils.V{1, 2, 1, -1, -2, -100, 0, 0} 16 | aq := New() 17 | 18 | for i, v := range tests { 19 | aq.Add(v) 20 | if aq.n != i+1 { 21 | t.Errorf("aq.n = %v at %v th Add", aq.n, i+1) 22 | } 23 | } 24 | } 25 | 26 | func TestAddMany(t *testing.T) { 27 | tests := make([]utils.V, 12345) 28 | aq := New() 29 | 30 | for i, v := range tests { 31 | aq.Add(v) 32 | if aq.n != i+1 { 33 | t.Errorf("aq.n = %v at %v th Add", aq.n, i+1) 34 | } 35 | } 36 | } 37 | 38 | func TestAddAndRemove(t *testing.T) { 39 | tests := []utils.V{1, 2, 1, -1, -2, -100, 0, 0} 40 | aq := New() 41 | 42 | for _, v := range tests { 43 | aq.Add(v) 44 | if ret := aq.Remove(); ret != v { 45 | t.Errorf("Add %v, then %v was removed", v, ret) 46 | } 47 | } 48 | } 49 | 50 | func TestAddAndRemove2(t *testing.T) { 51 | n := 123 52 | aq := New() 53 | 54 | for i := 0; i < n; i++ { 55 | aq.Add(utils.V(i)) 56 | } 57 | 58 | for i := 0; i < n; i++ { 59 | if ret, want := aq.Remove(), utils.V(i); ret != want { 60 | t.Errorf("expect %d but returned %d", ret, want) 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /array_stack/array_stack.go: -------------------------------------------------------------------------------- 1 | package array_stack 2 | 3 | import ( 4 | "github.com/spinute/ods-go/utils" 5 | ) 6 | 7 | type ArrayStack struct { 8 | n, cap int 9 | buf []utils.V 10 | } 11 | 12 | func New() ArrayStack { 13 | return ArrayStack{} 14 | } 15 | 16 | func (as ArrayStack) Size() int { 17 | return as.n 18 | } 19 | 20 | func (as *ArrayStack) Push(v utils.V) { 21 | as.Add(as.n, v) 22 | } 23 | 24 | func (as *ArrayStack) Pop() utils.V { 25 | return as.Remove(as.n - 1) 26 | } 27 | 28 | func (as ArrayStack) Get(i int) utils.V { 29 | return as.buf[i] 30 | } 31 | 32 | func (as *ArrayStack) Set(i int, v utils.V) utils.V { 33 | ret := as.buf[i] 34 | as.buf[i] = v 35 | return ret 36 | } 37 | 38 | func (as *ArrayStack) Add(i int, v utils.V) { 39 | if as.is_full() { 40 | as.resize() 41 | } 42 | for j := as.n; j > i; j-- { 43 | as.buf[j] = as.buf[j-1] 44 | } 45 | as.buf[i] = v 46 | as.n++ 47 | } 48 | 49 | func (as *ArrayStack) Remove(i int) utils.V { 50 | ret := as.buf[i] 51 | for j := i; j < as.n-1; j++ { 52 | as.buf[j] = as.buf[j+1] 53 | } 54 | as.n-- 55 | if as.is_sparse() { 56 | as.resize() 57 | } 58 | return ret 59 | } 60 | 61 | func (as ArrayStack) is_full() bool { 62 | return as.n == as.cap 63 | } 64 | 65 | func (as ArrayStack) is_sparse() bool { 66 | return len(as.buf) >= 3*as.n 67 | } 68 | 69 | func (as *ArrayStack) resize() { 70 | as.cap = utils.Max(2*as.n, 1) 71 | buf_new := make([]utils.V, as.cap) 72 | for i := 0; i < as.n; i++ { 73 | buf_new[i] = as.buf[i] 74 | } 75 | as.buf = buf_new 76 | } 77 | -------------------------------------------------------------------------------- /array_stack/array_stack_test.go: -------------------------------------------------------------------------------- 1 | package array_stack 2 | 3 | import ( 4 | "github.com/spinute/ods-go/utils" 5 | "testing" 6 | ) 7 | 8 | func TestNew(t *testing.T) { 9 | if ret := New().n; ret != 0 { 10 | t.Errorf("ArrayStack.New().n = %v", ret) 11 | } 12 | } 13 | 14 | func TestPush(t *testing.T) { 15 | tests := []utils.V{1, 2, 1, -1, -2, -100, 0, 0} 16 | as := New() 17 | 18 | for i, v := range tests { 19 | as.Push(v) 20 | if as.n != i+1 { 21 | t.Errorf("as.n = %v at %v th push", as.n, i+1) 22 | } 23 | } 24 | } 25 | 26 | func TestPushMany(t *testing.T) { 27 | tests := make([]utils.V, 12345) 28 | as := New() 29 | 30 | for i, v := range tests { 31 | as.Push(v) 32 | if as.n != i+1 { 33 | t.Errorf("as.n = %v at %v th push", as.n, i+1) 34 | } 35 | } 36 | } 37 | 38 | func TestPushAndPop(t *testing.T) { 39 | tests := []utils.V{1, 2, 1, -1, -2, -100, 0, 0} 40 | as := New() 41 | 42 | for _, v := range tests { 43 | as.Push(v) 44 | if ret := as.Pop(); ret != v { 45 | t.Errorf("pushed %v, then %v was poped", v, ret) 46 | } 47 | } 48 | } 49 | 50 | func TestPushAndPop2(t *testing.T) { 51 | n := 123 52 | as := New() 53 | 54 | for i := 0; i < n; i++ { 55 | as.Push(utils.V(i + 1)) 56 | } 57 | 58 | for i := 0; i < n; i++ { 59 | if ret, want := as.Pop(), utils.V(n-i); ret != want { 60 | t.Errorf("expect %d but returned %d", ret, want) 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /binary_heap/binary_heap.go: -------------------------------------------------------------------------------- 1 | package binary_heap 2 | 3 | import ( 4 | "github.com/spinute/ods-go/utils" 5 | ) 6 | 7 | type BinaryHeap struct { 8 | n int 9 | a []utils.V 10 | } 11 | 12 | func New() *BinaryHeap { 13 | return &BinaryHeap{} 14 | } 15 | 16 | func left(i int) int { 17 | return 2*i + 1 18 | } 19 | func right(i int) int { 20 | return 2*i + 2 21 | } 22 | func parent(i int) int { 23 | return (i - 1) / 2 24 | } 25 | 26 | func (bh *BinaryHeap) Add(x utils.V) bool { 27 | if bh.n+1 > len(bh.a) { 28 | bh.resize() 29 | } 30 | bh.a[bh.n] = x 31 | bh.n++ 32 | bh.bubbleUp(bh.n - 1) 33 | return true 34 | } 35 | func (bh *BinaryHeap) bubbleUp(i int) { 36 | p := parent(i) 37 | for i > 0 && utils.Compare(bh.a[i], bh.a[p]) < 0 { 38 | tmp := bh.a[i] 39 | bh.a[i] = bh.a[p] 40 | bh.a[p] = tmp 41 | 42 | i = p 43 | p = parent(i) 44 | } 45 | } 46 | 47 | func (bh *BinaryHeap) resize() { 48 | cap_new := utils.Max(2*bh.n, 1) 49 | a_new := make([]utils.V, cap_new) 50 | copy(a_new, bh.a) 51 | bh.a = a_new 52 | } 53 | 54 | func (bh *BinaryHeap) Remove() utils.V { 55 | x := bh.a[0] 56 | bh.n-- 57 | bh.a[0] = bh.a[bh.n] 58 | bh.trickleDown(0) 59 | if 3*bh.n < len(bh.a) { 60 | bh.resize() 61 | } 62 | return x 63 | } 64 | func (bh *BinaryHeap) trickleDown(i int) { 65 | for i >= 0 { 66 | j := -1 67 | r := right(i) 68 | if r < bh.n && utils.Compare(bh.a[r], bh.a[i]) < 0 { 69 | l := left(i) 70 | if utils.Compare(bh.a[l], bh.a[r]) < 0 { 71 | j = l 72 | } else { 73 | j = r 74 | } 75 | } else { 76 | l := left(i) 77 | if l < bh.n && utils.Compare(bh.a[l], bh.a[i]) < 0 { 78 | j = l 79 | } 80 | } 81 | if j >= 0 { 82 | tmp := bh.a[i] 83 | bh.a[i] = bh.a[j] 84 | bh.a[j] = tmp 85 | } 86 | i = j 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /binary_heap/binary_heap_test.go: -------------------------------------------------------------------------------- 1 | package binary_heap 2 | 3 | import ( 4 | "github.com/spinute/ods-go/utils" 5 | "testing" 6 | ) 7 | 8 | func TestNew(t *testing.T) { 9 | if ret := New().n; ret != 0 { 10 | t.Errorf("BinaryHeap.New().n = %v", ret) 11 | } 12 | } 13 | 14 | func TestAdd(t *testing.T) { 15 | tests := []utils.V{1, 2, 1, -1, -2, -100, 0, 0} 16 | bh := New() 17 | 18 | for i, v := range tests { 19 | bh.Add(v) 20 | if bh.n != i+1 { 21 | t.Errorf("bh.n = %v at %v th Add", bh.n, i+1) 22 | } 23 | } 24 | } 25 | 26 | func TestAddMany(t *testing.T) { 27 | tests := make([]utils.V, 12345) 28 | bh := New() 29 | 30 | for i, v := range tests { 31 | bh.Add(v) 32 | if bh.n != i+1 { 33 | t.Errorf("bh.n = %v at %v th Add", bh.n, i+1) 34 | } 35 | } 36 | } 37 | 38 | func TestAddAndRemove(t *testing.T) { 39 | tests := []utils.V{1, 2, 1, -1, -2, -100, 0, 0} 40 | bh := New() 41 | 42 | for _, v := range tests { 43 | bh.Add(v) 44 | if ret := bh.Remove(); ret != v { 45 | t.Errorf("Add %v, then %v was removed", v, ret) 46 | } 47 | } 48 | } 49 | 50 | func TestAddAndRemove2(t *testing.T) { 51 | n := 123 52 | bh := New() 53 | 54 | for i := 0; i < n; i++ { 55 | bh.Add(utils.V(i)) 56 | } 57 | 58 | for i := 0; i < n; i++ { 59 | if ret, want := bh.Remove(), utils.V(i); ret != want { 60 | t.Errorf("expect %d but returned %d", ret, want) 61 | } 62 | } 63 | } 64 | 65 | func TestAddAndRemove3(t *testing.T) { 66 | n := 123 67 | bh := New() 68 | 69 | for i := 0; i < n; i++ { 70 | bh.Add(utils.V(n - i - 1)) 71 | } 72 | 73 | for i := 0; i < n; i++ { 74 | if ret, want := bh.Remove(), utils.V(i); ret != want { 75 | t.Errorf("expect %d but returned %d", ret, want) 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /binary_search_tree/binary_search_tree.go: -------------------------------------------------------------------------------- 1 | package binary_search_tree 2 | 3 | import "github.com/spinute/ods-go/utils" 4 | 5 | type node struct { 6 | left, right, parent *node 7 | x utils.V 8 | } 9 | 10 | type BinarySearchTree struct { 11 | r *node 12 | n int 13 | } 14 | 15 | func New() *BinarySearchTree { 16 | return &BinarySearchTree{} 17 | } 18 | 19 | func (bst *BinarySearchTree) FindEQ(x utils.V) bool { 20 | w := bst.r 21 | for w != nil { 22 | comp := utils.Compare(x, w.x) 23 | if comp < 0 { 24 | w = w.left 25 | } else if comp > 0 { 26 | w = w.right 27 | } else { 28 | return true 29 | } 30 | } 31 | return false 32 | } 33 | 34 | func (bst *BinarySearchTree) Find(x utils.V) *utils.V { 35 | w := bst.r 36 | var ret *node = nil 37 | for w != nil { 38 | comp := utils.Compare(x, w.x) 39 | if comp < 0 { 40 | ret = w 41 | w = w.left 42 | } else if comp > 0 { 43 | w = w.right 44 | } else { 45 | return &w.x 46 | } 47 | } 48 | if ret == nil { 49 | return nil 50 | } 51 | return &ret.x 52 | } 53 | 54 | func (bst *BinarySearchTree) Add(x utils.V) bool { 55 | var ret bool 56 | lastNode := bst.findLast(x) 57 | newNode := node{x: x} 58 | if lastNode == nil { 59 | bst.r = &newNode 60 | ret = true 61 | } else { 62 | ret = addChild(lastNode, &newNode) 63 | } 64 | if ret == true { 65 | bst.n++ 66 | } 67 | return ret 68 | } 69 | func (bst *BinarySearchTree) findLast(x utils.V) *node { 70 | w := bst.r 71 | last := w 72 | for w != nil { 73 | comp := utils.Compare(x, w.x) 74 | last = w 75 | if comp < 0 { 76 | w = w.left 77 | } else if comp > 0 { 78 | w = w.right 79 | } else { 80 | return w 81 | } 82 | } 83 | return last 84 | } 85 | func addChild(p, c *node) bool { 86 | comp := utils.Compare(c.x, p.x) 87 | if comp < 0 { 88 | p.left = c 89 | } else if comp > 0 { 90 | p.right = c 91 | } else { 92 | return false 93 | } 94 | c.parent = p 95 | return true 96 | } 97 | 98 | func (bst *BinarySearchTree) Remove(x utils.V) bool { 99 | node := bst.findLast(x) 100 | if node != nil && utils.Compare(x, node.x) == 0 { 101 | bst.removeNode(node) 102 | return true 103 | } 104 | return false 105 | } 106 | func (bst *BinarySearchTree) removeNode(node *node) { 107 | if node.left == nil || node.right == nil { 108 | bst.splice(node) 109 | } else { 110 | minInRight := node.right 111 | for minInRight.left != nil { 112 | minInRight = minInRight.left 113 | } 114 | node.x = minInRight.x 115 | bst.splice(minInRight) 116 | } 117 | bst.n-- 118 | } 119 | func (bst *BinarySearchTree) splice(n *node) { 120 | var c, p *node 121 | if n.left != nil { 122 | c = n.left 123 | } else { 124 | c = n.right 125 | } 126 | 127 | if bst.r == n { 128 | bst.r = c 129 | p = nil 130 | } else { 131 | p = n.parent 132 | if n == p.left { 133 | p.left = c 134 | } else { 135 | p.right = c 136 | } 137 | } 138 | 139 | if c != nil { 140 | c.parent = p 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /binary_search_tree/binary_search_tree_test.go: -------------------------------------------------------------------------------- 1 | package binary_search_tree 2 | 3 | import ( 4 | "github.com/spinute/ods-go/utils" 5 | "testing" 6 | ) 7 | 8 | func TestNew(t *testing.T) { 9 | if ret := New().n; ret != 0 { 10 | t.Errorf("BinarySearchTree.New().n = %v", ret) 11 | } 12 | } 13 | 14 | func TestAdd(t *testing.T) { 15 | n := 10 16 | bst := New() 17 | 18 | for i := 0; i < n; i++ { 19 | ret := bst.Add(utils.V(i)) 20 | if bst.n != i+1 { 21 | t.Errorf("bst.n = %v at %v th Add", bst.n, i+1) 22 | } 23 | if ret == false { 24 | t.Errorf("Add returned false unexpectedly") 25 | } 26 | } 27 | 28 | for i := 0; i < n; i++ { 29 | ret := bst.Add(utils.V(i)) 30 | if bst.n != n { 31 | t.Errorf("bst.n = %v", bst.n) 32 | } 33 | if ret == true { 34 | t.Errorf("Add returned true unexpectedly") 35 | } 36 | } 37 | } 38 | 39 | func TestFindEQ(t *testing.T) { 40 | n := 10 41 | bst := New() 42 | 43 | for i := 0; i < n; i++ { 44 | ret := bst.FindEQ(utils.V(i)) 45 | if ret == true { 46 | t.Errorf("Add returned non-nil unexpectedly, ret=%v", ret) 47 | } 48 | } 49 | 50 | for i := 0; i < n; i++ { 51 | bst.Add(utils.V(i)) 52 | ret := bst.FindEQ(utils.V(i)) 53 | if ret == false { 54 | t.Errorf("Add returned nil unexpectedly") 55 | } 56 | } 57 | 58 | ret := bst.FindEQ(utils.V(n + 123)) 59 | if ret == true { 60 | t.Errorf("Add returned nil unexpectedly") 61 | } 62 | } 63 | 64 | func TestFind(t *testing.T) { 65 | n := 10 66 | bst := New() 67 | 68 | for i := 0; i < n; i++ { 69 | ret := bst.Find(utils.V(i)) 70 | if ret != nil { 71 | t.Errorf("non-nil unexpectedly, ret=%d", ret) 72 | } 73 | } 74 | 75 | for i := 0; i < n; i++ { 76 | bst.Add(utils.V(i)) 77 | ret := bst.Find(utils.V(i)) 78 | if ret == nil { 79 | t.Errorf("Find returned nil unexpectedly") 80 | } 81 | } 82 | 83 | ret := bst.Find(utils.V(n - 123)) 84 | if *ret != utils.V(0) { 85 | t.Errorf("unexpectedly returned %v", *ret) 86 | } 87 | } 88 | 89 | func TestRemove(t *testing.T) { 90 | x := utils.V(-12345) 91 | bst := New() 92 | 93 | if bst.Remove(x) == true { 94 | t.Errorf("Add returned true unexpectedly") 95 | } 96 | 97 | bst.Add(x) 98 | if bst.Remove(x) == false { 99 | t.Errorf("Add returned false unexpectedly") 100 | } 101 | 102 | if bst.Find(x) != nil { 103 | t.Errorf("Add returned non-nil unexpectedly") 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /binary_tree/binary_tree.go: -------------------------------------------------------------------------------- 1 | package binary_tree 2 | 3 | import "github.com/spinute/ods-go/utils" 4 | 5 | type node struct { 6 | left, right, parent *node 7 | } 8 | 9 | func nodeNew() *node { 10 | return &node{} 11 | } 12 | 13 | type BinaryTree struct { 14 | r *node 15 | } 16 | 17 | func (bt BinaryTree) Depth(n *node) int { 18 | d := 0 19 | for n != bt.r { 20 | d++ 21 | n = n.parent 22 | } 23 | return d 24 | } 25 | 26 | func size_subtree(n *node) int { 27 | if n == nil { 28 | return 0 29 | } 30 | return size_subtree(n.left) + size_subtree(n.right) + 1 31 | } 32 | 33 | func (bt BinaryTree) Size() int { 34 | return size_subtree(bt.r) 35 | } 36 | 37 | func height_subtree(n *node) int { 38 | if n == nil { 39 | return -1 40 | } 41 | return utils.Max(height_subtree(n.left), height_subtree(n.right)) + 1 42 | } 43 | 44 | func (bt BinaryTree) Height() int { 45 | return height_subtree(bt.r) 46 | } 47 | -------------------------------------------------------------------------------- /binary_tree/binary_tree_test.go: -------------------------------------------------------------------------------- 1 | package binary_tree 2 | 3 | import "testing" 4 | 5 | func empty_bt() *BinaryTree { 6 | return &BinaryTree{} 7 | } 8 | 9 | func sample_bt() *BinaryTree { 10 | n1 := nodeNew() 11 | n2 := nodeNew() 12 | n3 := nodeNew() 13 | n4 := nodeNew() 14 | 15 | n1.left = n2 16 | n2.parent = n1 17 | n1.right = n3 18 | n3.parent = n1 19 | n2.right = n4 20 | n4.parent = n2 21 | 22 | return &BinaryTree{ 23 | r: n1, 24 | } 25 | } 26 | 27 | func TestDepth(t *testing.T) { 28 | bt := sample_bt() 29 | 30 | r := bt.r 31 | tests := []struct { 32 | arg *node 33 | expected int 34 | }{ 35 | {r, 0}, 36 | {r.left, 1}, 37 | {r.right, 1}, 38 | {r.left.right, 2}, 39 | } 40 | for _, test := range tests { 41 | if ret := bt.Depth(test.arg); ret != test.expected { 42 | t.Errorf("bt.Depth(%v) = %v", test.arg, ret) 43 | } 44 | } 45 | } 46 | 47 | func TestSize(t *testing.T) { 48 | bt := sample_bt() 49 | if ret := bt.Size(); ret != 4 { 50 | t.Errorf("bt.Size = %v", ret) 51 | } 52 | } 53 | func Test_size_subtree(t *testing.T) { 54 | bt := sample_bt() 55 | 56 | r := bt.r 57 | tests := []struct { 58 | arg *node 59 | expected int 60 | }{ 61 | {r, 4}, 62 | {r.left, 2}, 63 | {r.right, 1}, 64 | {r.left.right, 1}, 65 | {r.left.left, 0}, 66 | } 67 | for _, test := range tests { 68 | if ret := size_subtree(test.arg); ret != test.expected { 69 | t.Errorf("size_subtree(%v) = %v", test.arg, ret) 70 | } 71 | } 72 | } 73 | func TestHeight(t *testing.T) { 74 | bt := sample_bt() 75 | if ret := bt.Height(); ret != 2 { 76 | t.Errorf("bt.Height() = %v", ret) 77 | } 78 | } 79 | func Test_height_subtree(t *testing.T) { 80 | bt := sample_bt() 81 | 82 | r := bt.r 83 | tests := []struct { 84 | arg *node 85 | expected int 86 | }{ 87 | {r, 2}, 88 | {r.left, 1}, 89 | {r.right, 0}, 90 | {r.left.right, 0}, 91 | } 92 | for _, test := range tests { 93 | if ret := height_subtree(test.arg); ret != test.expected { 94 | t.Errorf("height_subtree(%v) = %v", test.arg, ret) 95 | } 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /chained_hash_table/chained_hash_table.go: -------------------------------------------------------------------------------- 1 | package chained_hash_table 2 | 3 | import ( 4 | "github.com/spinute/ods-go/array_stack" 5 | "github.com/spinute/ods-go/utils" 6 | "math/rand" 7 | ) 8 | 9 | type ChainedHashTable struct { 10 | n int 11 | t []array_stack.ArrayStack 12 | z, d uint64 13 | } 14 | 15 | func New() *ChainedHashTable { 16 | return &ChainedHashTable{ 17 | d: 1, 18 | t: make([]array_stack.ArrayStack, 1<<1), 19 | z: rand.Uint64() | uint64(1), 20 | } 21 | } 22 | 23 | func (cht *ChainedHashTable) hash(x utils.V) uint64 { 24 | return (cht.z * uint64(x)) >> (64 - cht.d) 25 | } 26 | 27 | func (cht *ChainedHashTable) Find(x utils.V) *utils.V { 28 | h := cht.hash(x) 29 | for i := 0; i < cht.t[h].Size(); i++ { 30 | if x == cht.t[h].Get(i) { 31 | ret := cht.t[h].Get(i) 32 | return &ret 33 | } 34 | } 35 | return nil 36 | } 37 | func (cht *ChainedHashTable) Add(x utils.V) bool { 38 | if cht.Find(x) != nil { 39 | return false 40 | } 41 | if cht.n+1 > len(cht.t) { 42 | cht.resize() 43 | } 44 | cht.t[cht.hash(x)].Push(x) 45 | cht.n++ 46 | return true 47 | } 48 | 49 | func (cht *ChainedHashTable) Remove(x utils.V) bool { 50 | j := cht.hash(x) 51 | for i := 0; i < cht.t[j].Size(); i++ { 52 | ret := cht.t[j].Get(i) 53 | if x == ret { 54 | cht.t[j].Remove(i) 55 | cht.n-- 56 | return true 57 | } 58 | } 59 | return false 60 | } 61 | 62 | func (cht *ChainedHashTable) resize() { 63 | dNew := uint64(1) 64 | for 1< i; j-- { 42 | p = p.prev 43 | } 44 | } 45 | return p 46 | } 47 | 48 | func (l *DLList) Get(i int) utils.V { 49 | return l.get_node(i).x 50 | } 51 | func (l *DLList) Set(i int, v utils.V) utils.V { 52 | p := l.get_node(i) 53 | ret := p.x 54 | p.x = v 55 | return ret 56 | } 57 | 58 | func (l *DLList) add_before(p *node, x utils.V) { 59 | new_node := nodeNew(x) 60 | new_node.prev = p.prev 61 | new_node.next = p 62 | new_node.prev.next = new_node 63 | new_node.next.prev = new_node 64 | l.n++ 65 | } 66 | 67 | func (l *DLList) add_i(i int, x utils.V) { 68 | l.add_before(l.get_node(i), x) 69 | } 70 | 71 | func (l *DLList) remove_i(i int) utils.V { 72 | p := l.get_node(i) 73 | ret := p.x 74 | p.prev.next = p.next 75 | p.next.prev = p.prev 76 | l.n-- 77 | return ret 78 | } 79 | 80 | func (l *DLList) Push(x utils.V) { 81 | l.add_i(l.n, x) 82 | } 83 | 84 | func (l *DLList) Add(x utils.V) { 85 | l.add_i(l.n, x) 86 | } 87 | 88 | func (l *DLList) Pop() utils.V { 89 | return l.remove_i(l.n - 1) 90 | } 91 | 92 | func (l *DLList) Remove() utils.V { 93 | return l.remove_i(0) 94 | } 95 | -------------------------------------------------------------------------------- /dllist/dllist_test.go: -------------------------------------------------------------------------------- 1 | package dllist 2 | 3 | import ( 4 | "github.com/spinute/ods-go/utils" 5 | "testing" 6 | ) 7 | 8 | func TestNew(t *testing.T) { 9 | if ret := New().n; ret != 0 { 10 | t.Errorf("DLList.New().n = %v", ret) 11 | } 12 | } 13 | 14 | func TestAdd(t *testing.T) { 15 | n := 10 16 | dll := New() 17 | 18 | for i := 0; i < n; i++ { 19 | dll.Add(utils.V(i)) 20 | if dll.n != i+1 { 21 | t.Errorf("dll.n = %v at %v th Add", dll.n, i+1) 22 | } 23 | } 24 | } 25 | 26 | func TestPush(t *testing.T) { 27 | n := 10 28 | dll := New() 29 | 30 | for i := 0; i < n; i++ { 31 | dll.Push(utils.V(i)) 32 | if dll.n != i+1 { 33 | t.Errorf("dll.n = %v at %v th Push", dll.n, i+1) 34 | } 35 | } 36 | } 37 | 38 | func TestPushAndPop(t *testing.T) { 39 | n := 10 40 | dll := New() 41 | for i := 0; i < n; i++ { 42 | dll.Push(utils.V(i)) 43 | } 44 | 45 | for i := 0; i < n; i++ { 46 | if ret := dll.Pop(); ret != utils.V(n-1-i) { 47 | t.Errorf("%v th dll.Pop() = %v", i, ret) 48 | } 49 | } 50 | } 51 | 52 | func TestAddAndRemove(t *testing.T) { 53 | n := 10 54 | dll := New() 55 | for i := 0; i < n; i++ { 56 | dll.Add(utils.V(i)) 57 | } 58 | 59 | for i := 0; i < n; i++ { 60 | if ret := dll.Remove(); ret != utils.V(i) { 61 | t.Errorf("%v th dll.Remove() = %v", i, ret) 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /dual_array_deque/dual_array_deque.go: -------------------------------------------------------------------------------- 1 | package dual_array_deque 2 | 3 | import ( 4 | "github.com/spinute/ods-go/array_stack" 5 | "github.com/spinute/ods-go/utils" 6 | ) 7 | 8 | type DualArrayDeque struct { 9 | n int 10 | front, back array_stack.ArrayStack 11 | } 12 | 13 | func New() DualArrayDeque { 14 | return DualArrayDeque{ 15 | front: array_stack.New(), 16 | back: array_stack.New(), 17 | } 18 | } 19 | 20 | func (dad DualArrayDeque) Get(i int) utils.V { 21 | if front_size := dad.front.Size(); i < front_size { 22 | return dad.front.Get(front_size - i - 1) 23 | } else { 24 | return dad.back.Get(i - front_size) 25 | } 26 | } 27 | 28 | func (dad *DualArrayDeque) Set(i int, v utils.V) utils.V { 29 | if front_size := dad.front.Size(); i < front_size { 30 | return dad.front.Set(front_size-i-1, v) 31 | } else { 32 | return dad.back.Set(i-front_size, v) 33 | } 34 | } 35 | 36 | func (dad *DualArrayDeque) Add(i int, v utils.V) { 37 | if front_size := dad.front.Size(); i < front_size { 38 | dad.front.Add(front_size-i, v) 39 | } else { 40 | dad.back.Add(i-front_size, v) 41 | } 42 | dad.balance() 43 | dad.n++ 44 | } 45 | 46 | func (dad *DualArrayDeque) Remove(i int) utils.V { 47 | var ret utils.V 48 | if front_size := dad.front.Size(); i < front_size { 49 | ret = dad.front.Remove(front_size - i - 1) 50 | } else { 51 | ret = dad.back.Remove(i - front_size) 52 | } 53 | dad.balance() 54 | dad.n-- 55 | return ret 56 | } 57 | 58 | func (dad *DualArrayDeque) balance() { 59 | front_size := dad.front.Size() 60 | back_size := dad.back.Size() 61 | 62 | if 3*front_size < back_size || 3*back_size < front_size { 63 | n := front_size + back_size 64 | 65 | front_size_new := n / 2 66 | front_new := array_stack.New() 67 | for i := front_size_new - 1; i >= 0; i-- { 68 | front_new.Push(dad.Get(i)) 69 | } 70 | 71 | back_size_new := n - front_size_new 72 | back_new := array_stack.New() 73 | for i := 0; i < back_size_new; i++ { 74 | back_new.Push(dad.Get(front_size_new + i)) 75 | } 76 | 77 | dad.front = front_new 78 | dad.back = back_new 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /dual_array_deque/dual_array_deque_test.go: -------------------------------------------------------------------------------- 1 | package dual_array_deque 2 | 3 | import ( 4 | "github.com/spinute/ods-go/utils" 5 | "testing" 6 | ) 7 | 8 | func TestNew(t *testing.T) { 9 | if ret := New().n; ret != 0 { 10 | t.Errorf("DualArrayDeque.New().n = %v", ret) 11 | } 12 | } 13 | 14 | func TestAddHead(t *testing.T) { 15 | n := 10 16 | dad := New() 17 | 18 | for i := 0; i < n; i++ { 19 | dad.Add(0, utils.V(i)) 20 | if dad.n != i+1 { 21 | t.Errorf("dad.n = %v at %v th Add", dad.n, i+1) 22 | } 23 | } 24 | } 25 | 26 | func TestAddMid(t *testing.T) { 27 | n := 10 28 | dad := New() 29 | for i := 0; i < n; i++ { 30 | dad.Add(0, utils.V(i)) 31 | } 32 | 33 | for i := 0; i < n; i++ { 34 | mid := n / 2 35 | dad.Add(mid, utils.V(i)) 36 | if dad.n != n+i+1 { 37 | t.Errorf("dad.n = %v at %v th Add", dad.n, n+i+1) 38 | } 39 | } 40 | } 41 | 42 | func TestAddLast(t *testing.T) { 43 | n := 10 44 | dad := New() 45 | 46 | for i := 0; i < n; i++ { 47 | dad.Add(i, utils.V(i)) 48 | if dad.n != i+1 { 49 | t.Errorf("dad.n = %v at %v th Add", dad.n, i+1) 50 | } 51 | } 52 | } 53 | 54 | func TestGet(t *testing.T) { 55 | n := 10 56 | dad := New() 57 | for i := 0; i < n; i++ { 58 | dad.Add(i, utils.V(i)) 59 | } 60 | 61 | for i := 0; i < n; i++ { 62 | if ret := dad.Get(i); ret != utils.V(i) { 63 | t.Errorf("dad.Get(%v) = %v", i, ret) 64 | } 65 | } 66 | } 67 | 68 | func TestSet(t *testing.T) { 69 | n := 10 70 | dad := New() 71 | for i := 0; i < n; i++ { 72 | dad.Add(0, utils.V(i)) 73 | } 74 | 75 | ofs := 1000 76 | for i := 0; i < n; i++ { 77 | if ret := dad.Set(i, utils.V(ofs+i)); ret != utils.V(n-i-1) { 78 | t.Errorf("dad.Set(%v) = %v", i, ret) 79 | } 80 | } 81 | for i := 0; i < n; i++ { 82 | if ret := dad.Get(i); ret != utils.V(ofs+i) { 83 | t.Errorf("dad.Get(%v) = %v", i, ret) 84 | } 85 | } 86 | } 87 | 88 | func TestRemove(t *testing.T) { 89 | n := 10 90 | dad := New() 91 | for i := 0; i < n; i++ { 92 | dad.Add(0, utils.V(i)) 93 | } 94 | 95 | mid := n / 2 96 | for i := mid; i < n; i++ { 97 | if ret := dad.Remove(mid); ret != utils.V(n-i-1) { 98 | t.Errorf("%v th dad.Remove(mid) = %v", i-mid+1, ret) 99 | } 100 | } 101 | for i := 0; i < mid; i++ { 102 | if ret := dad.Remove(0); ret != utils.V(n-i-1) { 103 | t.Errorf("dad.Remove(head) = %v", ret) 104 | } 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /fast_array_stack/fast_array_stack.go: -------------------------------------------------------------------------------- 1 | package fast_array_stack 2 | 3 | import "github.com/spinute/ods-go/utils" 4 | 5 | type FastArrayStack struct { 6 | n, cap int 7 | buf []utils.V 8 | } 9 | 10 | func New() FastArrayStack { 11 | return FastArrayStack{} 12 | } 13 | 14 | func (fas *FastArrayStack) Push(v utils.V) { 15 | fas.Add(fas.n, v) 16 | } 17 | 18 | func (fas *FastArrayStack) Pop() utils.V { 19 | return fas.Remove(fas.n - 1) 20 | } 21 | 22 | func (fas FastArrayStack) Get(i int) utils.V { 23 | return fas.buf[i] 24 | } 25 | 26 | func (fas *FastArrayStack) Set(i int, v utils.V) utils.V { 27 | ret := fas.buf[i] 28 | fas.buf[i] = v 29 | return ret 30 | } 31 | 32 | func (fas *FastArrayStack) Add(i int, v utils.V) { 33 | if fas.is_full() { 34 | fas.resize() 35 | } 36 | copy(fas.buf[i+1:fas.n+1], fas.buf[i:fas.n]) 37 | fas.buf[i] = v 38 | fas.n++ 39 | } 40 | 41 | func (fas *FastArrayStack) Remove(i int) utils.V { 42 | ret := fas.buf[i] 43 | copy(fas.buf[i:fas.n-1], fas.buf[i+1:fas.n]) 44 | fas.n-- 45 | if fas.is_sparse() { 46 | fas.resize() 47 | } 48 | return ret 49 | } 50 | 51 | func (fas FastArrayStack) is_full() bool { 52 | return fas.n == fas.cap 53 | } 54 | 55 | func (fas FastArrayStack) is_sparse() bool { 56 | return len(fas.buf) >= 3*fas.n 57 | } 58 | 59 | func (fas *FastArrayStack) resize() { 60 | fas.cap = utils.Max(2*fas.n, 1) 61 | buf_new := make([]utils.V, fas.cap) 62 | copy(buf_new, fas.buf) 63 | fas.buf = buf_new 64 | } 65 | -------------------------------------------------------------------------------- /fast_array_stack/fast_array_stack_test.go: -------------------------------------------------------------------------------- 1 | package fast_array_stack 2 | 3 | import ( 4 | "github.com/spinute/ods-go/utils" 5 | "testing" 6 | ) 7 | 8 | func TestNew(t *testing.T) { 9 | if ret := New().n; ret != 0 { 10 | t.Errorf("FastArrayStack.New().n = %v", ret) 11 | } 12 | } 13 | 14 | func TestPush(t *testing.T) { 15 | tests := []utils.V{1, 2, 1, -1, -2, -100, 0, 0} 16 | fas := New() 17 | 18 | for i, v := range tests { 19 | fas.Push(v) 20 | if fas.n != i+1 { 21 | t.Errorf("fas.n = %v at %v th push", fas.n, i+1) 22 | } 23 | } 24 | } 25 | 26 | func TestPushMany(t *testing.T) { 27 | tests := make([]utils.V, 12345) 28 | fas := New() 29 | 30 | for i, v := range tests { 31 | fas.Push(v) 32 | if fas.n != i+1 { 33 | t.Errorf("fas.n = %v at %v th push", fas.n, i+1) 34 | } 35 | } 36 | } 37 | 38 | func TestPushAndPop(t *testing.T) { 39 | tests := []utils.V{1, 2, 1, -1, -2, -100, 0, 0} 40 | fas := New() 41 | 42 | for _, v := range tests { 43 | fas.Push(v) 44 | if ret := fas.Pop(); ret != v { 45 | t.Errorf("pushed %v, then %v was poped", v, ret) 46 | } 47 | } 48 | } 49 | 50 | func TestPushAndPop2(t *testing.T) { 51 | n := 123 52 | fas := New() 53 | 54 | for i := 0; i < n; i++ { 55 | fas.Push(utils.V(i + 1)) 56 | } 57 | 58 | for i := 0; i < n; i++ { 59 | if ret, want := fas.Pop(), utils.V(n-i); ret != want { 60 | t.Errorf("expect %d but returned %d", ret, want) 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /linear_hash_table/linear_hash_table.go: -------------------------------------------------------------------------------- 1 | package linear_hash_table 2 | 3 | import ( 4 | "math/rand" 5 | 6 | "github.com/spinute/ods-go/utils" 7 | ) 8 | 9 | type LinearHashTable struct { 10 | n, q int 11 | t []*utils.V 12 | d, z uint64 13 | del *utils.V 14 | } 15 | 16 | func New() *LinearHashTable { 17 | return &LinearHashTable{ 18 | d: 1, 19 | t: make([]*utils.V, 1<<1), 20 | z: rand.Uint64() | uint64(1), 21 | del: new(utils.V), 22 | } 23 | } 24 | 25 | func (lht *LinearHashTable) hash(x utils.V) uint64 { 26 | return (lht.z * uint64(x)) >> (64 - lht.d) 27 | } 28 | 29 | func (lht *LinearHashTable) next_ind(i uint64) uint64 { 30 | return (i + 1) % uint64(len(lht.t)) 31 | } 32 | 33 | func (lht *LinearHashTable) Find(x utils.V) *utils.V { 34 | h := lht.hash(x) 35 | for i := h; lht.t[i] != nil; i = lht.next_ind(i) { 36 | if lht.t[i] != lht.del && *lht.t[i] == x { 37 | return lht.t[i] 38 | } 39 | } 40 | return nil 41 | } 42 | func (lht *LinearHashTable) Add(x utils.V) bool { 43 | if lht.Find(x) != nil { 44 | return false 45 | } 46 | 47 | if 2*(lht.q+1) > len(lht.t) { 48 | lht.resize() 49 | } 50 | i := lht.hash(x) 51 | for lht.t[i] != nil && lht.t[i] != lht.del { 52 | i = lht.next_ind(i) 53 | } 54 | if lht.t[i] == nil { 55 | lht.q++ 56 | } 57 | lht.n++ 58 | lht.t[i] = &x 59 | return true 60 | } 61 | 62 | func (lht *LinearHashTable) Remove(x utils.V) bool { 63 | i := lht.hash(x) 64 | for lht.t[i] != nil { 65 | y := lht.t[i] 66 | if y != lht.del && x == *y { 67 | lht.t[i] = lht.del 68 | lht.n-- 69 | if 8*lht.n < len(lht.t) { 70 | lht.resize() 71 | } 72 | return true 73 | } 74 | i = lht.next_ind(i) 75 | } 76 | return false 77 | } 78 | 79 | func (lht *LinearHashTable) resize() { 80 | dNew := uint64(1) 81 | for 1< 0 { 31 | return mh.merge(h2, h1) 32 | } 33 | if rand.Int()%2 == 0 { 34 | h1.left = mh.merge(h1.left, h2) 35 | if h1.left != nil { 36 | h1.left.parent = h1 37 | } 38 | } else { 39 | h1.right = mh.merge(h1.right, h2) 40 | if h1.right != nil { 41 | h1.right.parent = h1 42 | } 43 | } 44 | return h1 45 | } 46 | 47 | func (mh *MeldableHeap) Add(x utils.V) bool { 48 | u := &node{x: x} 49 | mh.r = mh.merge(u, mh.r) 50 | mh.r.parent = nil 51 | mh.n++ 52 | return true 53 | } 54 | 55 | func (mh *MeldableHeap) Remove() utils.V { 56 | x := mh.r.x 57 | mh.r = mh.merge(mh.r.left, mh.r.right) 58 | if mh.r != nil { 59 | mh.r.parent = nil 60 | } 61 | mh.n-- 62 | return x 63 | } 64 | -------------------------------------------------------------------------------- /meldable_heap/meldable_heap_test.go: -------------------------------------------------------------------------------- 1 | package meldable_heap 2 | 3 | import ( 4 | "github.com/spinute/ods-go/utils" 5 | "testing" 6 | ) 7 | 8 | func TestNew(t *testing.T) { 9 | if ret := New().n; ret != 0 { 10 | t.Errorf("MeldableHeap.New().n = %v", ret) 11 | } 12 | } 13 | 14 | func TestAdd(t *testing.T) { 15 | tests := []utils.V{1, 2, 1, -1, -2, -100, 0, 0} 16 | mh := New() 17 | 18 | for i, v := range tests { 19 | mh.Add(v) 20 | if mh.n != i+1 { 21 | t.Errorf("mh.n = %v at %v th Add", mh.n, i+1) 22 | } 23 | } 24 | } 25 | 26 | func TestAddMany(t *testing.T) { 27 | tests := make([]utils.V, 12345) 28 | mh := New() 29 | 30 | for i, v := range tests { 31 | mh.Add(v) 32 | if mh.n != i+1 { 33 | t.Errorf("mh.n = %v at %v th Add", mh.n, i+1) 34 | } 35 | } 36 | } 37 | 38 | func TestAddAndRemove(t *testing.T) { 39 | tests := []utils.V{1, 2, 1, -1, -2, -100, 0, 0} 40 | mh := New() 41 | 42 | for _, v := range tests { 43 | mh.Add(v) 44 | if ret := mh.Remove(); ret != v { 45 | t.Errorf("Add %v, then %v was removed", v, ret) 46 | } 47 | } 48 | } 49 | 50 | func TestAddAndRemove2(t *testing.T) { 51 | n := 123 52 | mh := New() 53 | 54 | for i := 0; i < n; i++ { 55 | mh.Add(utils.V(i)) 56 | } 57 | 58 | for i := 0; i < n; i++ { 59 | if ret, want := mh.Remove(), utils.V(i); ret != want { 60 | t.Errorf("expect %d but returned %d", ret, want) 61 | } 62 | } 63 | } 64 | 65 | func TestAddAndRemove3(t *testing.T) { 66 | n := 123 67 | mh := New() 68 | 69 | for i := 0; i < n; i++ { 70 | mh.Add(utils.V(n - i - 1)) 71 | } 72 | 73 | for i := 0; i < n; i++ { 74 | if ret, want := mh.Remove(), utils.V(i); ret != want { 75 | t.Errorf("expect %d but returned %d", ret, want) 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /rootish_array_stack/rootish_array_stack.go: -------------------------------------------------------------------------------- 1 | package rootish_array_stack 2 | 3 | import ( 4 | "github.com/spinute/ods-go/utils" 5 | "math" 6 | ) 7 | 8 | type RootishArrayStack struct { 9 | n int 10 | blocks [][]utils.V 11 | } 12 | 13 | func New() RootishArrayStack { 14 | return RootishArrayStack{} 15 | } 16 | 17 | func i2b(i int) int { 18 | db := (-3.0 + math.Sqrt(float64(9+8*i))) / 2.0 19 | return int(math.Ceil(db)) 20 | } 21 | 22 | func (ras RootishArrayStack) Get(i int) utils.V { 23 | b := i2b(i) 24 | j := i - b*(b+1)/2 25 | return ras.blocks[b][j] 26 | } 27 | 28 | func (ras *RootishArrayStack) Set(i int, v utils.V) utils.V { 29 | b := i2b(i) 30 | j := i - b*(b+1)/2 31 | ret := ras.blocks[b][j] 32 | ras.blocks[b][j] = v 33 | return ret 34 | } 35 | 36 | func (ras RootishArrayStack) is_full() bool { 37 | n_b := len(ras.blocks) 38 | return n_b*(n_b+1)/2 == ras.n 39 | } 40 | func (ras *RootishArrayStack) grow() { 41 | ras.blocks = append(ras.blocks, make([]utils.V, len(ras.blocks)+1)) 42 | } 43 | 44 | func (ras *RootishArrayStack) Add(i int, v utils.V) { 45 | if ras.is_full() { 46 | ras.grow() 47 | } 48 | for j := ras.n; j > i; j-- { 49 | ras.Set(j, ras.Get(j-1)) 50 | } 51 | ras.Set(i, v) 52 | ras.n++ 53 | } 54 | 55 | func (ras RootishArrayStack) is_sparse() bool { 56 | n_b := len(ras.blocks) 57 | return n_b > 0 && (n_b-2)*(n_b-1)/2 >= ras.n 58 | } 59 | func (ras *RootishArrayStack) shrink() { 60 | // go slice will not shrink ?? 61 | } 62 | 63 | func (ras *RootishArrayStack) Remove(i int) utils.V { 64 | ret := ras.Get(i) 65 | for j := i; j < ras.n-1; j++ { 66 | ras.Set(j, ras.Get(j+1)) 67 | } 68 | ras.n-- 69 | n_b := len(ras.blocks) 70 | if (n_b-2)*(n_b-1)/2 >= ras.n { 71 | ras.shrink() 72 | } 73 | return ret 74 | } 75 | -------------------------------------------------------------------------------- /rootish_array_stack/rootish_array_stack_test.go: -------------------------------------------------------------------------------- 1 | package rootish_array_stack 2 | 3 | import ( 4 | "github.com/spinute/ods-go/utils" 5 | "testing" 6 | ) 7 | 8 | func TestNew(t *testing.T) { 9 | if ret := New().n; ret != 0 { 10 | t.Errorf("RootishArrayStack.New().n = %v", ret) 11 | } 12 | } 13 | 14 | func TestAddHead(t *testing.T) { 15 | n := 10 16 | ras := New() 17 | 18 | for i := 0; i < n; i++ { 19 | ras.Add(0, utils.V(i)) 20 | if ras.n != i+1 { 21 | t.Errorf("ras.n = %v at %v th Add", ras.n, i+1) 22 | } 23 | } 24 | } 25 | 26 | func TestAddMid(t *testing.T) { 27 | n := 10 28 | ras := New() 29 | for i := 0; i < n; i++ { 30 | ras.Add(0, utils.V(i)) 31 | } 32 | 33 | for i := 0; i < n; i++ { 34 | mid := n / 2 35 | ras.Add(mid, utils.V(i)) 36 | if ras.n != n+i+1 { 37 | t.Errorf("ras.n = %v at %v th Add", ras.n, n+i+1) 38 | } 39 | } 40 | } 41 | 42 | func TestAddLast(t *testing.T) { 43 | n := 10 44 | ras := New() 45 | 46 | for i := 0; i < n; i++ { 47 | ras.Add(i, utils.V(i)) 48 | if ras.n != i+1 { 49 | t.Errorf("ras.n = %v at %v th Add", ras.n, i+1) 50 | } 51 | } 52 | } 53 | 54 | func TestGet(t *testing.T) { 55 | n := 10 56 | ras := New() 57 | for i := 0; i < n; i++ { 58 | ras.Add(i, utils.V(i)) 59 | } 60 | 61 | for i := 0; i < n; i++ { 62 | if ret := ras.Get(i); ret != utils.V(i) { 63 | t.Errorf("ras.Get(%v) = %v", i, ret) 64 | } 65 | } 66 | } 67 | 68 | func TestSet(t *testing.T) { 69 | n := 10 70 | ras := New() 71 | for i := 0; i < n; i++ { 72 | ras.Add(0, utils.V(i)) 73 | } 74 | 75 | ofs := 1000 76 | for i := 0; i < n; i++ { 77 | if ret := ras.Set(i, utils.V(ofs+i)); ret != utils.V(n-i-1) { 78 | t.Errorf("ras.Set(%v) = %v", i, ret) 79 | } 80 | } 81 | for i := 0; i < n; i++ { 82 | if ret := ras.Get(i); ret != utils.V(ofs+i) { 83 | t.Errorf("ras.Get(%v) = %v", i, ret) 84 | } 85 | } 86 | } 87 | 88 | func TestRemove(t *testing.T) { 89 | n := 10 90 | ras := New() 91 | for i := 0; i < n; i++ { 92 | ras.Add(0, utils.V(i)) 93 | } 94 | 95 | mid := n / 2 96 | for i := mid; i < n; i++ { 97 | if ret := ras.Remove(mid); ret != utils.V(n-i-1) { 98 | t.Errorf("%v th ras.Remove(mid) = %v", i-mid+1, ret) 99 | } 100 | } 101 | for i := 0; i < mid; i++ { 102 | if ret := ras.Remove(0); ret != utils.V(n-i-1) { 103 | t.Errorf("ras.Remove(head) = %v", ret) 104 | } 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /scapegoat_tree/scapegoat_tree.go: -------------------------------------------------------------------------------- 1 | package scapegoat_tree 2 | 3 | import ( 4 | "math" 5 | 6 | "github.com/spinute/ods-go/utils" 7 | ) 8 | 9 | type node struct { 10 | left, right, parent *node 11 | x utils.V 12 | } 13 | 14 | type ScapegoatTree struct { 15 | r *node 16 | n, q int 17 | } 18 | 19 | func New() *ScapegoatTree { 20 | return &ScapegoatTree{} 21 | } 22 | 23 | func (st *ScapegoatTree) FindEQ(x utils.V) bool { 24 | w := st.r 25 | for w != nil { 26 | comp := utils.Compare(x, w.x) 27 | if comp < 0 { 28 | w = w.left 29 | } else if comp > 0 { 30 | w = w.right 31 | } else { 32 | return true 33 | } 34 | } 35 | return false 36 | } 37 | 38 | func (st *ScapegoatTree) Find(x utils.V) *utils.V { 39 | w := st.r 40 | var ret *node = nil 41 | for w != nil { 42 | comp := utils.Compare(x, w.x) 43 | if comp < 0 { 44 | ret = w 45 | w = w.left 46 | } else if comp > 0 { 47 | w = w.right 48 | } else { 49 | return &w.x 50 | } 51 | } 52 | if ret == nil { 53 | return nil 54 | } 55 | return &ret.x 56 | } 57 | 58 | func size_subtree(n *node) int { 59 | if n == nil { 60 | return 0 61 | } 62 | return size_subtree(n.left) + size_subtree(n.right) + 1 63 | } 64 | func (st *ScapegoatTree) rebuild(u *node) { 65 | sz := size_subtree(u) 66 | p := u.parent 67 | a := make([]*node, sz) 68 | packIntoArray(u, a, 0) 69 | if p == nil { 70 | st.r = st.buildBalanced(a, 0, sz) 71 | st.r.parent = nil 72 | } else if p.right == u { 73 | p.right = st.buildBalanced(a, 0, sz) 74 | p.right.parent = p 75 | } else { 76 | p.left = st.buildBalanced(a, 0, sz) 77 | p.left.parent = p 78 | } 79 | } 80 | func packIntoArray(u *node, a []*node, i int) int { 81 | if u == nil { 82 | return i 83 | } 84 | i = packIntoArray(u.left, a, i) 85 | a[i] = u 86 | i++ 87 | return packIntoArray(u.right, a, i) 88 | } 89 | func (st *ScapegoatTree) buildBalanced(a []*node, i, ns int) *node { 90 | if ns == 0 { 91 | return nil 92 | } 93 | m := ns / 2 94 | a[i+m].left = st.buildBalanced(a, i, m) 95 | if a[i+m].left != nil { 96 | a[i+m].left.parent = a[i+m] 97 | } 98 | a[i+m].right = st.buildBalanced(a, i+m+1, ns-m-1) 99 | if a[i+m].right != nil { 100 | a[i+m].right.parent = a[i+m] 101 | } 102 | return a[i+m] 103 | } 104 | 105 | func log32(n int) int { 106 | return int(math.Log(float64(n)) / math.Log(3.0/2)) 107 | } 108 | func (st *ScapegoatTree) Add(x utils.V) bool { 109 | u := &node{x: x} 110 | d := st.addWithDepth(u) 111 | if d > log32(st.q) { 112 | w := u.parent 113 | a := size_subtree(w) 114 | b := size_subtree(w.parent) 115 | for 3*a <= 2*b { 116 | w = w.parent 117 | a = size_subtree(w) 118 | b = size_subtree(w.parent) 119 | } 120 | st.rebuild(w.parent) 121 | } else if d < 0 { 122 | return false 123 | } 124 | return true 125 | } 126 | func (st *ScapegoatTree) addWithDepth(u *node) int { 127 | w := st.r 128 | if w == nil { 129 | st.r = u 130 | st.n++ 131 | st.q++ 132 | return 0 133 | } 134 | done := false 135 | d := 0 136 | for !done { 137 | res := utils.Compare(u.x, w.x) 138 | if res < 0 { 139 | if w.left == nil { 140 | w.left = u 141 | u.parent = w 142 | done = true 143 | } else { 144 | w = w.left 145 | } 146 | } else if res > 0 { 147 | if w.right == nil { 148 | w.right = u 149 | u.parent = w 150 | done = true 151 | } 152 | w = w.right 153 | } else { 154 | return -1 155 | } 156 | d++ 157 | } 158 | st.n++ 159 | st.q++ 160 | return d 161 | } 162 | 163 | func (st *ScapegoatTree) findLast(x utils.V) *node { 164 | w := st.r 165 | last := w 166 | for w != nil { 167 | comp := utils.Compare(x, w.x) 168 | last = w 169 | if comp < 0 { 170 | w = w.left 171 | } else if comp > 0 { 172 | w = w.right 173 | } else { 174 | return w 175 | } 176 | } 177 | return last 178 | } 179 | func addChild(p, c *node) bool { 180 | comp := utils.Compare(c.x, p.x) 181 | if comp < 0 { 182 | p.left = c 183 | } else if comp > 0 { 184 | p.right = c 185 | } else { 186 | return false 187 | } 188 | c.parent = p 189 | return true 190 | } 191 | 192 | func (st *ScapegoatTree) Remove(x utils.V) bool { 193 | if st.remove_value(x) { 194 | if 2*st.n < st.q { 195 | if st.r != nil { 196 | st.rebuild(st.r) 197 | } 198 | st.q = st.n 199 | } 200 | return true 201 | } 202 | return false 203 | } 204 | func (st *ScapegoatTree) remove_value(x utils.V) bool { 205 | node := st.findLast(x) 206 | if node != nil && utils.Compare(x, node.x) == 0 { 207 | st.removeNode(node) 208 | return true 209 | } 210 | return false 211 | } 212 | func (st *ScapegoatTree) removeNode(node *node) { 213 | if node.left == nil || node.right == nil { 214 | st.splice(node) 215 | } else { 216 | minInRight := node.right 217 | for minInRight.left != nil { 218 | minInRight = minInRight.left 219 | } 220 | node.x = minInRight.x 221 | st.splice(minInRight) 222 | } 223 | st.n-- 224 | } 225 | func (st *ScapegoatTree) splice(n *node) { 226 | var c, p *node 227 | if n.left != nil { 228 | c = n.left 229 | } else { 230 | c = n.right 231 | } 232 | 233 | if st.r == n { 234 | st.r = c 235 | p = nil 236 | } else { 237 | p = n.parent 238 | if n == p.left { 239 | p.left = c 240 | } else { 241 | p.right = c 242 | } 243 | } 244 | 245 | if c != nil { 246 | c.parent = p 247 | } 248 | } 249 | -------------------------------------------------------------------------------- /scapegoat_tree/scapegoat_tree_test.go: -------------------------------------------------------------------------------- 1 | package scapegoat_tree 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/spinute/ods-go/utils" 7 | ) 8 | 9 | func TestNew(t *testing.T) { 10 | if ret := New().n; ret != 0 { 11 | t.Errorf("ScapegoatTree.New().n = %v", ret) 12 | } 13 | } 14 | 15 | func TestAdd(t *testing.T) { 16 | n := 10 17 | st := New() 18 | 19 | for i := 0; i < n; i++ { 20 | ret := st.Add(utils.V(i)) 21 | if st.n != i+1 { 22 | t.Errorf("st.n = %v at %v th Add", st.n, i+1) 23 | } 24 | if ret == false { 25 | t.Errorf("Add returned false unexpectedly") 26 | } 27 | } 28 | 29 | for i := 0; i < n; i++ { 30 | ret := st.Add(utils.V(i)) 31 | if st.n != n { 32 | t.Errorf("st.n = %v", st.n) 33 | } 34 | if ret == true { 35 | t.Errorf("Add returned true unexpectedly") 36 | } 37 | } 38 | } 39 | 40 | func TestFindEQ(t *testing.T) { 41 | n := 10 42 | st := New() 43 | 44 | for i := 0; i < n; i++ { 45 | ret := st.FindEQ(utils.V(i)) 46 | if ret == true { 47 | t.Errorf("Add returned non-nil unexpectedly, ret=%v", ret) 48 | } 49 | } 50 | 51 | for i := 0; i < n; i++ { 52 | st.Add(utils.V(i)) 53 | ret := st.FindEQ(utils.V(i)) 54 | if ret == false { 55 | t.Errorf("Add returned nil unexpectedly") 56 | } 57 | } 58 | 59 | ret := st.FindEQ(utils.V(n + 123)) 60 | if ret == true { 61 | t.Errorf("Add returned nil unexpectedly") 62 | } 63 | } 64 | 65 | func TestFind(t *testing.T) { 66 | n := 10 67 | st := New() 68 | 69 | for i := 0; i < n; i++ { 70 | ret := st.Find(utils.V(i)) 71 | if ret != nil { 72 | t.Errorf("non-nil unexpectedly, ret=%d", ret) 73 | } 74 | } 75 | 76 | for i := 0; i < n; i++ { 77 | st.Add(utils.V(i)) 78 | ret := st.Find(utils.V(i)) 79 | if ret == nil { 80 | t.Errorf("Find returned nil unexpectedly") 81 | } 82 | } 83 | 84 | ret := st.Find(utils.V(n - 123)) 85 | if *ret != utils.V(0) { 86 | t.Errorf("unexpectedly returned %v", *ret) 87 | } 88 | } 89 | 90 | func TestRemove(t *testing.T) { 91 | x := utils.V(-12345) 92 | st := New() 93 | 94 | if st.Remove(x) == true { 95 | t.Errorf("Add returned true unexpectedly") 96 | } 97 | 98 | st.Add(x) 99 | if st.Remove(x) == false { 100 | t.Errorf("Add returned false unexpectedly") 101 | } 102 | 103 | if st.Find(x) != nil { 104 | t.Errorf("Add returned non-nil unexpectedly") 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /skiplistlist/skiplistlist.go: -------------------------------------------------------------------------------- 1 | package skiplistlist 2 | 3 | import ( 4 | "math/rand" 5 | "strconv" 6 | 7 | "github.com/spinute/ods-go/utils" 8 | ) 9 | 10 | type node struct { 11 | x utils.V 12 | height int 13 | lengths []int 14 | nexts []*node 15 | } 16 | 17 | func pickHeight() int { 18 | r := rand.Int() 19 | h := 0 20 | for r&1 != 0 { 21 | h++ 22 | r >>= 1 23 | } 24 | return h 25 | } 26 | 27 | func nodeNew(x utils.V, h int) *node { 28 | return &node{ 29 | height: h, 30 | x: x, 31 | lengths: make([]int, h+1), 32 | nexts: make([]*node, h+1), 33 | } 34 | } 35 | 36 | type SkiplistList struct { 37 | sentinel *node 38 | n, height int 39 | stack [strconv.IntSize]*node 40 | } 41 | 42 | func New() *SkiplistList { 43 | ss := SkiplistList{ 44 | sentinel: nodeNew(utils.V(0), strconv.IntSize), 45 | } 46 | ss.stack[0] = ss.sentinel 47 | return &ss 48 | } 49 | 50 | func (ss *SkiplistList) findPred(i int) *node { 51 | u := ss.sentinel 52 | r := ss.height 53 | j := -1 54 | for r >= 0 { 55 | for u.nexts[r] != nil && j+u.lengths[r] < i { 56 | j += u.lengths[r] 57 | u = u.nexts[r] 58 | } 59 | r-- 60 | } 61 | return u 62 | } 63 | 64 | func (ss *SkiplistList) Get(i int) utils.V { 65 | return ss.findPred(i).nexts[0].x 66 | } 67 | 68 | func (ss *SkiplistList) Set(i int, x utils.V) utils.V { 69 | u := ss.findPred(i).nexts[0] 70 | y := u.x 71 | u.x = x 72 | return y 73 | } 74 | 75 | func (ss *SkiplistList) Add(i int, x utils.V) { 76 | w := nodeNew(x, pickHeight()) 77 | if w.height > ss.height { 78 | ss.height = w.height 79 | } 80 | ss.addNode(i, w) 81 | } 82 | 83 | func (ss *SkiplistList) addNode(i int, w *node) *node { 84 | u := ss.sentinel 85 | k := w.height 86 | r := ss.height 87 | j := -1 88 | for r >= 0 { 89 | for u.nexts[r] != nil && j+u.lengths[r] < i { 90 | j += u.lengths[r] 91 | u = u.nexts[r] 92 | } 93 | u.lengths[r]++ 94 | if r <= k { 95 | w.nexts[r] = u.nexts[r] 96 | u.nexts[r] = w 97 | w.lengths[r] = u.lengths[r] - (i - j) 98 | u.lengths[r] = i - j 99 | } 100 | r-- 101 | } 102 | ss.n++ 103 | return u 104 | } 105 | 106 | func (ss *SkiplistList) Remove(i int) utils.V { 107 | // FIXME: return error when i th value does not exist 108 | ret := utils.V(-12345) 109 | orig := ret 110 | 111 | u := ss.sentinel 112 | r := ss.height 113 | j := -1 114 | for r >= 0 { 115 | for u.nexts[r] != nil && j+u.lengths[r] < i { 116 | j += u.lengths[r] 117 | u = u.nexts[r] 118 | } 119 | u.lengths[r]-- 120 | if j+u.lengths[r]+1 == i && u.nexts[r] != nil { 121 | ret = u.nexts[r].x 122 | u.lengths[r] += u.nexts[r].lengths[r] 123 | u.nexts[r] = u.nexts[r].nexts[r] 124 | if u == ss.sentinel && u.nexts[r] == nil { 125 | ss.height-- 126 | } 127 | } 128 | r-- 129 | } 130 | 131 | // FIXME: return error when i th value does not exist 132 | if ret != orig { 133 | ss.n-- 134 | } 135 | 136 | return ret 137 | } 138 | -------------------------------------------------------------------------------- /skiplistlist/skiplistlist_test.go: -------------------------------------------------------------------------------- 1 | package skiplistlist 2 | 3 | import ( 4 | "github.com/spinute/ods-go/utils" 5 | "testing" 6 | ) 7 | 8 | func TestNew(t *testing.T) { 9 | if ret := New().n; ret != 0 { 10 | t.Errorf("SkiplistList.New().n = %v", ret) 11 | } 12 | } 13 | 14 | func TestAddHead(t *testing.T) { 15 | n := 10 16 | sll := New() 17 | 18 | for i := 0; i < n; i++ { 19 | sll.Add(0, utils.V(i)) 20 | if sll.n != i+1 { 21 | t.Errorf("sll.n = %v at %v th Add", sll.n, i+1) 22 | } 23 | } 24 | } 25 | 26 | func TestAddMid(t *testing.T) { 27 | n := 10 28 | sll := New() 29 | for i := 0; i < n; i++ { 30 | sll.Add(0, utils.V(i)) 31 | } 32 | 33 | for i := 0; i < n; i++ { 34 | mid := n / 2 35 | sll.Add(mid, utils.V(i)) 36 | if sll.n != n+i+1 { 37 | t.Errorf("sll.n = %v at %v th Add", sll.n, n+i+1) 38 | } 39 | } 40 | } 41 | 42 | func TestAddLast(t *testing.T) { 43 | n := 10 44 | sll := New() 45 | 46 | for i := 0; i < n; i++ { 47 | sll.Add(i, utils.V(i)) 48 | if sll.n != i+1 { 49 | t.Errorf("sll.n = %v at %v th Add", sll.n, i+1) 50 | } 51 | } 52 | } 53 | 54 | func TestGet(t *testing.T) { 55 | n := 10 56 | sll := New() 57 | for i := 0; i < n; i++ { 58 | sll.Add(i, utils.V(i)) 59 | } 60 | 61 | for i := 0; i < n; i++ { 62 | if ret := sll.Get(i); ret != utils.V(i) { 63 | t.Errorf("sll.Get(%v) = %v", i, ret) 64 | } 65 | } 66 | } 67 | 68 | func TestSet(t *testing.T) { 69 | n := 10 70 | sll := New() 71 | for i := 0; i < n; i++ { 72 | sll.Add(0, utils.V(i)) 73 | } 74 | 75 | ofs := 1000 76 | for i := 0; i < n; i++ { 77 | if ret := sll.Set(i, utils.V(ofs+i)); ret != utils.V(n-i-1) { 78 | t.Errorf("sll.Set(%v) = %v", i, ret) 79 | } 80 | } 81 | for i := 0; i < n; i++ { 82 | if ret := sll.Get(i); ret != utils.V(ofs+i) { 83 | t.Errorf("sll.Get(%v) = %v", i, ret) 84 | } 85 | } 86 | } 87 | 88 | func TestRemove(t *testing.T) { 89 | n := 10 90 | sll := New() 91 | for i := 0; i < n; i++ { 92 | sll.Add(0, utils.V(i)) 93 | } 94 | 95 | mid := n / 2 96 | for i := mid; i < n; i++ { 97 | if ret := sll.Remove(mid); ret != utils.V(n-i-1) { 98 | t.Errorf("%v th sll.Remove(mid) = %v", i-mid+1, ret) 99 | } 100 | } 101 | for i := 0; i < mid; i++ { 102 | if ret := sll.Remove(0); ret != utils.V(n-i-1) { 103 | t.Errorf("sll.Remove(head) = %v", ret) 104 | } 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /skiplistsset/skiplistsset.go: -------------------------------------------------------------------------------- 1 | package skiplistsset 2 | 3 | import ( 4 | "math/rand" 5 | "strconv" 6 | 7 | "github.com/spinute/ods-go/utils" 8 | ) 9 | 10 | type node struct { 11 | x utils.V 12 | height int 13 | nexts []*node 14 | } 15 | 16 | func pickHeight() int { 17 | r := rand.Int() 18 | h := 0 19 | for r&1 != 0 { 20 | h++ 21 | r >>= 1 22 | } 23 | return h 24 | } 25 | 26 | func nodeNew(x utils.V, h int) *node { 27 | return &node{ 28 | height: h, 29 | x: x, 30 | nexts: make([]*node, h+1), 31 | } 32 | } 33 | 34 | type SkiplistSSet struct { 35 | sentinel *node 36 | n, height int 37 | stack [strconv.IntSize]*node 38 | } 39 | 40 | func New() *SkiplistSSet { 41 | ss := SkiplistSSet{ 42 | sentinel: nodeNew(utils.V(0), strconv.IntSize), 43 | } 44 | ss.stack[0] = ss.sentinel 45 | return &ss 46 | } 47 | 48 | func (ss *SkiplistSSet) Find(x utils.V) *utils.V { 49 | p := ss.findPredNode(x) 50 | if p.nexts[0] == nil { 51 | return nil 52 | } 53 | return &p.nexts[0].x 54 | } 55 | 56 | func (ss *SkiplistSSet) findPredNode(x utils.V) *node { 57 | p := ss.sentinel 58 | r := ss.height 59 | for r >= 0 { 60 | for p.nexts[r] != nil && utils.Compare(p.nexts[r].x, x) < 0 { 61 | p = p.nexts[r] 62 | } 63 | r-- 64 | } 65 | return p 66 | } 67 | 68 | func (ss *SkiplistSSet) Add(x utils.V) bool { 69 | p := ss.sentinel 70 | r := ss.height 71 | for r >= 0 { 72 | for p.nexts[r] != nil && utils.Compare(p.nexts[r].x, x) < 0 { 73 | p = p.nexts[r] 74 | } 75 | if p.nexts[r] != nil && utils.Compare(p.nexts[r].x, x) == 0 { 76 | return false 77 | } 78 | ss.stack[r] = p 79 | r-- 80 | } 81 | h := pickHeight() 82 | newNode := nodeNew(x, h) 83 | for ss.height < newNode.height { 84 | ss.height++ 85 | ss.stack[ss.height] = ss.sentinel 86 | } 87 | for i := 0; i <= newNode.height; i++ { 88 | newNode.nexts[i] = ss.stack[i].nexts[i] 89 | ss.stack[i].nexts[i] = newNode 90 | } 91 | ss.n++ 92 | return true 93 | } 94 | 95 | func (ss *SkiplistSSet) Remove(x utils.V) bool { 96 | ret := false 97 | p := ss.sentinel 98 | r := ss.height 99 | for r >= 0 { 100 | for p.nexts[r] != nil && utils.Compare(p.nexts[r].x, x) < 0 { 101 | p = p.nexts[r] 102 | } 103 | if p.nexts[r] != nil && utils.Compare(p.nexts[r].x, x) == 0 { 104 | ret = true 105 | ss.n-- 106 | p.nexts[r] = p.nexts[r].nexts[r] 107 | if p == ss.sentinel && p.nexts[r] == nil { 108 | ss.height-- 109 | } 110 | } 111 | r-- 112 | } 113 | return ret 114 | } 115 | -------------------------------------------------------------------------------- /skiplistsset/skiplistsset_test.go: -------------------------------------------------------------------------------- 1 | package skiplistsset 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/spinute/ods-go/utils" 7 | ) 8 | 9 | func TestNew(t *testing.T) { 10 | if ret := New().n; ret != 0 { 11 | t.Errorf("SkiplistSSet.New().n = %v", ret) 12 | } 13 | } 14 | 15 | func TestAdd(t *testing.T) { 16 | n := 10 17 | ss := New() 18 | 19 | for i := 0; i < n; i++ { 20 | ret := ss.Add(utils.V(i)) 21 | if ss.n != i+1 { 22 | t.Errorf("ss.n = %v at %v th Add", ss.n, i+1) 23 | } 24 | if ret == false { 25 | t.Errorf("Add returned false unexpectedly") 26 | } 27 | } 28 | 29 | for i := 0; i < n; i++ { 30 | ret := ss.Add(utils.V(i)) 31 | if ss.n != n { 32 | t.Errorf("ss.n = %v", ss.n) 33 | } 34 | if ret == true { 35 | t.Errorf("Add returned true unexpectedly") 36 | } 37 | } 38 | } 39 | 40 | func TestFind(t *testing.T) { 41 | n := 10 42 | ss := New() 43 | 44 | for i := 0; i < n; i++ { 45 | ret := ss.Find(utils.V(i)) 46 | if ret != nil { 47 | t.Errorf("Add returned non-nil unexpectedly, ret=%d", ret) 48 | } 49 | } 50 | 51 | for i := 0; i < n; i++ { 52 | ss.Add(utils.V(i)) 53 | ret := ss.Find(utils.V(i)) 54 | if ret == nil { 55 | t.Errorf("Add returned nil unexpectedly") 56 | } 57 | } 58 | 59 | ret := ss.Find(utils.V(n + 123)) 60 | if ret != nil { 61 | t.Errorf("Add returned nil unexpectedly") 62 | } 63 | } 64 | 65 | func TestRemove(t *testing.T) { 66 | x := utils.V(-12345) 67 | ss := New() 68 | 69 | if ss.Remove(x) == true { 70 | t.Errorf("Add returned true unexpectedly") 71 | } 72 | 73 | ss.Add(x) 74 | if ss.Remove(x) == false { 75 | t.Errorf("Add returned false unexpectedly") 76 | } 77 | 78 | if ss.Find(x) != nil { 79 | t.Errorf("Add returned non-nil unexpectedly") 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /sllist/sllist.go: -------------------------------------------------------------------------------- 1 | package sllist 2 | 3 | import ( 4 | "github.com/spinute/ods-go/utils" 5 | ) 6 | 7 | type node struct { 8 | x utils.V 9 | next *node 10 | } 11 | 12 | func nodeNew(x utils.V) *node { 13 | return &node{ 14 | x: x, 15 | } 16 | } 17 | 18 | type SLList struct { 19 | n int 20 | head, tail *node 21 | } 22 | 23 | func New() *SLList { 24 | return new(SLList) 25 | } 26 | 27 | func (l *SLList) Size() int { 28 | return l.n 29 | } 30 | 31 | func (l *SLList) Push(x utils.V) { 32 | new_node := nodeNew(x) 33 | new_node.next = l.head 34 | l.head = new_node 35 | if l.n == 0 { 36 | l.tail = new_node 37 | } 38 | l.n++ 39 | } 40 | 41 | func (l *SLList) Pop() utils.V { 42 | if l.n == 0 { 43 | return 0 // FIXME: handle error 44 | } 45 | 46 | ret := l.head.x 47 | l.head = l.head.next 48 | 49 | if l.n == 1 { 50 | l.tail = nil 51 | } 52 | l.n-- 53 | 54 | return ret 55 | } 56 | 57 | func (l *SLList) Remove() utils.V { 58 | return l.Pop() 59 | } 60 | 61 | func (l *SLList) Add(x utils.V) { 62 | new_node := nodeNew(x) 63 | if l.n == 0 { 64 | l.head = new_node 65 | } else { 66 | l.tail.next = new_node 67 | } 68 | 69 | l.tail = new_node 70 | l.n++ 71 | } 72 | -------------------------------------------------------------------------------- /sllist/sllist_test.go: -------------------------------------------------------------------------------- 1 | package sllist 2 | 3 | import ( 4 | "github.com/spinute/ods-go/utils" 5 | "testing" 6 | ) 7 | 8 | func TestNew(t *testing.T) { 9 | if ret := New().n; ret != 0 { 10 | t.Errorf("SLList.New().n = %v", ret) 11 | } 12 | } 13 | 14 | func TestAdd(t *testing.T) { 15 | n := 10 16 | sll := New() 17 | 18 | for i := 0; i < n; i++ { 19 | sll.Add(utils.V(i)) 20 | if sll.n != i+1 { 21 | t.Errorf("sll.n = %v at %v th Add", sll.n, i+1) 22 | } 23 | } 24 | } 25 | 26 | func TestPush(t *testing.T) { 27 | n := 10 28 | sll := New() 29 | 30 | for i := 0; i < n; i++ { 31 | sll.Push(utils.V(i)) 32 | if sll.n != i+1 { 33 | t.Errorf("sll.n = %v at %v th Push", sll.n, i+1) 34 | } 35 | } 36 | } 37 | 38 | func TestPushAndPop(t *testing.T) { 39 | n := 10 40 | sll := New() 41 | for i := 0; i < n; i++ { 42 | sll.Push(utils.V(i)) 43 | } 44 | 45 | for i := 0; i < n; i++ { 46 | if ret := sll.Pop(); ret != utils.V(n-1-i) { 47 | t.Errorf("%v th sll.Pop() = %v", i, ret) 48 | } 49 | } 50 | } 51 | 52 | func TestAddAndRemove(t *testing.T) { 53 | n := 10 54 | sll := New() 55 | for i := 0; i < n; i++ { 56 | sll.Add(utils.V(i)) 57 | } 58 | 59 | for i := 0; i < n; i++ { 60 | if ret := sll.Remove(); ret != utils.V(i) { 61 | t.Errorf("%v th sll.Remove() = %v", i, ret) 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /sort/sort.go: -------------------------------------------------------------------------------- 1 | package sort 2 | 3 | import ( 4 | "math/rand" 5 | 6 | "github.com/spinute/ods-go/utils" 7 | ) 8 | 9 | func merge(a0, a1, a []utils.V) { 10 | i0 := 0 11 | i1 := 0 12 | for i := 0; i < len(a); i++ { 13 | if i0 == len(a0) { 14 | a[i] = a1[i1] 15 | i1++ 16 | } else if i1 == len(a1) { 17 | a[i] = a0[i0] 18 | i0++ 19 | } else if utils.Compare(a0[i0], a1[i1]) < 0 { 20 | a[i] = a0[i0] 21 | i0++ 22 | } else { 23 | a[i] = a1[i1] 24 | i1++ 25 | } 26 | } 27 | } 28 | 29 | func MergeSort(a []utils.V) []utils.V { 30 | if len(a) <= 1 { 31 | return a 32 | } 33 | mid := len(a) / 2 34 | a0 := make([]utils.V, mid) 35 | copy(a0[0:mid], a[0:mid]) 36 | a1 := make([]utils.V, len(a)-mid) 37 | copy(a1[0:len(a)-mid], a[mid:len(a)]) 38 | MergeSort(a0) 39 | MergeSort(a1) 40 | merge(a0, a1, a) 41 | return a 42 | } 43 | 44 | func QuickSort(a []utils.V) []utils.V { 45 | quickSort(a, 0, len(a)) 46 | return a 47 | } 48 | 49 | func quickSort(a []utils.V, i, n int) []utils.V { 50 | if n <= 1 { 51 | return a 52 | } 53 | x := a[i+rand.Int()%n] 54 | p := i - 1 55 | j := i 56 | q := i + n 57 | for j < q { 58 | comp := utils.Compare(a[j], x) 59 | if comp < 0 { 60 | p++ 61 | a[j], a[p] = a[p], a[j] 62 | j++ 63 | } else if comp > 0 { 64 | q-- 65 | a[j], a[q] = a[q], a[j] 66 | } else { 67 | j++ 68 | } 69 | } 70 | quickSort(a, i, p-i+1) 71 | quickSort(a, q, n-(q-i)) 72 | return a 73 | } 74 | -------------------------------------------------------------------------------- /sort/sort_test.go: -------------------------------------------------------------------------------- 1 | package sort 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/spinute/ods-go/utils" 7 | ) 8 | 9 | func slice_equal(a, b []utils.V) bool { 10 | if len(a) != len(b) { 11 | return false 12 | } 13 | for i, _ := range a { 14 | if a[i] != b[i] { 15 | return false 16 | } 17 | } 18 | return true 19 | } 20 | 21 | func TestMergeSort(t *testing.T) { 22 | tests := []struct { 23 | arg []utils.V 24 | expected []utils.V 25 | }{ 26 | {[]utils.V{}, []utils.V{}}, 27 | {[]utils.V{1}, []utils.V{1}}, 28 | {[]utils.V{0, 1}, []utils.V{0, 1}}, 29 | {[]utils.V{1, 0, 1}, []utils.V{0, 1, 1}}, 30 | {[]utils.V{3, 2, -1}, []utils.V{-1, 2, 3}}, 31 | {[]utils.V{3, 2, -1, 3, 2, 1, 1, 2, 3}, []utils.V{-1, 1, 1, 2, 2, 2, 3, 3, 3}}, 32 | } 33 | for _, test := range tests { 34 | if ret := MergeSort(test.arg); slice_equal(ret, test.expected) == false { 35 | t.Errorf("MergeSort(%v) = %v", test.arg, ret) 36 | } 37 | } 38 | } 39 | 40 | func TestQuickSort(t *testing.T) { 41 | tests := []struct { 42 | arg []utils.V 43 | expected []utils.V 44 | }{ 45 | {[]utils.V{}, []utils.V{}}, 46 | {[]utils.V{1}, []utils.V{1}}, 47 | {[]utils.V{0, 1}, []utils.V{0, 1}}, 48 | {[]utils.V{1, 0, 1}, []utils.V{0, 1, 1}}, 49 | {[]utils.V{3, 2, -1}, []utils.V{-1, 2, 3}}, 50 | {[]utils.V{3, 2, -1, 3, 2, 1, 1, 2, 3}, []utils.V{-1, 1, 1, 2, 2, 2, 3, 3, 3}}, 51 | } 52 | for _, test := range tests { 53 | if ret := QuickSort(test.arg); slice_equal(ret, test.expected) == false { 54 | t.Errorf("QuickSort(%v) = %v", test.arg, ret) 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | for dir in $(find . -type dir -depth 1 | grep -v \.git); do 4 | cd $dir 5 | go test 6 | cd .. 7 | done 8 | -------------------------------------------------------------------------------- /treap/treap.go: -------------------------------------------------------------------------------- 1 | package treap 2 | 3 | import ( 4 | "math/rand" 5 | 6 | "github.com/spinute/ods-go/utils" 7 | ) 8 | 9 | type node struct { 10 | left, right, parent *node 11 | x utils.V 12 | p int 13 | } 14 | 15 | type Treap struct { 16 | r *node 17 | n int 18 | } 19 | 20 | func New() *Treap { 21 | return &Treap{} 22 | } 23 | 24 | func (treap *Treap) FindEQ(x utils.V) bool { 25 | w := treap.r 26 | for w != nil { 27 | comp := utils.Compare(x, w.x) 28 | if comp < 0 { 29 | w = w.left 30 | } else if comp > 0 { 31 | w = w.right 32 | } else { 33 | return true 34 | } 35 | } 36 | return false 37 | } 38 | 39 | func (treap *Treap) Find(x utils.V) *utils.V { 40 | w := treap.r 41 | var ret *node = nil 42 | for w != nil { 43 | comp := utils.Compare(x, w.x) 44 | if comp < 0 { 45 | ret = w 46 | w = w.left 47 | } else if comp > 0 { 48 | w = w.right 49 | } else { 50 | return &w.x 51 | } 52 | } 53 | if ret == nil { 54 | return nil 55 | } 56 | return &ret.x 57 | } 58 | 59 | func (treap *Treap) Add(x utils.V) bool { 60 | var added bool 61 | newNode := &node{x: x, p: rand.Int()} 62 | lastNode := treap.findLast(x) 63 | 64 | if lastNode == nil { 65 | treap.r = newNode 66 | added = true 67 | } else { 68 | added = addChild(lastNode, newNode) 69 | } 70 | 71 | if added == true { 72 | treap.n++ 73 | treap.bubble_up(newNode) 74 | } 75 | return added 76 | } 77 | func (treap *Treap) findLast(x utils.V) *node { 78 | w := treap.r 79 | last := w 80 | for w != nil { 81 | comp := utils.Compare(x, w.x) 82 | last = w 83 | if comp < 0 { 84 | w = w.left 85 | } else if comp > 0 { 86 | w = w.right 87 | } else { 88 | return w 89 | } 90 | } 91 | return last 92 | } 93 | func addChild(p, c *node) bool { 94 | comp := utils.Compare(c.x, p.x) 95 | if comp < 0 { 96 | p.left = c 97 | } else if comp > 0 { 98 | p.right = c 99 | } else { 100 | return false 101 | } 102 | c.parent = p 103 | return true 104 | } 105 | func (treap *Treap) bubble_up(u *node) { 106 | for u.parent != nil && u.parent.p > u.p { 107 | if u.parent.right == u { 108 | treap.rotateLeft(u.parent) 109 | } else { 110 | treap.rotateRight(u.parent) 111 | } 112 | } 113 | if u.parent == nil { 114 | treap.r = u 115 | } 116 | } 117 | 118 | func (treap *Treap) Remove(x utils.V) bool { 119 | u := treap.findLast(x) 120 | if u != nil && utils.Compare(u.x, x) == 0 { 121 | treap.trickleDown(u) 122 | treap.splice(u) 123 | return true 124 | } 125 | return false 126 | } 127 | func (treap *Treap) trickleDown(u *node) { 128 | for u.left != nil || u.right != nil { 129 | if u.left == nil { 130 | treap.rotateLeft(u) 131 | } else if u.right == nil { 132 | treap.rotateRight(u) 133 | } else if u.left.p < u.right.p { 134 | treap.rotateRight(u) 135 | } else { 136 | treap.rotateLeft(u) 137 | } 138 | if treap.r == u { 139 | treap.r = u.parent 140 | } 141 | } 142 | } 143 | func (treap *Treap) splice(u *node) { 144 | var c, p *node 145 | if u.left != nil { 146 | c = u.left 147 | } else { 148 | c = u.right 149 | } 150 | 151 | if treap.r == u { 152 | treap.r = c 153 | p = nil 154 | } else { 155 | p = u.parent 156 | if u == p.left { 157 | p.left = c 158 | } else { 159 | p.right = c 160 | } 161 | } 162 | 163 | if c != nil { 164 | c.parent = p 165 | } 166 | } 167 | 168 | func (treap *Treap) rotateLeft(u *node) { 169 | w := u.right 170 | w.parent = u.parent 171 | if w.parent != nil { 172 | if w.parent.left == u { 173 | w.parent.left = w 174 | } else { 175 | w.parent.right = w 176 | } 177 | } 178 | u.right = w.left 179 | if u.right != nil { 180 | u.right.parent = u 181 | } 182 | u.parent = w 183 | w.left = u 184 | if u == treap.r { 185 | treap.r = w 186 | treap.r.parent = nil 187 | } 188 | } 189 | func (treap *Treap) rotateRight(u *node) { 190 | w := u.left 191 | w.parent = u.parent 192 | if w.parent != nil { 193 | if w.parent.left == u { 194 | w.parent.left = w 195 | } else { 196 | w.parent.right = w 197 | } 198 | } 199 | u.left = w.right 200 | if u.left != nil { 201 | u.left.parent = u 202 | } 203 | u.parent = w 204 | w.right = u 205 | if u == treap.r { 206 | treap.r = w 207 | treap.r.parent = nil 208 | } 209 | } 210 | -------------------------------------------------------------------------------- /treap/treap_test.go: -------------------------------------------------------------------------------- 1 | package treap 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/spinute/ods-go/utils" 7 | ) 8 | 9 | func TestNew(t *testing.T) { 10 | if ret := New().n; ret != 0 { 11 | t.Errorf("Treap.New().n = %v", ret) 12 | } 13 | } 14 | 15 | func TestAdd(t *testing.T) { 16 | n := 10 17 | treap := New() 18 | 19 | for i := 0; i < n; i++ { 20 | ret := treap.Add(utils.V(i)) 21 | if treap.n != i+1 { 22 | t.Errorf("treap.n = %v at %v th Add", treap.n, i+1) 23 | } 24 | if ret == false { 25 | t.Errorf("Add returned false unexpectedly") 26 | } 27 | } 28 | 29 | for i := 0; i < n; i++ { 30 | ret := treap.Add(utils.V(i)) 31 | if treap.n != n { 32 | t.Errorf("treap.n = %v", treap.n) 33 | } 34 | if ret == true { 35 | t.Errorf("Add returned true unexpectedly") 36 | } 37 | } 38 | } 39 | 40 | func TestFindEQ(t *testing.T) { 41 | n := 10 42 | treap := New() 43 | 44 | for i := 0; i < n; i++ { 45 | ret := treap.FindEQ(utils.V(i)) 46 | if ret == true { 47 | t.Errorf("Add returned non-nil unexpectedly, ret=%v", ret) 48 | } 49 | } 50 | 51 | for i := 0; i < n; i++ { 52 | treap.Add(utils.V(i)) 53 | ret := treap.FindEQ(utils.V(i)) 54 | if ret == false { 55 | t.Errorf("Add returned nil unexpectedly") 56 | } 57 | } 58 | 59 | ret := treap.FindEQ(utils.V(n + 123)) 60 | if ret == true { 61 | t.Errorf("Add returned nil unexpectedly") 62 | } 63 | } 64 | 65 | func TestFind(t *testing.T) { 66 | n := 10 67 | treap := New() 68 | 69 | for i := 0; i < n; i++ { 70 | ret := treap.Find(utils.V(i)) 71 | if ret != nil { 72 | t.Errorf("non-nil unexpectedly, ret=%d", ret) 73 | } 74 | } 75 | 76 | for i := 0; i < n; i++ { 77 | treap.Add(utils.V(i)) 78 | ret := treap.Find(utils.V(i)) 79 | if ret == nil { 80 | t.Errorf("Find returned nil unexpectedly") 81 | } 82 | } 83 | 84 | ret := treap.Find(utils.V(n - 123)) 85 | if *ret != utils.V(0) { 86 | t.Errorf("unexpectedly returned %v", *ret) 87 | } 88 | } 89 | 90 | func TestRemove(t *testing.T) { 91 | x := utils.V(-12345) 92 | treap := New() 93 | 94 | if treap.Remove(x) == true { 95 | t.Errorf("Add returned true unexpectedly") 96 | } 97 | 98 | treap.Add(x) 99 | if treap.Remove(x) == false { 100 | t.Errorf("Add returned false unexpectedly") 101 | } 102 | 103 | if treap.Find(x) != nil { 104 | t.Errorf("Add returned non-nil unexpectedly") 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /utils/utils.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | type V int 4 | 5 | func Compare(a, b V) int { 6 | return int(a - b) 7 | } 8 | 9 | func Max(a, b int) int { 10 | if a < b { 11 | return b 12 | } else { 13 | return a 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /utils/utils_test.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import "testing" 4 | 5 | func TestMax(t *testing.T) { 6 | tests := []struct { 7 | arg1, arg2, want int 8 | }{ 9 | {0, 1, 1}, 10 | {-123, 321, 321}, 11 | {3, 3, 3}, 12 | } 13 | 14 | for _, test := range tests { 15 | if ret := Max(test.arg1, test.arg2); ret != test.want { 16 | t.Errorf("Max(%v, %v) = %v", test.arg1, test.arg2, ret) 17 | } 18 | } 19 | } 20 | --------------------------------------------------------------------------------