2 Commits

Author SHA1 Message Date
huangsimin
b71ba9ebdd 初步测试, 性能不如添加索引的链表 2019-02-13 11:54:07 +08:00
huangsimin
05bcac44ef 退回最简单的优先链表 2019-02-13 10:52:08 +08:00
8 changed files with 738 additions and 303 deletions

View File

@@ -0,0 +1,249 @@
package clinked
import (
"log"
"strings"
"github.com/davecgh/go-spew/spew"
)
// CNode 循环链表 三色标记 不确定是否会清除循环引用, 网上说会
type CNode struct {
value interface{}
prev *CNode
next *CNode
}
// GetValue 获取到Node的值
func (node *CNode) GetValue() interface{} {
return node.value
}
// SetValue 获取到Node的值
func (node *CNode) SetValue(value interface{}) {
node.value = value
}
// CircularLinked 循环链表
type CircularLinked struct {
cursor *CNode
head *CNode
tail *CNode
size uint64
}
// NewCircularLinked create a CircularLinked
func NewCircularLinked(values ...interface{}) *CircularLinked {
list := &CircularLinked{}
if len(values) > 0 {
list.Append(values...)
}
return list
}
// Head 链表的首
func (list *CircularLinked) Head() *CNode {
return list.head
}
// Tail 链表的首
func (list *CircularLinked) Tail() *CNode {
return list.tail
}
// Cursor get current Cursor
func (list *CircularLinked) Cursor() *CNode {
if list.cursor == nil {
list.cursor = list.head
}
return list.cursor
}
// MoveNext get next Cursor
func (list *CircularLinked) MoveNext() *CNode {
if list.cursor == nil {
list.cursor = list.head
}
list.cursor = list.cursor.next
return list.cursor
}
// MovePrev get prev Cursor
func (list *CircularLinked) MovePrev() *CNode {
if list.cursor == nil {
list.cursor = list.head
}
list.cursor = list.cursor.prev
return list.cursor
}
// CursorToHead cursor move to head
func (list *CircularLinked) CursorToHead() *CNode {
list.cursor = list.head
return list.cursor
}
// CursorToTail cursor move to tail
func (list *CircularLinked) CursorToTail() *CNode {
list.cursor = list.tail
return list.cursor
}
// GetLoopValues 获取从头到尾的值
func (list *CircularLinked) GetLoopValues() []*CNode {
var result []*CNode
if list.head != nil {
result = append(result, list.head)
for cur := list.head.next; cur != list.head; cur = cur.next {
result = append(result, cur)
}
}
return result
}
// Append a value (one or more) at the end of the list (same as Append())
func (list *CircularLinked) Append(values ...interface{}) {
for _, value := range values {
node := &CNode{value: value}
if list.size == 0 {
list.head = node
list.tail = node
node.next = node
node.prev = node
} else {
list.tail.next = node
node.next = list.head
node.prev = list.tail
list.tail = node
}
list.size++
}
}
// Remove 移除一些节点
func (list *CircularLinked) Remove(node *CNode) {
switch list.size {
case 0:
list.errorNotInList(node)
case 1:
if list.head == node {
list.head = nil
list.tail = nil
node.next = nil
node.prev = nil
list.cursor = nil
list.size--
} else {
list.errorNotInList(node)
}
case 2:
node.prev = nil
node.next = nil
switch node {
case list.head:
list.head = list.tail
list.tail.prev = list.head
list.head.next = list.tail
list.cursor = list.head
list.size--
case list.tail:
list.tail = list.head
list.tail.prev = list.head
list.head.next = list.tail
list.cursor = list.head
list.size--
default:
list.errorNotInList(node)
}
default:
switch node {
case list.head:
_, next := list.cutAndSplice(node)
list.size--
list.head = next
if list.cursor == node {
list.cursor = next
}
case list.tail:
prev, _ := list.cutAndSplice(node)
list.size--
list.tail = prev
if list.cursor == node {
list.cursor = prev
}
default:
_, next := list.cutAndSplice(node)
list.size--
if list.cursor == node {
list.cursor = next
}
}
}
}
// LookCursor for list show
func (list *CircularLinked) LookCursor() string {
cursor := list.Cursor()
content := "->["
cur := list.head
if list.size != 0 {
for size := uint64(0); size < list.size; size++ {
if cursor == cur {
content += "(" + spew.Sprint(cur.value) + ")" + ", "
} else {
content += spew.Sprint(cur.value) + ", "
}
cur = cur.next
}
}
content = strings.TrimRight(content, ", ")
showlen := len(content)
if showlen >= 64 {
showlen = 64
}
content += "]" + content[0:showlen] + " ..."
return content
}
// Clear for list show
func (list *CircularLinked) Clear() {
if list.size != 0 {
list.head.prev = nil
list.tail.next = nil
list.head = nil
list.tail = nil
list.cursor = nil
list.size = 0
}
}
// Size for list show
func (list *CircularLinked) Size() uint64 {
return list.size
}
func (list *CircularLinked) errorNotInList(node *CNode) {
log.Println("the node value ", spew.Sprint(node), " is not in list")
}
// cutAndSplice (不考虑边界情况)
func (list *CircularLinked) cutAndSplice(node *CNode) (prev, next *CNode) {
prev = node.prev
next = node.next
prev.next = next
next.prev = prev
node.prev = nil
node.next = nil
return prev, next
}

View File

@@ -0,0 +1,65 @@
package clinked
import "testing"
func TestCircularLinkedLookUp(t *testing.T) {
cl := NewCircularLinked(1, 2, 3, 4, 5, 6)
if !(cl.head.value.(int) == 1 && cl.tail.value.(int) == 6) {
t.Error(cl.LookCursor())
}
cl = NewCircularLinked(6, 2, 3, 4, 5, 1)
if !(cl.head.value.(int) == 6 && cl.tail.value.(int) == 1) {
t.Error("New List is error:", cl.LookCursor())
}
if cl.MoveNext().value.(int) != 2 {
t.Error("CursorNext error:", cl.LookCursor())
}
cl = NewCircularLinked(0, 1, 2, 3, 4, 5)
for i := 0; i < 6; i++ {
if cl.Cursor().value.(int) != i {
t.Error("CursorNext error:", cl.LookCursor())
}
cl.MoveNext()
}
for i := 0; i < 6; i++ {
if cl.Cursor().value.(int) != i {
t.Error("CursorNext loop error:", cl.LookCursor())
}
cl.MoveNext()
}
cl = NewCircularLinked(6, 2, 3, 4, 5, 1)
cl.Remove(cl.Cursor())
if cl.Cursor().value != 2 {
t.Error("Remove Head is error", cl.LookCursor())
}
cl.Remove(cl.CursorToTail())
if cl.Cursor().value != 5 {
t.Error("Remove CursorToTail is error", cl.LookCursor())
}
cl.Remove(cl.CursorToHead())
if cl.Cursor().value != 3 {
t.Error("Remove CursorToHead is error", cl.LookCursor())
}
limitCount := 0
for cl.Size() > 0 {
cl.Remove(cl.Cursor())
limitCount++
if limitCount >= 10 {
t.Error("Not Clear", cl.LookCursor())
break
}
}
cl.Remove(cl.CursorToHead()) // nil is not in list is success!
if cl.head != nil || cl.tail != nil || cl.cursor != nil {
t.Error("Remove Boundary error")
}
}

View File

@@ -1,70 +0,0 @@
package plist
type Iterator struct {
pl *PriorityList
cur *Node
}
func (iter *Iterator) Value() interface{} {
return iter.cur.Value
}
func (iter *Iterator) RingNext() bool {
if iter.pl.size == 0 {
return false
}
iter.cur = iter.cur.next
if iter.cur == iter.pl.tail {
iter.cur = iter.pl.head.next
}
return true
}
func (iter *Iterator) Next() bool {
if iter.cur == iter.pl.tail {
return false
}
if iter.cur.next == iter.pl.tail {
iter.cur = iter.cur.next
return false
}
iter.cur = iter.cur.next
return true
}
func (iter *Iterator) RingPrev() bool {
if iter.pl.size == 0 {
return false
}
iter.cur = iter.cur.prev
if iter.cur == iter.pl.head {
iter.cur = iter.pl.tail.prev
}
return true
}
func (iter *Iterator) Prev() bool {
if iter.cur == iter.pl.head {
return false
}
if iter.cur.prev == iter.pl.head {
iter.cur = iter.cur.prev
return false
}
iter.cur = iter.cur.prev
return true
}
func (iter *Iterator) MoveHead() {
iter.cur = iter.pl.head
}
func (iter *Iterator) MoveTail() {
iter.cur = iter.pl.tail
}

View File

@@ -0,0 +1,18 @@
package plist
// NodeInt plist 现成的Int节点, 可以作为例子
type NodeInt struct {
Node
}
// Compare plist 现成的Int节点Compare覆盖
func (fl *NodeInt) Compare(v INode) bool {
return fl.GetValue().(int) > v.GetValue().(int)
}
// NewNodeInt plist 现成的Int节点, New一个NodeInt
func NewNodeInt(v int) (fl *NodeInt) {
fl = new(NodeInt)
fl.SetValue(v)
return fl
}

View File

@@ -2,7 +2,6 @@ package plist
import (
"github.com/davecgh/go-spew/spew"
"github.com/emirpasic/gods/utils"
)
// INode 比较的必须继承的接口
@@ -22,18 +21,59 @@ type INode interface {
// Node 优先链表的节点
type Node struct {
next, prev *Node
INode
prev, next INode
// isrelease bool
Value interface{}
value interface{}
}
// NewNode 创建一个PriorityList 节点
func NewNode(v interface{}) *Node {
n := new(Node)
n.SetValue(v)
return n
}
// GetValue 获取值
func (node *Node) GetValue() interface{} {
return node.value
}
// SetValue 设置值
func (node *Node) SetValue(v interface{}) {
node.value = v
}
// GetPrev 获取left值
func (node *Node) GetPrev() INode {
return node.prev
}
// SetPrev 设置left值
func (node *Node) SetPrev(n INode) {
node.prev = n
}
// GetNext 设置right值
func (node *Node) GetNext() INode {
return node.next
}
// SetNext 获取left值
func (node *Node) SetNext(n INode) {
node.next = n
}
func (node *Node) String() string {
return spew.Sprint(node.value)
}
// PriorityList 优先列表
type PriorityList struct {
head *Node
tail *Node
head INode
tail INode
compartor utils.Comparator
size int
size int
}
// Size 长度
@@ -44,73 +84,135 @@ func (pl *PriorityList) Size() int {
// Clear 清空链表, 如果外部有引用其中一个节点 要把节点Prev Next值为nil, 三色标记
func (pl *PriorityList) Clear() {
pl.head = nil
pl.tail = nil
pl.size = 0
}
// // ForEach 顺序遍历
// func (pl *PriorityList) ForEach(eachfunc func(*Node) *Node) {
// cur := pl.head
// }
// GetCompare 获取比较的节点 compare >= 11这个节点小的值 [15,12,9,8,6,1] = 9
func (pl *PriorityList) GetCompare(cNode INode) INode {
cur := pl.head
for cur != nil {
if !cur.Compare(cNode) {
return cur
}
cur = cur.GetNext()
}
return nil
}
// GetCompareReverse 逆序获取比较的节点 compare >= 11这个节点大的值 [15,12,9,8,6,1] = 12
func (pl *PriorityList) GetCompareReverse(cNode INode) INode {
cur := pl.tail
for cur != nil {
if cur.Compare(cNode) {
return cur
}
cur = cur.GetPrev()
}
return nil
}
// ForEach 顺序遍历
func (pl *PriorityList) ForEach(eachfunc func(INode) bool) {
cur := pl.head
for cur != nil {
if !eachfunc(cur) {
break
}
cur = cur.GetNext()
}
}
// ForEachReverse 逆遍历
func (pl *PriorityList) ForEachReverse(eachfunc func(INode) bool) {
cur := pl.tail
for cur != nil {
if !eachfunc(cur) {
break
}
cur = cur.GetPrev()
}
}
// Get 获取索引长度
func (pl *PriorityList) Get(idx int) interface{} {
node := pl.GetNode(idx)
if node != nil {
return node.Value
func (pl *PriorityList) Get(idx int) INode {
if idx >= pl.size {
return nil
}
return nil
}
// GetNode 获取索引长度
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
}
cur := pl.head
for i := 0; i < idx; i++ {
cur = cur.GetNext()
}
return nil
return cur
}
// Remove 删除节点
func (pl *PriorityList) Remove(idx int) {
pl.RemoveNode(pl.GetNode(idx))
// GetReverse 腻序获取索引长度
func (pl *PriorityList) GetReverse(idx int) INode {
if idx >= pl.size {
return nil
}
cur := pl.tail
for i := 0; i < idx; i++ {
cur = cur.GetPrev()
}
return cur
}
// RemoveNode 删除节点
func (pl *PriorityList) RemoveNode(node *Node) {
if node == nil {
// Remove 删除节点
func (pl *PriorityList) Remove(node INode) {
if pl.size <= 1 {
pl.head = nil
pl.tail = nil
if pl.size == 0 {
panic("the node is not in this list, node:" + spew.Sprint(node))
}
pl.size = 0
return
}
prev := node.prev
next := node.next
prev.next = next
next.prev = prev
pl.size--
prev := node.GetPrev()
next := node.GetNext()
if prev == nil {
pl.head = next
next.SetPrev(nil)
node.SetNext(nil)
} else if next == nil {
pl.tail = prev
prev.SetNext(nil)
node.SetPrev(nil)
} else {
prev.SetNext(next)
next.SetPrev(prev)
node.SetPrev(nil)
node.SetNext(nil)
}
}
// RemoveIndex 删除节点 并获取该节点
func (pl *PriorityList) RemoveIndex(idx int) INode {
result := pl.Get(idx)
pl.Remove(result)
return result
}
// RemoveReverseIndex 逆顺序删除节点 并获取该节点
func (pl *PriorityList) RemoveReverseIndex(idx int) INode {
result := pl.GetReverse(idx)
pl.Remove(result)
return result
}
func (pl *PriorityList) String() string {
content := "["
cur := pl.head.next
for cur != pl.tail {
content += spew.Sprint(cur.Value) + ","
cur = cur.next
cur := pl.head
for cur != nil {
content += spew.Sprint(cur.GetValue()) + ","
cur = cur.GetNext()
}
if content[len(content)-1:] == "," {
@@ -121,44 +223,48 @@ func (pl *PriorityList) String() string {
return content
}
func (pl *PriorityList) Iterator() *Iterator {
return &Iterator{pl: pl, cur: pl.head}
}
// Insert 插入节点
func (pl *PriorityList) Insert(value interface{}) {
func (pl *PriorityList) Insert(node INode) {
pl.size++
inode := &Node{Value: value}
cur := pl.head.next
for i := 0; cur != pl.tail; i++ {
if pl.compartor(value, cur.Value) > 0 {
prev := cur.prev
prev.next = inode
cur.prev = inode
inode.prev = prev
inode.next = cur
return
}
cur = cur.next
if pl.head == nil {
pl.head = node
pl.tail = node
return
}
cur := pl.head
for {
if !cur.Compare(node) {
// 插入该值
prev := cur.GetPrev()
if prev == nil {
pl.head.SetPrev(node)
node.SetNext(pl.head)
pl.head = node
} else {
prev.SetNext(node)
node.SetNext(cur)
cur.SetPrev(node)
node.SetPrev(prev)
}
return
}
next := cur.GetNext()
if next == nil {
cur.SetNext(node)
node.SetPrev(cur)
pl.tail = node
return
}
cur = next
}
prev := cur.prev
prev.next = inode
cur.prev = inode
inode.prev = prev
inode.next = cur
}
// New 创建 PriorityList
func New(compartor utils.Comparator) *PriorityList {
pl := new(PriorityList)
pl.compartor = compartor
pl.head = new(Node)
pl.tail = new(Node)
pl.head.next = pl.tail
pl.tail.prev = pl.head
return pl
func New() *PriorityList {
return new(PriorityList)
}

View File

@@ -2,41 +2,86 @@ package plist
import (
"testing"
"github.com/Pallinder/go-randomdata"
"github.com/emirpasic/gods/utils"
)
func TestPriority(t *testing.T) {
pl := New(utils.IntComparator)
for i := 0; i < 20; i++ {
pl.Insert(randomdata.Number(0, 100000))
}
t.Error(pl.String(), pl.Get(5), pl.Get(-1), pl.Get(-pl.size), pl.Get(-pl.size-1))
pl := New()
iter := pl.Iterator()
for iter.Next() {
t.Error(iter.Value())
pl.Insert(NewNodeInt(1))
pl.Insert(NewNodeInt(2))
pl.Insert(NewNodeInt(3))
if pl.String() != "[3,2,1]" {
t.Error("Insert or String error", pl.String())
}
for iter.Prev() {
t.Error(iter.Value())
if pl.Get(0).GetValue() != 3 {
t.Error(pl.Get(0).GetValue())
}
for i := 0; i < 20; i++ {
pl.Remove(0)
t.Error(pl.String())
if pl.Get(pl.Size()-1).GetValue() != 1 {
t.Error(pl.Get(pl.Size() - 1).GetValue())
}
if pl.Size() != 3 {
t.Error("size error, current is", pl.Size())
}
pl.Remove(pl.Get(2))
if pl.String() != "[3,2]" || pl.Size() != 2 {
t.Error("Remove error current is ", pl.String(), pl.Size())
}
pl.Remove(pl.GetReverse(0))
if pl.String() != "[3]" || pl.Size() != 1 {
t.Error("Remove error current is ", pl.String(), pl.Size())
}
pl.Remove(pl.Get(0))
if pl.String() != "[]" || pl.Size() != 0 {
t.Error("Remove error current is ", pl.String(), pl.Size())
}
pl.Insert(NewNodeInt(6))
pl.Insert(NewNodeInt(5))
pl.Insert(NewNodeInt(7))
pl.Insert(NewNodeInt(12))
pl.Insert(NewNodeInt(8))
if pl.String() != "[12,8,7,6,5]" || pl.Size() != 5 {
t.Error("Insert or String error, current is ", pl.String(), pl.Size())
}
pl.RemoveReverseIndex(3)
if pl.String() != "[12,7,6,5]" || pl.Size() != 4 {
t.Error("Remove error current is ", pl.String(), pl.Size())
}
size := pl.Size()
for i := 0; i < size; i++ {
pl.RemoveReverseIndex(0)
}
if pl.String() != "[]" || pl.Size() != 0 {
t.Error("Remove error current is ", pl.String(), pl.Size())
}
pl.Insert(NewNodeInt(6))
pl.Insert(NewNodeInt(1))
pl.Insert(NewNodeInt(9))
pl.Insert(NewNodeInt(15))
pl.Insert(NewNodeInt(12))
pl.Insert(NewNodeInt(8))
if pl.GetCompare(NewNodeInt(9)).GetValue() != 9 {
t.Error(pl.String(), pl.GetCompare(NewNodeInt(9)).GetValue())
}
if pl.GetCompareReverse(NewNodeInt(11)).GetValue() != 12 {
t.Error(pl.String(), pl.GetCompareReverse(NewNodeInt(11)).GetValue())
}
pl.Clear()
if pl.String() != "[]" || pl.Size() != 0 {
t.Error("Remove error current is ", pl.String(), pl.Size())
}
}
func BenchmarkPriority(b *testing.B) {
pl := New(utils.IntComparator)
b.N = 10000
for i := 0; i < b.N; i++ {
pl.Insert(randomdata.Number(0, 100000))
}
}

View File

@@ -1,82 +1,114 @@
package plist
import (
"errors"
"log"
"github.com/davecgh/go-spew/spew"
"github.com/emirpasic/gods/trees/binaryheap"
"github.com/emirpasic/gods/utils"
)
// PriorityQueue 优先队列 适合数据量不大, 加索引
type PriorityQueue struct {
heaps []*binaryheap.Heap
heapsCap int
cursor int
data []interface{}
left, right, mid int
cap int
size int
isSorted bool
comparator utils.Comparator
}
splitlimit int
size int
comparator utils.Comparator
// NewWithInt compare use int
func NewWithInt() *PriorityQueue {
p := new(PriorityQueue)
p.cap = 11
p.mid = 5
p.data = make([]interface{}, p.cap, p.cap)
p.comparator = func(a, b interface{}) int {
if a.(int) > b.(int) {
return 1
}
return -1
}
return p
}
func (pq *PriorityQueue) String() string {
content := ""
for i := pq.cursor; i < pq.heapsCap; i++ {
content += spew.Sprint(pq.heaps[i].Values()) + "--"
}
return content
return "(" + spew.Sprint(pq.data[pq.mid]) + "," + spew.Sprint(pq.size) + ")" + spew.Sprint(pq.Values())
}
func NewWithIntComparator() *PriorityQueue {
pq := new(PriorityQueue)
pq.splitlimit = 20
pq.heapsCap = 10
pq.heaps = make([]*binaryheap.Heap, pq.heapsCap, pq.heapsCap)
pq.cursor = pq.heapsCap - 1
pq.comparator = func(v1, v2 interface{}) int {
if v1.(int) > v2.(int) {
return 1
} else if v1.(int) < v2.(int) {
return -1
}
return 0
}
pq.heaps[pq.cursor] = binaryheap.NewWith(pq.comparator)
return pq
}
func (pq *PriorityQueue) Push(value interface{}) {
pq.size++
curheap := pq.heaps[pq.cursor]
log.Println(pq.heaps)
if curheap.Size() >= pq.splitlimit {
if pq.cursor == 0 {
// remake
}
pq.cursor--
heap := binaryheap.NewWith(pq.comparator)
heap.Push(value)
for i := 0; i < pq.splitlimit/2-1; i++ {
v, ok := curheap.Pop()
if !ok {
panic(errors.New("size is error?"))
}
heap.Push(v)
}
pq.heaps[pq.cursor] = heap
func (pq *PriorityQueue) reMakeData() {
var temp []interface{}
if pq.cap <= 1024 {
pq.cap = pq.cap*2 + 1
temp = make([]interface{}, pq.cap, pq.cap)
} else {
curheap.Push(value)
pq.cap = pq.cap*5/8*2 + 1
temp = make([]interface{}, pq.cap, pq.cap)
}
return
pq.mid = (pq.cap - 1) / 2
left := pq.mid - pq.size/2
copy(temp[left:], pq.data[pq.left:pq.right])
pq.left = left
pq.right = pq.left + pq.size
pq.data = temp
}
func (pq *PriorityQueue) Push(v interface{}) {
if pq.size == 0 {
pq.data[pq.mid] = v
pq.left = pq.mid
pq.right = pq.mid + 1
pq.size = 1
return
}
midvalue := pq.data[pq.mid]
if pq.comparator(v, midvalue) > 0 {
if pq.left == 0 {
pq.reMakeData()
}
pq.left--
pq.data[pq.left] = v
} else {
if pq.right == pq.cap {
pq.reMakeData()
}
pq.data[pq.right] = v
pq.right++
}
pq.isSorted = false
pq.size++
}
// func (pq *PriorityQueue) Top() (interface{}, bool) {
// return pq.Get(0)
// }
// func (pq *PriorityQueue) Bottom() (interface{}, bool) {
// return pq.Get(pq.right - 1)
// }
// func (pq *PriorityQueue) Get(index int) (interface{}, bool) {
// if index < pq.size {
// return pq.Values()[index], true
// }
// return nil, false
// }
func (pq *PriorityQueue) Values() []interface{} {
values := pq.data[pq.left:pq.right]
if !pq.isSorted {
utils.Sort(values, pq.comparator)
pq.isSorted = true
}
return values
}

View File

@@ -3,8 +3,6 @@ package plist
import (
"testing"
"github.com/emirpasic/gods/trees/avltree"
"github.com/emirpasic/gods/utils"
"github.com/Pallinder/go-randomdata"
@@ -12,76 +10,36 @@ import (
"github.com/emirpasic/gods/trees/binaryheap"
)
func TestPQ(t *testing.T) {
func TestPriorityQueue(t *testing.T) {
p := NewWithInt()
var l []int
pq := NewWithIntComparator()
for i := 0; i < 50; i++ {
v := randomdata.Number(0, 1000)
pq.Push(v)
l = append(l, v)
for i := 0; i < 100; i++ {
p.Push(randomdata.Number(0, 10000))
t.Log(p.String())
}
// iter := pq.avl.Iterator()
// iter.Next()
// pl := iter.Value().(*PriorityList)
// t.Error(pq.size, "avlsize:", pq.avl.Size(), pl.Size(), pl.head == nil, pl.String())
t.Error(l)
t.Error(pq.String())
t.Error(p.String())
}
func BenchmarkPQ(b *testing.B) {
func BenchmarkPriorityQueue(b *testing.B) {
p := NewWithInt()
// b.Log("all:", pq.avl.Size(), pq.avl.Values())
}
// for i := 0; i < 10000; i++ {
// p.Push(randomdata.Number(0, 100000))
// // p.Values()
// }
func TestAvl(t *testing.T) {
comparator := func(v1, v2 interface{}) int {
if v1.(int) > v2.(int) {
return 1
} else if v1.(int) < v2.(int) {
return -1
b.N = 100000
for i := 0; i < b.N; i++ {
p.Push(randomdata.Number(0, 100000))
if i%100 == 0 {
p.Values()
}
return 0
}
avl := avltree.NewWith(comparator)
for _, v := range []int{9, 2, 3, 4, 5, 6, 8, 1} {
avl.Put(v, v)
}
iter := avl.Iterator()
iter.End()
iter.Prev()
t.Error(avl.Values(), iter.Value())
f, ok := avl.Floor(10)
if ok {
t.Error("Floor", f)
}
f, ok = avl.Ceiling(10)
if ok {
t.Error("Ceiling", f)
}
for _, v := range []int{9, 2, 3, 45, 51, 16, 18, 11} {
avl.Put(v, v)
}
iter = avl.Iterator()
iter.End()
for iter.Prev() {
t.Error(iter.Value())
}
}
func TestHeap(t *testing.T) {
heap := binaryheap.NewWithIntComparator()
for i := 0; i < 10; i++ {
@@ -94,3 +52,35 @@ func TestHeap(t *testing.T) {
utils.Sort(heap.Values(), utils.IntComparator)
}
func BenchmarkList_InsertValues123(b *testing.B) {
a := func(v1, v2 interface{}) int {
if v1.(int) > v2.(int) {
return -1
}
return 1
}
h := binaryheap.NewWith(a)
TOPK := 50
for i := 0; i < TOPK*1000; i++ {
h.Push(i)
}
b.StartTimer()
for i := 0; i < b.N; i++ {
h.Push(i)
l := []interface{}{}
for n := 0; n < TOPK; n++ {
v, _ := h.Pop()
l = append(l, v)
}
for _, v := range l {
h.Push(v)
}
}
b.StopTimer()
}