From 0bfa7f1317487d9e0d19c1ad77c5051772c0a332 Mon Sep 17 00:00:00 2001 From: eson <474420502@qq.com> Date: Tue, 23 Apr 2019 09:39:04 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E4=B8=80=E4=B8=AA=E9=93=BE?= =?UTF-8?q?=E8=A1=A8,=20=E5=92=8C=20TODO:=20hashmap=20=E7=BC=93=E5=AD=98?= =?UTF-8?q?=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hashmap/avlkeydup.go | 598 +++++-------------------------------------- list/list.go | 108 ++++++++ list/list_test.go | 87 +++++++ 3 files changed, 258 insertions(+), 535 deletions(-) create mode 100644 list/list.go create mode 100644 list/list_test.go diff --git a/hashmap/avlkeydup.go b/hashmap/avlkeydup.go index 2fba6a3..fa53109 100644 --- a/hashmap/avlkeydup.go +++ b/hashmap/avlkeydup.go @@ -2,20 +2,18 @@ package hashmap import ( "474420502.top/eson/structure/compare" - "github.com/davecgh/go-spew/spew" ) type avlNode struct { children [2]*avlNode - parent *avlNode - height int + hash uint key, value interface{} } type avlTree struct { - root *avlNode - size int - Compare compare.Compare + root *avlNode + lsize, rsize int + Compare compare.Compare } func avlNew(Compare compare.Compare) *avlTree { @@ -23,78 +21,78 @@ func avlNew(Compare compare.Compare) *avlTree { } func (tree *avlTree) Clear() { - tree.size = 0 + tree.lsize, tree.rsize = 0, 0 tree.root = nil } -func (tree *avlTree) Size() int { - return tree.size -} +// 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 cur.value, true +// } - return nil, false -} +// return nil, false +// } func (tree *avlTree) Get(key interface{}) (interface{}, bool) { n, ok := tree.GetNode(key) @@ -123,15 +121,13 @@ func (tree *avlTree) GetNode(key interface{}) (*avlNode, bool) { func (tree *avlTree) PutNode(pnode *avlNode) bool { - pnode.height = 0 pnode.children[0] = nil pnode.children[1] = nil // pnode.parent = nil - if tree.size == 0 { - tree.size++ + if tree.root == nil { + // tree.size++ tree.root = pnode - pnode.parent = nil return true } @@ -139,23 +135,14 @@ func (tree *avlTree) PutNode(pnode *avlNode) bool { c = tree.Compare(pnode.key, cur.key) if c == -1 { if cur.children[0] == nil { - tree.size++ + // tree.size++ cur.children[0] = pnode - 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] = pnode - cur.children[1].parent = cur - if cur.height == 0 { - tree.fixPutHeight(cur) - } return true } cur = cur.children[1] @@ -169,8 +156,7 @@ func (tree *avlTree) PutNode(pnode *avlNode) bool { func (tree *avlTree) Put(key, value interface{}) bool { - if tree.size == 0 { - tree.size++ + if tree.root == nil { tree.root = &avlNode{key: key, value: value} return true } @@ -179,23 +165,13 @@ 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,187 +183,11 @@ func (tree *avlTree) Put(key, value interface{}) bool { } } -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(node *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) { @@ -395,38 +195,6 @@ 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) { @@ -439,29 +207,6 @@ 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) { @@ -473,221 +218,4 @@ 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/list/list.go b/list/list.go new file mode 100644 index 0000000..6c1b29c --- /dev/null +++ b/list/list.go @@ -0,0 +1,108 @@ +package list + +type Node struct { + next *Node + value interface{} +} + +func (node *Node) Value() interface{} { + return node.value +} + +type List struct { + head *Node + size uint +} + +func New() *List { + return &List{} +} + +func (l *List) Size() uint { + return l.size +} + +func (l *List) Push(v interface{}) { + l.size++ + if l.head == nil { + l.head = &Node{value: v} + return + } + l.head = &Node{value: v, next: l.head} +} + +func (l *List) PushNode(n *Node) { + l.size++ + if l.head == nil { + l.head = n + return + } + + n.next = l.head + l.head = n +} + +func (l *List) Pop() (result interface{}, found bool) { + if n, ok := l.PopNode(); ok { + return n.value, ok + } + return nil, false +} + +func (l *List) PopNode() (result *Node, found bool) { + if l.head == nil { + return nil, false + } + + result = l.head + found = true + l.head = result.next + result.next = nil + l.size-- + return +} + +func (l *List) Remove(idx uint) (result *Node, found bool) { + if l.size == 0 { + return nil, false + } + + if idx == 0 { + result = l.head + found = true + l.head = result.next + result.next = nil + l.size-- + return + } + + for cur := l.head; cur.next != nil; cur = cur.next { + if idx == 1 { + l.size-- + result = cur.next + found = true + cur.next = result.next + result.next = nil + return + } + idx-- + } + + return nil, false +} + +func (l *List) Values() (result []interface{}) { + l.Traversal(func(cur *Node) bool { + result = append(result, cur.value) + return true + }) + return +} + +func (l *List) Traversal(every func(*Node) bool) { + for cur := l.head; cur != nil; cur = cur.next { + if !every(cur) { + break + } + } +} diff --git a/list/list_test.go b/list/list_test.go new file mode 100644 index 0000000..da0ce10 --- /dev/null +++ b/list/list_test.go @@ -0,0 +1,87 @@ +package list + +import ( + "testing" + + "github.com/davecgh/go-spew/spew" +) + +func TestPush(t *testing.T) { + l := New() + for i := 0; i < 5; i++ { + l.Push(i) + } + var result string + result = spew.Sprint(l.Values()) + if result != "[4 3 2 1 0]" { + t.Error(result) + } + + l.Push(0) + result = spew.Sprint(l.Values()) + if result != "[0 4 3 2 1 0]" { + t.Error(result) + } +} + +func TestPop(t *testing.T) { + l := New() + for i := 0; i < 5; i++ { + l.Push(i) + } + + if v, ok := l.Pop(); ok { + if v != 4 { + t.Error(v) + } + } else { + t.Error("Pop should ok, but is not ok") + } + + var result string + result = spew.Sprint(l.Values()) + if result != "[3 2 1 0]" { + t.Error(result) + } + + for i := 3; l.Size() != 0; i-- { + if v, ok := l.Pop(); ok { + if v != i { + t.Error(i, v, "is not equals") + } + } else { + t.Error("Pop should ok, but is not ok", i) + } + } + + l.Push(0) + result = spew.Sprint(l.Values()) + if result != "[0]" { + t.Error(result) + } + + if l.Size() != 1 { + t.Error("l.Size() == 1, but is error, size = ", l.Size()) + } +} + +func TestRemove(t *testing.T) { + l := New() + for i := 0; i < 5; i++ { + l.Push(i) + } + + for i := 0; i < 5; i++ { + if n, ok := l.Remove(0); ok { + if n.Value() != 4-i { + t.Error(n) + } + } else { + t.Error("Pop should ok, but is not ok", i) + } + } + + if l.Size() != 0 { + t.Error("l.Size() == 0, but is error, size = ", l.Size()) + } +}