diff --git a/hashmap/avlkeydup.go b/hashmap/avlkeydup.go index 329ad8c..097c749 100644 --- a/hashmap/avlkeydup.go +++ b/hashmap/avlkeydup.go @@ -2,120 +2,98 @@ package hashmap import ( "474420502.top/eson/structure/compare" + "github.com/davecgh/go-spew/spew" ) type avlNode struct { children [2]*avlNode - hash uint + parent *avlNode + height int key, value interface{} } type avlTree struct { - root *avlNode - lsize, rsize int - Compare compare.Compare + 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.lsize, tree.rsize = 0, 0 + tree.size = 0 tree.root = nil } -// func (tree *avlTree) Size() int { -// return tree.lsize + tree.rsize + 1 -// } +func (tree *avlTree) Remove(key interface{}) (interface{}, bool) { -// func (tree *avlTree) Remove(key interface{}) (interface{}, bool) { + if n, ok := tree.GetNode(key); ok { -// if n, ok := tree.GetNode(key); ok { + tree.size-- + if tree.size == 0 { + tree.root = nil + return n.value, true + } -// tree.size-- -// if tree.size == 0 { -// tree.root = nil -// return n.value, true -// } + left := getHeight(n.children[0]) + right := getHeight(n.children[1]) -// 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 + } -// 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] + } -// 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 + } -// 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] + } -// } else { -// cur = n.children[1] -// for cur.children[0] != nil { -// cur = cur.children[0] -// } + cright := cur.children[1] + cur.parent.children[getRelationship(cur)] = cright -// cright := cur.children[1] -// cur.parent.children[getRelationship(cur)] = cright + if cright != nil { + cright.parent = cur.parent + } + } -// 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 -// 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) + } -// // 考虑到刚好替换的节点是 被替换节点的孩子节点的时候, 从自身修复高度 -// if cparent == n { -// tree.fixRemoveHeight(n) -// } else { -// tree.fixRemoveHeight(cparent) -// } - -// return cur.value, true -// } - -// return nil, false -// } - -func (tree *avlTree) Traversal(every func(*avlNode) bool) { - if tree.root == nil { - return + return cur.value, true } - 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) + return nil, false } func (tree *avlTree) Get(key interface{}) (interface{}, bool) { @@ -143,44 +121,10 @@ func (tree *avlTree) GetNode(key interface{}) (*avlNode, bool) { return nil, false } -func (tree *avlTree) PutNode(pnode *avlNode) bool { - - pnode.children[0] = nil - pnode.children[1] = nil - // pnode.parent = nil - - if tree.root == nil { - // tree.size++ - tree.root = pnode - return true - } - - for cur, c := tree.root, 0; ; { - c = tree.Compare(pnode.key, cur.key) - if c == -1 { - if cur.children[0] == nil { - // tree.size++ - cur.children[0] = pnode - return true - } - cur = cur.children[0] - } else if c == 1 { - if cur.children[1] == nil { - cur.children[1] = pnode - return true - } - cur = cur.children[1] - } else { - cur.key = pnode.key - cur.value = pnode.value - return false - } - } -} - func (tree *avlTree) Put(key, value interface{}) bool { - if tree.root == nil { + if tree.size == 0 { + tree.size++ tree.root = &avlNode{key: key, value: value} return true } @@ -189,13 +133,23 @@ func (tree *avlTree) Put(key, value interface{}) bool { 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] @@ -207,11 +161,228 @@ func (tree *avlTree) Put(key, value interface{}) bool { } } +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) { @@ -219,6 +390,38 @@ 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) { @@ -231,6 +434,29 @@ func (tree *avlTree) rrotate(cur *avlNode) { 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) { @@ -242,4 +468,221 @@ func (tree *avlTree) lrotate(cur *avlNode) { 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/hashmap.go b/hashmap/hashmap.go index 37a07ee..e580fcb 100644 --- a/hashmap/hashmap.go +++ b/hashmap/hashmap.go @@ -53,8 +53,10 @@ func (hm *HashMap) grow() { hm.table.Traversal(func(cur *avlTree) { if cur != nil { cur.Traversal(func(node *avlNode) bool { - nodelist[i] = node - i++ + if node != nil { + nodelist[i] = node + i++ + } return true }) cur.Clear() @@ -86,12 +88,10 @@ func (hm *HashMap) Put(key, value interface{}) { data[idx] = avlNew(hm.Compare) }) - n := hm.pool.Get() + n := &avlNode{key: key, value: value} if bkt.PutNode(n) { hm.size++ hm.grow() - } else { - hm.pool.Recycling(n) } } diff --git a/hashmap/hashmap_test.go b/hashmap/hashmap_test.go index 14a7318..2e36d7d 100644 --- a/hashmap/hashmap_test.go +++ b/hashmap/hashmap_test.go @@ -31,7 +31,7 @@ func TestCount(t *testing.T) { hm.Put(i, i) } - t.Error(hm.Get(4)) + // t.Error(hm.Get(4)) } func PrintMemUsage() { @@ -52,10 +52,18 @@ var executeCount = 5 var compareSize = 100000 func BenchmarkPut(b *testing.B) { - l := loadTestData() + 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() + for c := 0; c < executeCount; c++ { for i := 0; i < len(l); i++ { v := l[i] @@ -85,13 +93,17 @@ func BenchmarkGoPut(b *testing.B) { } func BenchmarkGet(b *testing.B) { + b.StopTimer() + l := loadTestData() hm := New(HashInt, compare.Int) - b.N = 100000 - for i := 0; i < b.N; i++ { - hm.Put(i, i) + 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) } @@ -102,14 +114,18 @@ func BenchmarkGet(b *testing.B) { func BenchmarkGoGet(b *testing.B) { b.StopTimer() - m := make(map[int]int) - b.N = 100000 - for i := 0; i < b.N; i++ { - m[i] = i + 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 } + b.StartTimer() for i := 0; i < b.N; i++ { - if _, ok := m[i]; !ok { + if _, ok := hm[i]; !ok { } }