少量测试通过版本

This commit is contained in:
huangsimin 2019-03-12 10:54:52 +08:00
commit 7f107bf6c3
10 changed files with 1284 additions and 0 deletions

14
.gitignore vendored Normal file
View File

@ -0,0 +1,14 @@
# ---> Go
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib
# Test binary, build with `go test -c`
*.test
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
*.log
.vscode

21
LICENSE Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) <year> <copyright holders>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:
The above copyright notice and this permission notice (including the next
paragraph) shall be included in all copies or substantial portions of the
Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

2
README.md Normal file
View File

@ -0,0 +1,2 @@
# structure

550
avltree/avltree.go Normal file
View File

@ -0,0 +1,550 @@
package bstree
import (
"github.com/davecgh/go-spew/spew"
"github.com/emirpasic/gods/utils"
)
type Node struct {
children [2]*Node
parent *Node
height int
child int
value interface{}
}
func (n *Node) String() string {
if n == nil {
return "nil"
}
p := "nil"
if n.parent != nil {
p = spew.Sprint(n.parent.value)
}
return spew.Sprint(n.value) + "(" + p + "-" + spew.Sprint(n.child) + "|" + spew.Sprint(n.height) + ")"
}
type AVLTree struct {
root *Node
size int
comparator utils.Comparator
}
func New(comparator utils.Comparator) *AVLTree {
return &AVLTree{comparator: comparator}
}
func (avl *AVLTree) replace(old *Node, newN *Node) {
if old.parent == nil {
setChild(newN, 0, old.children[0])
setChild(newN, 1, old.children[1])
newN.parent = nil
newN.child = -1
newN.height = old.height
avl.root = newN
} else {
setChild(newN, 0, old.children[0])
setChild(newN, 1, old.children[1])
newN.parent = old.parent
newN.child = old.child
newN.height = old.height
old.parent.children[old.child] = newN
}
}
func setChild(p *Node, child int, node *Node) {
p.children[child] = node
if node != nil {
node.child = child
node.parent = p
}
}
func (avl *AVLTree) Remove(v interface{}) *Node {
if n, ok := avl.GetNode(v); ok {
avl.size--
if avl.size == 0 {
avl.root = nil
return n
}
left := getHeight(n.children[0])
right := getHeight(n.children[1])
if left == -1 && right == -1 {
p := n.parent
p.children[n.child] = nil
avl.fixRemoveHeight(p)
return n
}
var cur *Node
if left > right {
cur = n.children[0]
for cur.children[1] != nil {
cur = cur.children[1]
}
cleft := cur.children[0]
cur.parent.children[cur.child] = cleft
if cleft != nil {
cleft.child = cur.child
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[cur.child] = cright
if cright != nil {
cright.child = cur.child
cright.parent = cur.parent
}
}
cparent := cur.parent
avl.replace(n, cur)
// 考虑到刚好替换的节点是 被替换节点的孩子节点的时候, 从自身修复高度
if cparent == n {
avl.fixRemoveHeight(cur)
} else {
avl.fixRemoveHeight(cparent)
}
return n
}
return nil
}
func (avl *AVLTree) Get(v interface{}) (interface{}, bool) {
n, ok := avl.GetNode(v)
if ok {
return n.value, true
}
return n, false
}
func (avl *AVLTree) GetNode(v interface{}) (*Node, bool) {
n := avl.root
for n != nil {
switch c := avl.comparator(v, n.value); c {
case -1:
n = n.children[0]
case 1:
n = n.children[1]
case 0:
return n, true
default:
panic("Get comparator only is allowed in -1, 0, 1")
}
}
return nil, false
}
func (avl *AVLTree) Put(v interface{}) {
avl.size++
node := &Node{value: v}
if avl.size == 1 {
avl.root = node
return
}
cur := avl.root
parent := cur.parent
child := -1
for {
if cur == nil {
parent.children[child] = node
node.parent = parent
node.child = child
if node.parent.height == 0 {
avl.fixPutHeight(node.parent)
}
return
}
parent = cur
c := avl.comparator(node.value, cur.value)
if c > -1 { // right
child = 1
cur = cur.children[child]
} else {
child = 0
cur = cur.children[child]
}
}
}
func (avl *AVLTree) String() string {
if avl.size == 0 {
return ""
}
str := "AVLTree" + "\n"
output(avl.root, "", true, &str)
return str
}
func (avl *AVLTree) debugString() string {
if avl.size == 0 {
return ""
}
str := "AVLTree" + "\n"
outputfordebug(avl.root, "", true, &str)
return str
}
func (avl *AVLTree) TraversalBreadth() (result []interface{}) {
var traverasl func(cur *Node)
traverasl = func(cur *Node) {
if cur == nil {
return
}
result = append(result, cur.value)
traverasl(cur.children[0])
traverasl(cur.children[1])
}
traverasl(avl.root)
return
}
func (avl *AVLTree) TraversalDepth(leftright int) (result []interface{}) {
if leftright < 0 {
var traverasl func(cur *Node)
traverasl = func(cur *Node) {
if cur == nil {
return
}
traverasl(cur.children[0])
result = append(result, cur.value)
traverasl(cur.children[1])
}
traverasl(avl.root)
} else {
var traverasl func(cur *Node)
traverasl = func(cur *Node) {
if cur == nil {
return
}
traverasl(cur.children[1])
result = append(result, cur.value)
traverasl(cur.children[0])
}
traverasl(avl.root)
}
return
}
func (avl *AVLTree) lrrotate(cur *Node) *Node {
r := cur.children[1]
rl := r.children[0]
if cur.parent == nil {
avl.root = rl
rl.parent = nil
} else {
setChild(cur.parent, cur.child, rl)
}
rll := rl.children[0]
rlr := rl.children[1]
setChild(cur, 1, rll)
setChild(r, 0, rlr)
setChild(rl, 0, cur)
setChild(rl, 1, r)
cur.height = getMaxChildrenHeight(cur) + 1
r.height = getMaxChildrenHeight(r) + 1
rl.height = getMaxChildrenHeight(rl) + 1
return rl
}
func (avl *AVLTree) rlrotate(cur *Node) *Node {
l := cur.children[0]
lr := l.children[1]
if cur.parent == nil {
avl.root = lr
lr.parent = nil
} else {
setChild(cur.parent, cur.child, lr)
}
lrr := lr.children[1]
lrl := lr.children[0]
setChild(cur, 0, lrr)
setChild(l, 1, lrl)
setChild(lr, 1, cur)
setChild(lr, 0, l)
cur.height = getMaxChildrenHeight(cur) + 1
l.height = getMaxChildrenHeight(l) + 1
lr.height = getMaxChildrenHeight(lr) + 1
return lr
}
func (avl *AVLTree) rrotate(cur *Node) *Node {
l := cur.children[0]
setChild(cur, 0, l.children[1])
l.parent = cur.parent
if cur.parent != nil {
cur.parent.children[cur.child] = l
} else {
avl.root = l
}
l.child = cur.child
l.children[1] = cur
cur.child = 1
cur.parent = l
cur.height = getMaxChildrenHeight(cur) + 1
l.height = getMaxChildrenHeight(l) + 1
return l
}
func (avl *AVLTree) lrotate(cur *Node) *Node {
r := cur.children[1]
// 右左节点 链接 当前的右节点
setChild(cur, 1, r.children[0])
// 设置 需要旋转的节点到当前节点的 链条
r.parent = cur.parent
if cur.parent != nil {
cur.parent.children[cur.child] = r
} else {
avl.root = r
}
r.child = cur.child
// 当前节点旋转到 左边的 链条
r.children[0] = cur
cur.child = 0
cur.parent = r
// 修复改动过的节点高度 先从低开始到高
cur.height = getMaxChildrenHeight(cur) + 1
r.height = getMaxChildrenHeight(r) + 1
return r
}
func getMaxAndChildrenHeight(cur *Node) (h1, h2, maxh int) {
h1 = getHeight(cur.children[0])
h2 = getHeight(cur.children[1])
if h1 > h2 {
maxh = h1
return
}
maxh = h2
return
}
func getMaxChildrenHeight(cur *Node) int {
h1 := getHeight(cur.children[0])
h2 := getHeight(cur.children[1])
if h1 > h2 {
return h1
}
return h2
}
func getHeight(cur *Node) int {
if cur == nil {
return -1
}
return cur.height
}
func (avl *AVLTree) fixRemoveHeight(cur *Node) {
for {
lefth, rigthh, lrmax := getMaxAndChildrenHeight(cur)
// 判断当前节点是否有变化, 如果没变化的时候, 不需要往上修复
isBreak := false
if cur.height == lrmax+1 {
isBreak = true
} else {
cur.height = lrmax + 1
}
// 计算高度的差值 绝对值大于2的时候需要旋转
diff := lefth - rigthh
if diff < -1 {
r := cur.children[1] // 根据左旋转的右边节点的子节点 左右高度选择旋转的方式
if getHeight(r.children[0]) > getHeight(r.children[1]) {
cur = avl.lrrotate(cur)
} else {
cur = avl.lrotate(cur)
}
} else if diff > 1 {
l := cur.children[0]
if getHeight(l.children[1]) > getHeight(l.children[0]) {
cur = avl.rlrotate(cur)
} else {
cur = avl.rrotate(cur)
}
} else {
if isBreak {
return
}
}
if cur.parent == nil {
return
}
cur = cur.parent
}
}
func (avl *AVLTree) fixPutHeight(cur *Node) {
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]) {
cur = avl.lrrotate(cur)
} else {
cur = avl.lrotate(cur)
}
} else if diff > 1 {
l := cur.children[0]
if getHeight(l.children[1]) > getHeight(l.children[0]) {
cur = avl.rlrotate(cur)
} else {
cur = avl.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 output(node *Node, 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 *Node, 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.child) + "|" + 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)
}
}

316
avltree/avltree_test.go Normal file
View File

@ -0,0 +1,316 @@
package bstree
import (
"testing"
"github.com/emirpasic/gods/trees/redblacktree"
"github.com/emirpasic/gods/trees/avltree"
"github.com/davecgh/go-spew/spew"
"github.com/Pallinder/go-randomdata"
"github.com/emirpasic/gods/utils"
)
func TestRotate(t *testing.T) {
avl := New(utils.IntComparator)
content := ""
for i := 0; i < 10; i++ {
v := randomdata.Number(0, 1000)
content += spew.Sprint(v) + " "
avl.Put(v)
}
t.Error(content)
src := avl.String()
t.Error(src)
lsrc := avl.String()
t.Error(lsrc)
// rrotate(&avl.root)
rsrc := avl.String()
t.Error(rsrc)
if src == rsrc {
t.Error("src == rsrc")
}
}
func TestPutStable(t *testing.T) {
avl := New(utils.IntComparator)
for _, v := range []int{7, 14, 15, 20, 30, 21} {
t.Error(v)
avl.Put(v)
t.Error(avl.debugString())
}
// avl = New(utils.IntComparator)
// for _, v := range []int{88, 77, 80} {
// avl.Put(v)
// t.Error(avl.String())
// }
}
func TestDiffPutRandom(t *testing.T) {
avl := New(utils.IntComparator)
godsavl := avltree.NewWithIntComparator()
content := ""
m := make(map[int]int)
for i := 0; len(m) < 10; i++ {
v := randomdata.Number(0, 10000)
if _, ok := m[v]; !ok {
m[v] = v
content += spew.Sprint(v) + " "
t.Error(v)
avl.Put(v)
t.Error(avl.String())
godsavl.Put(v, v)
}
}
t.Error(godsavl.String())
}
func TestPutComparatorRandom(t *testing.T) {
for n := 0; n < 1000000; n++ {
avl := New(utils.IntComparator)
godsavl := avltree.NewWithIntComparator()
content := ""
m := make(map[int]int)
for i := 0; len(m) < 10; i++ {
v := randomdata.Number(0, 65535)
if _, ok := m[v]; !ok {
m[v] = v
content += spew.Sprint(v) + " "
// t.Error(v)
avl.Put(v)
// t.Error(avl.String())
godsavl.Put(v, v)
}
}
if avl.String() != godsavl.String() {
t.Error(content)
break
}
}
// t.Error(content)
// t.Error(avl.String())
// t.Error(godsavl.String())
// t.Error(avl.String() == godsavl.String())
}
func TestGet(t *testing.T) {
avl := New(utils.IntComparator)
for i := 0; i < 15; i++ {
avl.Put(randomdata.Number(0, 1000))
}
t.Error(avl.String())
t.Error(avl.Get(500))
}
func TestRemoveAll(t *testing.T) {
for c := 0; c < 10000; c++ {
// f, _ := os.OpenFile("./out.log", os.O_TRUNC|os.O_CREATE|os.O_RDWR, 0666)
// log.SetOutput(f)
avl := New(utils.IntComparator)
var l []int
for i := 0; i < 100; i++ {
v := randomdata.Number(0, 100000)
l = append(l, v)
avl.Put(v)
}
// defer func() {
// if err := recover(); err != nil {
// panic(avl.String())
// }
// }()
// log.Println(avl.TraversalBreadth())
for i := 0; i < 100; i++ {
// log.Println(l[i])
// log.Println(avl.debugString())
avl.Remove(l[i])
}
}
}
func TestRemove(t *testing.T) {
// avl := New(utils.IntComparator)
// var l []int
// for _, v := range []int{86, 97, 9, 61, 37, 45, 97, 43, 95, 8} {
// l = append(l, v)
// avl.Put(v)
// }
// for i := 0; i < len(l); i++ {
// // log.Println(i)
// log.Println("begin", l[i], avl.debugString())
// avl.Remove(l[i])
// log.Println("end", l[i], avl.debugString())
// }
ALL:
for N := 0; N < 500000; N++ {
avl := New(utils.IntComparator)
gods := avltree.NewWithIntComparator()
var l []int
m := make(map[int]int)
for i := 0; len(l) < 10; i++ {
v := randomdata.Number(0, 100)
if _, ok := m[v]; !ok {
l = append(l, v)
m[v] = v
avl.Put(v)
gods.Put(v, v)
}
}
src1 := avl.String()
src2 := gods.String()
for i := 0; i < 10; i++ {
avl.Remove(l[i])
gods.Remove(l[i])
if spew.Sprint(gods.Values()) != spew.Sprint(avl.TraversalDepth(-1)) && avl.size != 0 {
// if gods.String() != avl.String() && gods.Size() != 0 && avl.size != 0 {
t.Error(src1)
t.Error(src2)
t.Error(avl.debugString())
t.Error(gods.String())
t.Error(l[i])
// t.Error(avl.TraversalDepth(-1))
// t.Error(gods.Values())
break ALL
}
}
}
}
const PutCompartorSize = 300000
const NumberMax = 60000000
func BenchmarkRemove(b *testing.B) {
avl := New(utils.IntComparator)
b.N = PutCompartorSize
var l []int
for i := 0; i < b.N; i++ {
v := randomdata.Number(0, NumberMax)
l = append(l, v)
avl.Put(v)
}
b.ResetTimer()
b.StartTimer()
for i := 0; i < b.N; i++ {
avl.Remove(l[i])
}
}
func BenchmarkGodsRemove(b *testing.B) {
avl := avltree.NewWithIntComparator()
b.N = PutCompartorSize
var l []int
for i := 0; i < b.N; i++ {
v := randomdata.Number(0, NumberMax)
l = append(l, v)
avl.Put(v, v)
}
b.ResetTimer()
b.StartTimer()
for i := 0; i < b.N; i++ {
avl.Remove(l[i])
}
}
func BenchmarkGet(b *testing.B) {
avl := New(utils.IntComparator)
b.N = PutCompartorSize
for i := 0; i < b.N/2; i++ {
avl.Put(randomdata.Number(0, NumberMax))
}
b.ResetTimer()
b.StartTimer()
for i := 0; i < b.N; i++ {
avl.Get(randomdata.Number(0, NumberMax))
}
}
func BenchmarkGodsRBGet(b *testing.B) {
rb := redblacktree.NewWithIntComparator()
b.N = PutCompartorSize
for i := 0; i < b.N/2; i++ {
rb.Put(randomdata.Number(0, NumberMax), i)
}
b.ResetTimer()
b.StartTimer()
for i := 0; i < b.N; i++ {
rb.Get(randomdata.Number(0, NumberMax))
}
}
func BenchmarkGodsAvlGet(b *testing.B) {
rb := avltree.NewWithIntComparator()
b.N = PutCompartorSize
for i := 0; i < b.N/2; i++ {
rb.Put(randomdata.Number(0, NumberMax), i)
}
b.ResetTimer()
b.StartTimer()
for i := 0; i < b.N; i++ {
rb.Get(randomdata.Number(0, NumberMax))
}
}
func BenchmarkPut(b *testing.B) {
avl := New(utils.IntComparator)
b.N = PutCompartorSize
for i := 0; i < b.N; i++ {
avl.Put(randomdata.Number(0, NumberMax))
}
}
func BenchmarkGodsRBPut(b *testing.B) {
rb := redblacktree.NewWithIntComparator()
b.N = PutCompartorSize
for i := 0; i < b.N; i++ {
rb.Put(randomdata.Number(0, NumberMax), i)
}
}
func BenchmarkGodsPut(b *testing.B) {
avl := avltree.NewWithIntComparator()
b.N = PutCompartorSize
for i := 0; i < b.N; i++ {
avl.Put(randomdata.Number(0, NumberMax), i)
}
}

87
priority_list/iterator.go Normal file
View File

@ -0,0 +1,87 @@
package plist
type Iterator struct {
pl *PriorityList
cur *Node
}
func (iter *Iterator) Value() interface{} {
return iter.cur.value
}
func (iter *Iterator) Prev() bool {
if iter.cur == iter.pl.head {
return false
}
iter.cur = iter.cur.prev
return iter.cur != iter.pl.head
}
func (iter *Iterator) Next() bool {
if iter.cur == iter.pl.tail {
return false
}
iter.cur = iter.cur.next
return iter.cur != iter.pl.tail
}
func (iter *Iterator) MoveToHead() {
iter.cur = iter.pl.head
}
func (iter *Iterator) MoveToTail() {
iter.cur = iter.pl.tail
}
type CircularIterator struct {
pl *PriorityList
cur *Node
}
func (iter *CircularIterator) Value() interface{} {
return iter.cur.value
}
func (iter *CircularIterator) Prev() bool {
if iter.pl.size == 0 {
return false
}
if iter.cur == iter.pl.head {
iter.cur = iter.pl.tail.prev
return true
}
iter.cur = iter.cur.prev
if iter.cur == iter.pl.head {
iter.cur = iter.pl.tail.prev
}
return true
}
func (iter *CircularIterator) Next() bool {
if iter.pl.size == 0 {
return false
}
if iter.cur == iter.pl.tail {
iter.cur = iter.pl.head.next
return true
}
iter.cur = iter.cur.next
if iter.cur == iter.pl.tail {
iter.cur = iter.pl.head.next
}
return true
}
func (iter *CircularIterator) MoveToHead() {
iter.cur = iter.pl.head
}
func (iter *CircularIterator) MoveToTail() {
iter.cur = iter.pl.tail
}

View File

@ -0,0 +1,138 @@
package plist
import (
"strings"
"github.com/davecgh/go-spew/spew"
"github.com/emirpasic/gods/utils"
)
type Node struct {
prev, next *Node
value interface{}
}
type PriorityList struct {
head, tail *Node
size int
comparator utils.Comparator
}
func New(compartor utils.Comparator) *PriorityList {
pl := &PriorityList{head: &Node{}, tail: &Node{}, size: 0, comparator: compartor}
pl.head.next = pl.tail
pl.tail.prev = pl.head
return pl
}
func (pl *PriorityList) String() string {
content := ""
cur := pl.head.next
for ; cur != pl.tail; cur = cur.next {
content += spew.Sprint(cur.value) + " "
}
content = strings.TrimRight(content, " ")
return content
}
func (pl *PriorityList) RString() string {
content := ""
cur := pl.tail.prev
for ; cur != pl.head; cur = cur.prev {
content += spew.Sprint(cur.value) + " "
}
content = strings.TrimRight(content, " ")
return content
}
func (pl *PriorityList) Iterator() *Iterator {
return &Iterator{pl: pl, cur: pl.head}
}
func (pl *PriorityList) CircularIterator() *CircularIterator {
return &CircularIterator{pl: pl, cur: pl.head}
}
func (pl *PriorityList) Push(pvalue interface{}) {
pl.size++
pnode := &Node{value: pvalue}
if pl.size == 1 {
pl.head.next = pnode
pl.tail.prev = pnode
pnode.prev = pl.head
pnode.next = pl.tail
return
}
cur := pl.head
for ; cur.next != pl.tail; cur = cur.next {
if pl.comparator(pvalue, cur.next.value) > 0 {
cnext := cur.next
cur.next = pnode
cnext.prev = pnode
pnode.prev = cur
pnode.next = cnext
return
}
}
cur.next = pnode
pnode.prev = cur
pnode.next = pl.tail
pl.tail.prev = pnode
}
func (pl *PriorityList) Get(idx int) interface{} {
return pl.GetNode(idx).value
}
func (pl *PriorityList) GetNode(idx int) *Node {
if idx >= 0 {
cur := pl.head.next
for i := 0; cur != pl.tail; i++ {
if i == idx {
return cur
}
cur = cur.next
}
} else {
cur := pl.tail.prev
for i := -1; cur != pl.head; i-- {
if i == idx {
return cur
}
cur = cur.prev
}
}
return nil
}
func (pl *PriorityList) RemoveWithIndex(idx int) {
pl.Remove(pl.GetNode(idx))
}
func (pl *PriorityList) Remove(node *Node) {
prev := node.prev
next := node.next
prev.next = next
next.prev = prev
node.prev = nil
node.next = nil
pl.size--
}
func (pl *PriorityList) Values() []interface{} {
values := make([]interface{}, pl.size, pl.size)
for i, cur := 0, pl.head.next; cur != pl.tail; i, cur = i+1, cur.next {
values[i] = cur.value
}
return values
}

View File

@ -0,0 +1,148 @@
package plist
import (
"testing"
"github.com/emirpasic/gods/utils"
)
func TestInsert(t *testing.T) {
pl := New(utils.IntComparator)
for i := 0; i < 10; i++ {
pl.Push(i)
}
if pl.size != 10 {
t.Error(pl.size)
}
if pl.String() != "9 8 7 6 5 4 3 2 1 0" {
t.Error(pl.String())
}
if pl.RString() != "0 1 2 3 4 5 6 7 8 9" {
t.Error(pl.RString())
}
for i := 0; i < 10; i++ {
pl.Push(i)
}
if pl.String() != "9 9 8 8 7 7 6 6 5 5 4 4 3 3 2 2 1 1 0 0" {
t.Error(pl.String())
}
if pl.RString() != "0 0 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9" {
t.Error(pl.RString())
}
}
func TestIterator(t *testing.T) {
pl := New(utils.IntComparator)
for i := 0; i < 10; i++ {
pl.Push(i)
}
iter := pl.Iterator()
for i := 0; iter.Next(); i++ {
if iter.Value() != 9-i {
t.Error("iter.Next() ", iter.Value(), "is not equal ", 9-i)
}
}
if iter.cur != iter.pl.tail {
t.Error("current point is not equal tail ", iter.pl.tail)
}
for i := 0; iter.Prev(); i++ {
if iter.Value() != i {
t.Error("iter.Prev() ", iter.Value(), "is not equal ", i)
}
}
}
func TestCircularIterator(t *testing.T) {
pl := New(utils.IntComparator)
for i := 0; i < 10; i++ {
pl.Push(i)
}
iter := pl.CircularIterator()
for i := 0; i != 10; i++ {
iter.Next()
if iter.Value() != 9-i {
t.Error("iter.Next() ", iter.Value(), "is not equal ", 9-i)
}
}
if iter.cur != iter.pl.tail.prev {
t.Error("current point is not equal tail ", iter.pl.tail.prev)
}
if iter.Next() {
if iter.Value() != 9 {
t.Error("iter.Value() != ", iter.Value())
}
}
iter.MoveToTail()
for i := 0; i != 10; i++ {
iter.Prev()
if iter.Value() != i {
t.Error("iter.Prev() ", iter.Value(), "is not equal ", i)
}
}
if iter.cur != iter.pl.head.next {
t.Error("current point is not equal tail ", iter.pl.tail.prev)
}
if iter.Prev() {
if iter.Value() != 0 {
t.Error("iter.Value() != ", iter.Value())
}
}
}
func TestGet(t *testing.T) {
pl := New(utils.IntComparator)
for i := 0; i < 10; i++ {
pl.Push(i)
}
for _, v := range []int{0, 9, 5, 7} {
if pl.Get(v) != (9 - v) {
t.Error(v, "Get == ", pl.Get(v))
}
}
func() {
defer func() {
if err := recover(); err == nil {
t.Error("out index, but is not error")
}
}()
pl.Get(10)
}()
}
func TestRemove(t *testing.T) {
pl := New(utils.IntComparator)
for i := 0; i < 10; i++ {
pl.Push(i)
}
pl.RemoveWithIndex(0)
if pl.Get(0).(int) != 8 {
t.Error(pl.Get(0))
}
pl.RemoveWithIndex(-1)
if pl.Get(-1).(int) != 1 {
t.Error(pl.Get(-1))
}
}

View File

@ -0,0 +1,4 @@
package pqueue
type Iterator struct {
}

View File

@ -0,0 +1,4 @@
package pqueue
type PriorityQueue struct {
}