diff --git a/avl/avl.go b/avl/avl.go index 53edc30..e60050d 100644 --- a/avl/avl.go +++ b/avl/avl.go @@ -117,6 +117,12 @@ func (tree *Tree) Remove(key interface{}) (interface{}, bool) { return nil, false } +func (tree *Tree) Clear() { + tree.size = 0 + tree.root = nil + tree.iter = NewIteratorWithCap(nil, 16) +} + // Values 返回先序遍历的值 func (tree *Tree) Values() []interface{} { mszie := 0 diff --git a/avldup/avldup.go b/avldup/avldup.go index f0552fe..4cd7855 100644 --- a/avldup/avldup.go +++ b/avldup/avldup.go @@ -117,6 +117,12 @@ func (tree *Tree) Remove(key interface{}) (interface{}, bool) { return nil, false } +func (tree *Tree) Clear() { + tree.size = 0 + tree.root = nil + tree.iter = NewIteratorWithCap(nil, 16) +} + // Values 返回先序遍历的值 func (tree *Tree) Values() []interface{} { mszie := 0 diff --git a/avlkey/avlkey.go b/avlkey/avlkey.go index 0d4fc92..6efbf4f 100644 --- a/avlkey/avlkey.go +++ b/avlkey/avlkey.go @@ -118,6 +118,12 @@ func (tree *Tree) Remove(key interface{}) (interface{}, bool) { return nil, false } +func (tree *Tree) Clear() { + tree.size = 0 + tree.root = nil + tree.iter = NewIteratorWithCap(nil, 16) +} + // Values 返回先序遍历的值 func (tree *Tree) Values() []interface{} { mszie := 0 diff --git a/avlkeydup/avlkeydup.go b/avlkeydup/avlkeydup.go index fff617c..a354745 100644 --- a/avlkeydup/avlkeydup.go +++ b/avlkeydup/avlkeydup.go @@ -118,6 +118,12 @@ func (tree *Tree) Remove(key interface{}) (interface{}, bool) { return nil, false } +func (tree *Tree) Clear() { + tree.size = 0 + tree.root = nil + tree.iter = NewIteratorWithCap(nil, 16) +} + // Values 返回先序遍历的值 func (tree *Tree) Values() []interface{} { mszie := 0 diff --git a/hashmap/avlkeydup.go b/hashmap/avlkeydup.go deleted file mode 100644 index 01079fe..0000000 --- a/hashmap/avlkeydup.go +++ /dev/null @@ -1,695 +0,0 @@ -package hashmap - -import ( - "474420502.top/eson/structure/compare" - "github.com/davecgh/go-spew/spew" -) - -type avlNode struct { - children [2]*avlNode - parent *avlNode - height int - key, value interface{} -} - -func (n *avlNode) clearAttr() { - n.parent = nil - n.children[0] = nil - n.children[1] = nil - n.height = 0 -} - -type avlTree struct { - root *avlNode - size int - Compare compare.Compare -} - -func avlNew(Compare compare.Compare) *avlTree { - return &avlTree{Compare: Compare} -} - -func (tree *avlTree) Size() int { - return tree.size -} - -func (tree *avlTree) Clear() { - tree.size = 0 - tree.root = nil -} - -func (tree *avlTree) Remove(key interface{}) (interface{}, bool) { - - if n, ok := tree.GetNode(key); ok { - - tree.size-- - if tree.size == 0 { - tree.root = nil - return n.value, true - } - - left := getHeight(n.children[0]) - right := getHeight(n.children[1]) - - if left == -1 && right == -1 { - p := n.parent - p.children[getRelationship(n)] = nil - tree.fixRemoveHeight(p) - return n.value, true - } - - var cur *avlNode - if left > right { - cur = n.children[0] - for cur.children[1] != nil { - cur = cur.children[1] - } - - cleft := cur.children[0] - cur.parent.children[getRelationship(cur)] = cleft - if cleft != nil { - cleft.parent = cur.parent - } - - } else { - cur = n.children[1] - for cur.children[0] != nil { - cur = cur.children[0] - } - - cright := cur.children[1] - cur.parent.children[getRelationship(cur)] = cright - - if cright != nil { - cright.parent = cur.parent - } - } - - cparent := cur.parent - // 修改为interface 交换 - n.value, cur.value = cur.value, n.value - n.key, cur.key = cur.key, n.key - - // 考虑到刚好替换的节点是 被替换节点的孩子节点的时候, 从自身修复高度 - if cparent == n { - tree.fixRemoveHeight(n) - } else { - tree.fixRemoveHeight(cparent) - } - - return cur.value, true - } - - return nil, false -} - -func (tree *avlTree) Get(key interface{}) (interface{}, bool) { - n, ok := tree.GetNode(key) - if ok { - return n.value, true - } - return n, false -} - -func (tree *avlTree) GetNode(key interface{}) (*avlNode, bool) { - - for n := tree.root; n != nil; { - switch c := tree.Compare(key, n.key); c { - case -1: - n = n.children[0] - case 1: - n = n.children[1] - case 0: - return n, true - default: - panic("Get Compare only is allowed in -1, 0, 1") - } - } - return nil, false -} - -func (tree *avlTree) Put(key, value interface{}) bool { - - if tree.size == 0 { - tree.size++ - tree.root = &avlNode{key: key, value: value} - return true - } - - for cur, c := tree.root, 0; ; { - c = tree.Compare(key, cur.key) - if c == -1 { - if cur.children[0] == nil { - tree.size++ - cur.children[0] = &avlNode{key: key, value: value} - cur.children[0].parent = cur - if cur.height == 0 { - tree.fixPutHeight(cur) - } - return true - } - cur = cur.children[0] - } else if c == 1 { - if cur.children[1] == nil { - tree.size++ - cur.children[1] = &avlNode{key: key, value: value} - cur.children[1].parent = cur - if cur.height == 0 { - tree.fixPutHeight(cur) - } - return true - } - cur = cur.children[1] - } else { - cur.key = key - cur.value = value - return false - } - } -} - -func (tree *avlTree) PutNode(n *avlNode) bool { - - if tree.size == 0 { - tree.size++ - tree.root = n - return true - } - - for cur, c := tree.root, 0; ; { - c = tree.Compare(n.key, cur.key) - if c == -1 { - if cur.children[0] == nil { - tree.size++ - cur.children[0] = n - cur.children[0].parent = cur - if cur.height == 0 { - tree.fixPutHeight(cur) - } - return true - } - cur = cur.children[0] - } else if c == 1 { - if cur.children[1] == nil { - tree.size++ - cur.children[1] = n - cur.children[1].parent = cur - if cur.height == 0 { - tree.fixPutHeight(cur) - } - return true - } - cur = cur.children[1] - } else { - // panic("same key") - cur.key = n.key - cur.value = n.value - return false - } - } -} - -type TraversalMethod int - -const ( - // L = left R = right D = Value(dest) - _ TraversalMethod = iota - //DLR 先值 然后左递归 右递归 下面同理 - DLR - //LDR 先从左边有序访问到右边 从小到大 - LDR - // LRD 同理 - LRD - // DRL 同理 - DRL - // RDL 先从右边有序访问到左边 从大到小 - RDL - // RLD 同理 - RLD -) - -// Traversal 遍历的方法 默认是LDR 从小到大 Compare 为 l < r -func (tree *avlTree) Traversal(every func(*avlNode) bool, traversalMethod ...interface{}) { - if tree.root == nil { - return - } - - method := LDR - if len(traversalMethod) != 0 { - method = traversalMethod[0].(TraversalMethod) - } - - switch method { - case DLR: - var traverasl func(cur *avlNode) bool - traverasl = func(cur *avlNode) bool { - if cur == nil { - return true - } - if !every(cur) { - return false - } - if !traverasl(cur.children[0]) { - return false - } - if !traverasl(cur.children[1]) { - return false - } - return true - } - traverasl(tree.root) - case LDR: - var traverasl func(cur *avlNode) bool - traverasl = func(cur *avlNode) bool { - if cur == nil { - return true - } - if !traverasl(cur.children[0]) { - return false - } - if !every(cur) { - return false - } - if !traverasl(cur.children[1]) { - return false - } - return true - } - traverasl(tree.root) - case LRD: - var traverasl func(cur *avlNode) bool - traverasl = func(cur *avlNode) bool { - if cur == nil { - return true - } - if !traverasl(cur.children[0]) { - return false - } - if !traverasl(cur.children[1]) { - return false - } - if !every(cur) { - return false - } - return true - } - traverasl(tree.root) - case DRL: - var traverasl func(cur *avlNode) bool - traverasl = func(cur *avlNode) bool { - if cur == nil { - return true - } - if !every(cur) { - return false - } - if !traverasl(cur.children[0]) { - return false - } - if !traverasl(cur.children[1]) { - return false - } - return true - } - traverasl(tree.root) - case RDL: - var traverasl func(cur *avlNode) bool - traverasl = func(cur *avlNode) bool { - if cur == nil { - return true - } - if !traverasl(cur.children[1]) { - return false - } - if !every(cur) { - return false - } - if !traverasl(cur.children[0]) { - return false - } - return true - } - traverasl(tree.root) - case RLD: - var traverasl func(cur *avlNode) bool - traverasl = func(cur *avlNode) bool { - if cur == nil { - return true - } - if !traverasl(cur.children[1]) { - return false - } - if !traverasl(cur.children[0]) { - return false - } - if !every(cur) { - return false - } - return true - } - traverasl(tree.root) - } -} - -func (tree *avlTree) lrrotate(cur *avlNode) { - - const l = 1 - const r = 0 - - movparent := cur.children[l] - mov := movparent.children[r] - - mov.value, cur.value = cur.value, mov.value //交换值达到, 相对位移 - mov.key, cur.key = cur.key, mov.key - - if mov.children[l] != nil { - movparent.children[r] = mov.children[l] - movparent.children[r].parent = movparent - //movparent.children[r].child = l - } else { - movparent.children[r] = nil - } - - if mov.children[r] != nil { - mov.children[l] = mov.children[r] - //mov.children[l].child = l - } else { - mov.children[l] = nil - } - - if cur.children[r] != nil { - mov.children[r] = cur.children[r] - mov.children[r].parent = mov - } else { - mov.children[r] = nil - } - - cur.children[r] = mov - mov.parent = cur - - mov.height = getMaxChildrenHeight(mov) + 1 - movparent.height = getMaxChildrenHeight(movparent) + 1 - cur.height = getMaxChildrenHeight(cur) + 1 -} - -func (tree *avlTree) rlrotate(cur *avlNode) { - - const l = 0 - const r = 1 - - movparent := cur.children[l] - mov := movparent.children[r] - - mov.value, cur.value = cur.value, mov.value //交换值达到, 相对位移 - mov.key, cur.key = cur.key, mov.key - - if mov.children[l] != nil { - movparent.children[r] = mov.children[l] - movparent.children[r].parent = movparent - } else { - movparent.children[r] = nil - } - - if mov.children[r] != nil { - mov.children[l] = mov.children[r] - } else { - mov.children[l] = nil - } - - if cur.children[r] != nil { - mov.children[r] = cur.children[r] - mov.children[r].parent = mov - } else { - mov.children[r] = nil - } - - cur.children[r] = mov - mov.parent = cur - - mov.height = getMaxChildrenHeight(mov) + 1 - movparent.height = getMaxChildrenHeight(movparent) + 1 - cur.height = getMaxChildrenHeight(cur) + 1 -} - -func (tree *avlTree) rrotate(cur *avlNode) { - - const l = 0 - const r = 1 - // 1 right 0 left - mov := cur.children[l] - - mov.value, cur.value = cur.value, mov.value //交换值达到, 相对位移 - mov.key, cur.key = cur.key, mov.key - - // mov.children[l]不可能为nil - mov.children[l].parent = cur - cur.children[l] = mov.children[l] - - // 解决mov节点孩子转移的问题 - if mov.children[r] != nil { - mov.children[l] = mov.children[r] - } else { - mov.children[l] = nil - } - - if cur.children[r] != nil { - mov.children[r] = cur.children[r] - mov.children[r].parent = mov - } else { - mov.children[r] = nil - } - - // 连接转移后的节点 由于mov只是与cur交换值,parent不变 - cur.children[r] = mov - - mov.height = getMaxChildrenHeight(mov) + 1 - cur.height = getMaxChildrenHeight(cur) + 1 -} - -func (tree *avlTree) lrotate(cur *avlNode) { - - const l = 1 - const r = 0 - - mov := cur.children[l] - - mov.value, cur.value = cur.value, mov.value //交换值达到, 相对位移 - mov.key, cur.key = cur.key, mov.key - - // 不可能为nil - mov.children[l].parent = cur - cur.children[l] = mov.children[l] - - if mov.children[r] != nil { - mov.children[l] = mov.children[r] - } else { - mov.children[l] = nil - } - - if cur.children[r] != nil { - mov.children[r] = cur.children[r] - mov.children[r].parent = mov - } else { - mov.children[r] = nil - } - - cur.children[r] = mov - - mov.height = getMaxChildrenHeight(mov) + 1 - cur.height = getMaxChildrenHeight(cur) + 1 -} - -func getMaxAndChildrenHeight(cur *avlNode) (h1, h2, maxh int) { - h1 = getHeight(cur.children[0]) - h2 = getHeight(cur.children[1]) - if h1 > h2 { - maxh = h1 - } else { - maxh = h2 - } - - return -} - -func getMaxChildrenHeight(cur *avlNode) int { - h1 := getHeight(cur.children[0]) - h2 := getHeight(cur.children[1]) - if h1 > h2 { - return h1 - } - return h2 -} - -func getHeight(cur *avlNode) int { - if cur == nil { - return -1 - } - return cur.height -} - -func (tree *avlTree) fixRemoveHeight(cur *avlNode) { - for { - - lefth, rigthh, lrmax := getMaxAndChildrenHeight(cur) - - // 判断当前节点是否有变化, 如果没变化的时候, 不需要往上修复 - curheight := lrmax + 1 - cur.height = curheight - - // 计算高度的差值 绝对值大于2的时候需要旋转 - diff := lefth - rigthh - if diff < -1 { - r := cur.children[1] // 根据左旋转的右边节点的子节点 左右高度选择旋转的方式 - if getHeight(r.children[0]) > getHeight(r.children[1]) { - tree.lrrotate(cur) - } else { - tree.lrotate(cur) - } - } else if diff > 1 { - l := cur.children[0] - if getHeight(l.children[1]) > getHeight(l.children[0]) { - tree.rlrotate(cur) - } else { - tree.rrotate(cur) - } - } else { - if cur.height == curheight { - return - } - } - - if cur.parent == nil { - return - } - - cur = cur.parent - } - -} - -func (tree *avlTree) fixPutHeight(cur *avlNode) { - - for { - - lefth := getHeight(cur.children[0]) - rigthh := getHeight(cur.children[1]) - - // 计算高度的差值 绝对值大于2的时候需要旋转 - diff := lefth - rigthh - if diff < -1 { - r := cur.children[1] // 根据左旋转的右边节点的子节点 左右高度选择旋转的方式 - if getHeight(r.children[0]) > getHeight(r.children[1]) { - tree.lrrotate(cur) - } else { - tree.lrotate(cur) - } - } else if diff > 1 { - l := cur.children[0] - if getHeight(l.children[1]) > getHeight(l.children[0]) { - tree.rlrotate(cur) - } else { - tree.rrotate(cur) - } - - } else { - // 选择一个child的最大高度 + 1为 高度 - if lefth > rigthh { - cur.height = lefth + 1 - } else { - cur.height = rigthh + 1 - } - } - - if cur.parent == nil || cur.height < cur.parent.height { - return - } - cur = cur.parent - } -} - -func getRelationship(cur *avlNode) int { - if cur.parent.children[1] == cur { - return 1 - } - return 0 -} - -func output(node *avlNode, prefix string, isTail bool, str *string) { - - if node.children[1] != nil { - newPrefix := prefix - if isTail { - newPrefix += "│ " - } else { - newPrefix += " " - } - output(node.children[1], newPrefix, false, str) - } - *str += prefix - if isTail { - *str += "└── " - } else { - *str += "┌── " - } - - *str += spew.Sprint(node.value) + "\n" - - if node.children[0] != nil { - newPrefix := prefix - if isTail { - newPrefix += " " - } else { - newPrefix += "│ " - } - output(node.children[0], newPrefix, true, str) - } - -} - -func outputfordebug(node *avlNode, prefix string, isTail bool, str *string) { - - if node.children[1] != nil { - newPrefix := prefix - if isTail { - newPrefix += "│ " - } else { - newPrefix += " " - } - outputfordebug(node.children[1], newPrefix, false, str) - } - *str += prefix - if isTail { - *str += "└── " - } else { - *str += "┌── " - } - - suffix := "(" - parentv := "" - if node.parent == nil { - parentv = "nil" - } else { - parentv = spew.Sprint(node.parent.value) - } - suffix += parentv + "|" + spew.Sprint(node.height) + ")" - *str += spew.Sprint(node.value) + suffix + "\n" - - if node.children[0] != nil { - newPrefix := prefix - if isTail { - newPrefix += " " - } else { - newPrefix += "│ " - } - outputfordebug(node.children[0], newPrefix, true, str) - } -} - -func (tree *avlTree) debugString() string { - if tree.size == 0 { - return "" - } - str := "AVLTree\n" - outputfordebug(tree.root, "", true, &str) - return str -} diff --git a/hashmap/bucket.go b/hashmap/bucket.go deleted file mode 100644 index 8645670..0000000 --- a/hashmap/bucket.go +++ /dev/null @@ -1,76 +0,0 @@ -package hashmap - -import ( - "474420502.top/eson/structure/compare" -) - -type hmBucket struct { - size uint - data []*bucketNode -} - -type bucketNode struct { - hash uint - key, value interface{} -} - -func newBucket() *hmBucket { - return &hmBucket{} -} - -func (bkt *hmBucket) Get(key interface{}, Compare compare.Compare) interface{} { - // bkt.data - for _, n := range bkt.data { - if Compare(n.key, key) == 0 { - return n.value - } - } - return nil -} - -func (bkt *hmBucket) Add(hash uint, k, v interface{}, Compare compare.Compare) { - - for i := uint(0); i < bkt.size; i++ { - n := bkt.data[i] - if Compare(n.key, k) == 0 { - n.hash = hash - n.key = k - n.value = v - return - } - } - - if bkt.size < uint(len(bkt.data)) { - n := bkt.data[bkt.size] - n.hash = hash - n.key = k - n.value = v - bkt.size++ - return - } - - bkt.data = append(bkt.data, &bucketNode{key: k, value: v, hash: hash}) - bkt.size++ -} - -func (bkt *hmBucket) AddNode(node *bucketNode, Compare compare.Compare) { - - for i := uint(0); i < bkt.size; i++ { - n := bkt.data[i] - if Compare(n.key, node.key) == 0 { - n.hash = node.hash - n.key = node.key - n.value = node.value - panic(123) - return - } - } - - if bkt.size < uint(len(bkt.data)) { - bkt.data[bkt.size] = node - bkt.size++ - return - } - bkt.data = append(bkt.data, node) - bkt.size++ -} diff --git a/hashmap/gomap/hashmap.go b/hashmap/gomap/hashmap.go deleted file mode 100644 index 438fe84..0000000 --- a/hashmap/gomap/hashmap.go +++ /dev/null @@ -1,63 +0,0 @@ -package gomap - -import "fmt" - -type HashMap struct { - hm map[interface{}]interface{} -} - -// New instantiates a hash map. -func New() *HashMap { - return &HashMap{hm: make(map[interface{}]interface{})} -} - -// Put inserts element into the map. -func (hm *HashMap) Put(key interface{}, value interface{}) { - hm.hm[key] = value -} - -func (hm *HashMap) Get(key interface{}) (value interface{}, isfound bool) { - value, isfound = hm.hm[key] - return -} - -func (hm *HashMap) Remove(key interface{}) { - delete(hm.hm, key) -} - -func (hm *HashMap) Empty() bool { - return len(hm.hm) == 0 -} - -func (hm *HashMap) Size() int { - return len(hm.hm) -} - -func (hm *HashMap) Keys() []interface{} { - keys := make([]interface{}, len(hm.hm)) - count := 0 - for key := range hm.hm { - keys[count] = key - count++ - } - return keys -} - -func (hm *HashMap) Values() []interface{} { - values := make([]interface{}, len(hm.hm)) - count := 0 - for _, value := range hm.hm { - values[count] = value - count++ - } - return values -} - -func (hm *HashMap) Clear() { - hm.hm = make(map[interface{}]interface{}) -} - -func (hm *HashMap) String() string { - str := fmt.Sprintf("%v", hm.hm) - return str -} diff --git a/hashmap/hashmap.go b/hashmap/hashmap.go index aa8dbde..56cd19f 100644 --- a/hashmap/hashmap.go +++ b/hashmap/hashmap.go @@ -1,104 +1,63 @@ package hashmap -import ( - "474420502.top/eson/structure/compare" -) - -type HashCode func(key interface{}) uint +import "fmt" type HashMap struct { - growfactor uint - slimmingfactor uint - - table *Table - - GetHash HashCode - Compare compare.Compare - - growsize uint - size uint + hm map[interface{}]interface{} } -func HashInt(key interface{}) uint { - thekey := uint(key.(int)) - hbit := thekey & 0xffffffff - lbit := (thekey & 0xffffffff00000000) >> 32 - return lbit ^ hbit +// New instantiates a hash map. +func New() *HashMap { + return &HashMap{hm: make(map[interface{}]interface{})} } -func New(hcode HashCode, comp compare.Compare) *HashMap { - hm := &HashMap{} - hm.growfactor = 2 - hm.GetHash = hcode - hm.Compare = comp - // initcap := uint(8) - hm.table = newTable() - hm.countNextGrow() - return hm +// Put inserts element into the map. +func (hm *HashMap) Put(key interface{}, value interface{}) { + hm.hm[key] = value } -func (hm *HashMap) countNextGrow() { - hm.growsize = hm.table.Cap() << 1 +func (hm *HashMap) Get(key interface{}) (value interface{}, isfound bool) { + value, isfound = hm.hm[key] + return } -func (hm *HashMap) grow() { - if hm.size >= hm.growsize { - newsize := hm.size << 1 - // newtable := make([]*avlTree, newsize, newsize) - hm.table.Grow(int(newsize - hm.size)) - nodelist := make([]*avlNode, hm.size, hm.size) - i := 0 - hm.table.Traversal(func(cur *avlTree) { - if cur != nil { - cur.Traversal(func(node *avlNode) bool { - nodelist[i] = node - i++ - return true - }) - cur.Clear() - } - }) +func (hm *HashMap) Remove(key interface{}) { + delete(hm.hm, key) +} - var hash, index uint - for _, node := range nodelist { - hash = hm.GetHash(node.key) - index = hash % hm.table.cap - //bkt := newtable[index] - bkt := hm.table.GetWithNilSet(index, func(data []*avlTree, idx uint) { - data[idx] = avlNew(hm.Compare) - }) - node.clearAttr() - bkt.PutNode(node) - } +func (hm *HashMap) Empty() bool { + return len(hm.hm) == 0 +} - hm.countNextGrow() +func (hm *HashMap) Size() int { + return len(hm.hm) +} + +func (hm *HashMap) Keys() []interface{} { + keys := make([]interface{}, len(hm.hm)) + count := 0 + for key := range hm.hm { + keys[count] = key + count++ } + return keys } -func (hm *HashMap) Put(key, value interface{}) { - hash := hm.GetHash(key) - - tlen := hm.table.Cap() - index := hash % tlen - - bkt := hm.table.GetWithNilSet(index, func(data []*avlTree, idx uint) { - data[idx] = avlNew(hm.Compare) - }) - if bkt.Put(key, value) { - hm.size++ - hm.grow() +func (hm *HashMap) Values() []interface{} { + values := make([]interface{}, len(hm.hm)) + count := 0 + for _, value := range hm.hm { + values[count] = value + count++ } + return values } -func (hm *HashMap) Get(key interface{}) (interface{}, bool) { - hash := hm.GetHash(key) - - tlen := hm.table.Cap() - index := hash % tlen - - bkt := hm.table.Get(index) - if bkt != nil { - return bkt.Get(key) - } - return nil, false +func (hm *HashMap) Clear() { + hm.hm = make(map[interface{}]interface{}) +} + +func (hm *HashMap) String() string { + str := fmt.Sprintf("%v", hm.hm) + return str } diff --git a/hashmap/hashmap_test.go b/hashmap/hashmap_test.go index f206242..853bf65 100644 --- a/hashmap/hashmap_test.go +++ b/hashmap/hashmap_test.go @@ -3,13 +3,9 @@ package hashmap import ( "bytes" "encoding/gob" - "fmt" "io/ioutil" "log" - "runtime" "testing" - - "474420502.top/eson/structure/compare" ) func loadTestData() []int { @@ -25,7 +21,7 @@ func loadTestData() []int { return l } func TestCount(t *testing.T) { - hm := New(HashInt, compare.Int) + hm := New() // for i := 0; i < 100000; i++ { // hm.Put(i, i) // } @@ -35,28 +31,14 @@ func TestCount(t *testing.T) { // t.Error(hm.Get(4)) } -func PrintMemUsage() { - var m runtime.MemStats - runtime.ReadMemStats(&m) - // For info on each, see: https://golang.org/pkg/runtime/#MemStats - fmt.Printf("Alloc = %v MiB", bToMb(m.Alloc)) - fmt.Printf("\tTotalAlloc = %v MiB", bToMb(m.TotalAlloc)) - fmt.Printf("\tSys = %v MiB", bToMb(m.Sys)) - fmt.Printf("\tNumGC = %v\n", m.NumGC) -} - -func bToMb(b uint64) uint64 { - return b / 1024 / 1024 -} - -var executeCount = 1 +var executeCount = 5 var compareSize = 100000 func BenchmarkPut(b *testing.B) { b.StopTimer() l := loadTestData() - hm := New(HashInt, compare.Int) + hm := New() b.N = len(l) * executeCount // for i := 0; i < len(l); i++ { @@ -94,43 +76,43 @@ func BenchmarkGoPut(b *testing.B) { //PrintMemUsage() } -func BenchmarkGet(b *testing.B) { +// func BenchmarkGet(b *testing.B) { - b.StopTimer() - l := loadTestData() - hm := New(HashInt, compare.Int) - b.N = len(l) * executeCount - for i := 0; i < len(l); i++ { - v := l[i] - hm.Put(v, v) - } - b.StartTimer() +// b.StopTimer() +// l := loadTestData() +// hm := New() +// b.N = len(l) * executeCount +// for i := 0; i < len(l); i++ { +// v := l[i] +// hm.Put(v, v) +// } +// b.StartTimer() - for i := 0; i < b.N; i++ { - hm.Get(i) - } +// for i := 0; i < b.N; i++ { +// hm.Get(i) +// } - //b.Log(len(hm.table), hm.size) - //PrintMemUsage() -} +// //b.Log(len(hm.table), hm.size) +// //PrintMemUsage() +// } -func BenchmarkGoGet(b *testing.B) { - b.StopTimer() - l := loadTestData() - hm := make(map[int]int) - b.N = len(l) * executeCount +// func BenchmarkGoGet(b *testing.B) { +// b.StopTimer() +// l := loadTestData() +// hm := make(map[int]int) +// b.N = len(l) * executeCount - for i := 0; i < len(l); i++ { - v := l[i] - hm[v] = v - } +// for i := 0; i < len(l); i++ { +// v := l[i] +// hm[v] = v +// } - b.StartTimer() - for i := 0; i < b.N; i++ { - if _, ok := hm[i]; !ok { +// b.StartTimer() +// for i := 0; i < b.N; i++ { +// if _, ok := hm[i]; !ok { - } - } - //b.Log(len(m)) - //PrintMemUsage() -} +// } +// } +// //b.Log(len(m)) +// //PrintMemUsage() +// } diff --git a/hashmap/table.go b/hashmap/table.go deleted file mode 100644 index 3944ca2..0000000 --- a/hashmap/table.go +++ /dev/null @@ -1,142 +0,0 @@ -package hashmap - -type Table struct { - // ysizes []int - // xsizes [][]int - // xyproduct int - - size uint - growsize uint - - data []*avlTree - cap uint -} - -func newTable() *Table { - table := &Table{} - table.data = make([]*avlTree, 16, 16) - table.countCap() - return table -} - -func (t *Table) countCap() { - t.cap = uint(len(t.data)) // * (4 * 4) -} - -func (t *Table) Cap() uint { - return t.cap -} - -func (t *Table) Traversal(every func(node *avlTree)) { - for _, z := range t.data { - every(z) - } -} - -func (t *Table) Grow(size int) { - zsize := len(t.data) + size - temp := make([]*avlTree, zsize, zsize) - copy(temp, t.data) - t.data = temp - t.countCap() -} - -func (t *Table) Get(idx uint) *avlTree { - return t.data[idx] -} - -func (t *Table) GetWithNilSet(idx uint, DoSetValue func([]*avlTree, uint)) *avlTree { - - if t.data[idx] == nil { - DoSetValue(t.data, idx) - } - return t.data[idx] -} - -// func (arr *Table) Get(idx int) (interface{}, bool) { -// zindex := idx / arr.xyproduct -// nextsize := (idx % arr.xyproduct) -// yindex := nextsize / arr.xsize -// xindex := nextsize % arr.xsize - -// ydata := arr.data[zindex] -// if ydata == nil { -// return nil, false -// } - -// xdata := ydata[yindex] -// if xdata == nil { -// return nil, false -// } - -// v := xdata[xindex] -// return v, v != nil -// } - -// func (arr *Table) GetOrSet(idx int, DoSetValue func([]interface{}, int)) (result interface{}, isSet bool) { -// zindex := idx / arr.xyproduct -// nidx := (idx % arr.xyproduct) -// yindex := nidx / arr.xsize -// xindex := nidx % arr.xsize - -// ydata := arr.data[zindex] -// if ydata == nil { -// ydata = make([][]interface{}, arr.ysize, arr.ysize) -// arr.data[zindex] = ydata -// } - -// xdata := ydata[yindex] -// if xdata == nil { -// xdata = make([]interface{}, arr.xsize, arr.xsize) -// ydata[yindex] = xdata -// arr.ysizes[zindex]++ -// } - -// result = xdata[xindex] -// if result == nil { -// DoSetValue(xdata, xindex) -// result = xdata[xindex] -// if result == nil { -// panic("DoSetValue Not Set Value") -// } -// arr.xsizes[zindex][yindex]++ -// return result, false -// } -// return result, true -// } - -// func (arr *Table) Del(idx int) (interface{}, bool) { -// zindex := idx / arr.xyproduct -// nextsize := (idx % arr.xyproduct) -// yindex := nextsize / arr.xsize -// xindex := nextsize % arr.xsize - -// ydata := arr.data[zindex] -// if ydata == nil { -// return nil, false -// } - -// xdata := ydata[yindex] -// if xdata == nil { -// return nil, false -// } - -// v := xdata[xindex] -// xdata[xindex] = nil - -// isnotnil := v != nil - -// if isnotnil { -// arr.xsizes[zindex][yindex]-- -// if arr.xsizes[zindex][yindex] == 0 { -// arr.data[zindex][yindex] = nil - -// arr.ysizes[zindex]-- -// if arr.ysizes[zindex] == 0 { -// arr.data[zindex] = nil -// } -// } -// } - -// return v, isnotnil -// } diff --git a/set/hashset/hashset.go b/set/hashset/hashset.go new file mode 100644 index 0000000..06754c7 --- /dev/null +++ b/set/hashset/hashset.go @@ -0,0 +1,80 @@ +package hashset + +import ( + "fmt" + "strings" +) + +var nullItem = struct{}{} + +// HashSet +type HashSet struct { + hm map[interface{}]struct{} +} + +// New +func New() *HashSet { + return &HashSet{hm: make(map[interface{}]struct{})} +} + +// Add +func (set *HashSet) Add(items ...interface{}) { + for _, item := range items { + if _, ok := set.hm[item]; !ok { + set.hm[item] = nullItem + } + } +} + +// Remove +func (set *HashSet) Remove(items ...interface{}) { + for _, item := range items { + delete(set.hm, item) + } +} + +// Values +func (set *HashSet) Values() []interface{} { + values := make([]interface{}, set.Size()) + count := 0 + for item := range set.hm { + values[count] = item + count++ + } + return values +} + +// Contains +func (set *HashSet) Contains(item interface{}) bool { + if _, contains := set.hm[item]; contains { + return true + } + return false +} + +// Empty +func (set *HashSet) Empty() bool { + return set.Size() == 0 +} + +// Clear +func (set *HashSet) Clear() { + set.hm = make(map[interface{}]struct{}) +} + +// Size +func (set *HashSet) Size() int { + return len(set.hm) +} + +// String +func (set *HashSet) String() string { + content := "[" + items := []string{} + for k := range set.hm { + items = append(items, fmt.Sprintf("%v", k)) + } + content += strings.Join(items, ",") + content += "]" + return content +} diff --git a/set/hashset/hashset_test.go b/set/hashset/hashset_test.go new file mode 100644 index 0000000..e2a8874 --- /dev/null +++ b/set/hashset/hashset_test.go @@ -0,0 +1,54 @@ +package hashset + +import ( + "bytes" + "encoding/gob" + "io/ioutil" + "log" + "testing" +) + +func loadTestData() []int { + log.SetFlags(log.Lshortfile) + + data, err := ioutil.ReadFile("../l.log") + if err != nil { + log.Println(err) + } + var l []int + decoder := gob.NewDecoder(bytes.NewReader(data)) + decoder.Decode(&l) + return l +} + +func TestAdd(t *testing.T) { + + set := New() + for i := 0; i < 10; i++ { + set.Add(i) + } + + if set.Size() != 10 { + t.Error("size is not equals to 10") + } +} + +func TestRemove(t *testing.T) { + set := New() + + for i := 0; i < 10; i++ { + set.Add(i) + } + + for i := 0; i < 9; i++ { + set.Remove(i) + } + + if set.Size() != 1 { + t.Error("size is not equals to 0") + } + + if set.Values()[0] != 9 { + t.Error("remain is not 9") + } +} diff --git a/set/treeset/treeset.go b/set/treeset/treeset.go new file mode 100644 index 0000000..7e48b08 --- /dev/null +++ b/set/treeset/treeset.go @@ -0,0 +1,85 @@ +package treeset + +import ( + "fmt" + "strings" + + "474420502.top/eson/structure/avldup" + "474420502.top/eson/structure/compare" +) + +// TreeSet +type TreeSet struct { + tree *avldup.Tree +} + +// New +func New(Compare compare.Compare) *TreeSet { + return &TreeSet{tree: avldup.New(Compare)} +} + +// Add +func (set *TreeSet) Add(items ...interface{}) { + for _, item := range items { + set.tree.Put(item) + } +} + +// Remove +func (set *TreeSet) Remove(items ...interface{}) { + for _, item := range items { + set.tree.Remove(item) + } +} + +// Values +func (set *TreeSet) Values() []interface{} { + return set.tree.Values() +} + +// Contains +func (set *TreeSet) Contains(item interface{}) bool { + if _, ok := set.tree.Get(item); ok { + return true + } + return false +} + +// Contains the result is [r1,r2], not [r1, r2) +func (set *TreeSet) GetRange(r1, r2 interface{}) (result []interface{}) { + return set.tree.GetRange(r1, r2) +} + +// Contains the result is [r1,item,r2] r1->item->r2 are close-knit +func (set *TreeSet) GetAround(item interface{}) (result [3]interface{}) { + return set.tree.GetAround(item) +} + +// Empty +func (set *TreeSet) Empty() bool { + return set.Size() == 0 +} + +// Clear +func (set *TreeSet) Clear() { + set.tree.Clear() +} + +// Size +func (set *TreeSet) Size() int { + return set.tree.Size() +} + +// String +func (set *TreeSet) String() string { + content := "HashSet\n" + items := []string{} + + set.tree.Traversal(func(k interface{}) bool { + items = append(items, fmt.Sprintf("%v", k)) + return true + }) + + content += strings.Join(items, ", ") + return content +} diff --git a/set/treeset/treeset_test.go b/set/treeset/treeset_test.go new file mode 100644 index 0000000..3e1768e --- /dev/null +++ b/set/treeset/treeset_test.go @@ -0,0 +1 @@ +package treeset