TODO: 完善avl+list的结合

This commit is contained in:
huangsimin 2019-02-15 18:51:21 +08:00
parent 0403bebea4
commit 6e249d4634
4 changed files with 180 additions and 223 deletions

BIN
priority_queue/debug.test Executable file

Binary file not shown.

View File

@ -0,0 +1,58 @@
package plist
import (
"github.com/davecgh/go-spew/spew"
)
// Node 节点结构
type Node struct {
next *Node
value interface{}
}
// PriorityList
type PriorityList struct {
size int
head *Node
}
// New a node
func New() *PriorityList {
p := new(PriorityList)
return p
}
// String 展示需要的
func (pl *PriorityList) String() string {
content := ""
for cur := pl.head; cur != nil; cur = cur.next {
content += spew.Sprint(cur.value) + "-"
}
if content != "" && content[len(content)-1] == '-' {
content = content[:len(content)-1]
}
return content
}
// insert 插入值
func (pl *PriorityList) nodeInsert(cur *Node, value interface{}) {
if cur == nil {
temp := pl.head
pl.head = &Node{value: value}
pl.head.next = temp
return
}
temp := cur.next
cur.next = &Node{value: value}
cur.next.next = temp
}
// Size 长度
func (pl *PriorityList) Size() int {
return pl.size
}

View File

@ -1,190 +1,74 @@
package plist
import (
"github.com/davecgh/go-spew/spew"
"github.com/emirpasic/gods/trees/avltree"
"github.com/emirpasic/gods/utils"
)
// PriorityQueue 优先队列 适合数据量不大, 加索引
type PriorityQueue struct {
index *Index
indexlimit int
node *Node
avl *avltree.Tree
size int
comparator utils.Comparator
splitlimit int
}
type Index struct {
node *Node
next *Index
nlen int
}
type Node struct {
value interface{}
// prev *Node
next *Node
}
// NewWithInt compare use int
func NewWithInt() *PriorityQueue {
p := new(PriorityQueue)
p.indexlimit = 10
p.comparator = func(a, b interface{}) int {
if a.(int) > b.(int) {
func NewWithIntComparator() *PriorityQueue {
pq := new(PriorityQueue)
pq.comparator = func(v1, v2 interface{}) int {
if v1.(int) > v2.(int) {
return 1
} else if v1.(int) < v2.(int) {
return -1
}
return -1
return 0
}
return p
pq.avl = avltree.NewWith(pq.comparator)
pq.size = 0
return pq
}
func (pq *PriorityQueue) String() string {
content := ""
for cur := pq.node; cur != nil; cur = cur.next {
// var prevcontent string
// if cur.prev != nil {
// prevcontent = "(" + spew.Sprint(cur.prev.value) + "<-)"
// } else {
// prevcontent = "(nil)"
// }
func (pq *PriorityQueue) Push(value interface{}) {
var pl *PriorityList
pq.size++
// content += spew.Sprint(cur.value) + prevcontent + "-"
content += spew.Sprint(cur.value) + "-"
}
floor, ok := pq.avl.Floor(value)
if ok {
if content != "" {
if content[len(content)-1] == '-' {
content = content[:len(content)-1]
}
}
pl = floor.Value.(*PriorityList)
cur := pl.head
pl.size++
idxContent := ""
for idx := pq.index; idx != nil; idx = idx.next {
idxContent += spew.Sprint(idx.node.value) + "(" + spew.Sprint(idx.nlen) + ")-"
}
if pq.comparator(value, cur.value) > 0 {
return content + "\n" + idxContent
}
func (pq *PriorityQueue) Push(v interface{}) {
node := new(Node)
node.value = v
if pq.node == nil {
//创建索引
index := new(Index)
index.nlen = 1
index.node = node
pq.index = index
pq.node = node
return
}
// find the node of index to start
idx := pq.index
for {
if idx.next == nil {
break
}
if pq.comparator(v, idx.next.node.value) > 0 {
break
}
idx = idx.next
}
cur := idx.node
//cur := pq.node
if pq.comparator(v, pq.node.value) > 0 {
pq.node = node
node.next = cur
pq.index.node = pq.node
pq.index.nlen++
// cur.prev = node
return
}
for i := 0; cur.next != nil; i++ {
if i >= pq.indexlimit {
if idx.next != nil && idx.next.nlen < pq.indexlimit {
idx.next.nlen += idx.nlen - pq.indexlimit
idx.nlen = pq.indexlimit
idx.next.node = cur
} else {
index := new(Index)
index.node = cur
index.nlen = idx.nlen - pq.indexlimit
index.next = idx.next
idx.next = index
idx.nlen = pq.indexlimit
idx = index
i = 0
}
}
if pq.comparator(v, cur.next.value) > 0 {
temp := cur.next
cur.next = node
node.next = temp
// node.prev = cur
// temp.prev = node
idx.nlen++
// if pq.index.nlen >= pq.indexlimit {
// // 分裂
// }
temp := pl.head
pl.head = &Node{value: value}
pl.head.next = temp
return
}
cur = cur.next
for cur.next != nil {
if pq.comparator(value, cur.next.value) >= 0 {
temp := cur.next
cur.next = &Node{value: value}
cur.next.next = temp
return
}
cur = cur.next
}
// next == nil
cur.next = &Node{value: value}
return
}
cur.next = node
pl = &PriorityList{}
pl.head = &Node{value: value}
pl.size++
// node.prev = cur
pq.size++
idx.nlen++
pq.avl.Put(pl.head.value, pl)
return
}
// 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.datas[pq.left:pq.right]
// // if !pq.isSorted {
// // utils.Sort(values, pq.comparator)
// // pq.isSorted = true
// // }
// return pq.datas[pq.left:pq.right]
// }

View File

@ -1,9 +1,10 @@
package plist
import (
"log"
"testing"
"github.com/emirpasic/gods/trees/avltree"
"github.com/emirpasic/gods/utils"
"github.com/Pallinder/go-randomdata"
@ -11,53 +12,99 @@ import (
"github.com/emirpasic/gods/trees/binaryheap"
)
type PriorityQ struct {
heap *binaryheap.Heap
comparator utils.Comparator
topk int
next *PriorityQ
}
func (pq *PriorityQ) Push(v interface{}) {
}
func TestNPQ(t *testing.T) {
h1 := binaryheap.NewWithIntComparator()
func TestPList(t *testing.T) {
pl := &PriorityList{}
for i := 0; i < 10; i++ {
h1.Push(i)
pl.nodeInsert(nil, randomdata.Number(0, 10))
}
t.Error(pl.String())
h1.Values()[0] = 3
log.Println(h1)
cur := pl.head
for i := 0; i < 5; i++ {
cur = cur.next
}
pl.nodeInsert(cur, 11)
t.Error(pl.String())
}
func TestPriorityQueue(t *testing.T) {
p := NewWithInt()
func TestPQ(t *testing.T) {
for i := 0; i < 100; i++ {
p.Push(randomdata.Number(0, 10000))
t.Log(p.String())
pq := NewWithIntComparator()
for i := 0; i < 1; i++ {
pq.Push(i)
}
t.Error(p.String())
iter := pq.avl.Iterator()
iter.Next()
pl := iter.Value().(*PriorityList)
t.Error(pq.size, pq.avl.Size(), pl.Size(), pl.head == nil, pl.head)
}
func BenchmarkPriorityQueue(b *testing.B) {
p := NewWithInt()
func BenchmarkPQ(b *testing.B) {
pq := NewWithIntComparator()
// for i := 0; i < 10000; i++ {
// p.Push(randomdata.Number(0, 100000))
// // p.Values()
// }
b.N = 1000000
for i := b.N; i > 0; i-- {
pq.Push(i)
}
iter := pq.avl.Iterator()
iter.Next()
pl := iter.Value().(*PriorityList)
b.Log(pq.size, pq.avl.Size(), pl.Size(), pl.head)
b.Log(pl.head.value)
if pl.head.next != nil {
b.Log(pl.head.next.value)
}
// b.Log("all:", pq.avl.Size(), pq.avl.Values())
}
func BenchmarkPList(b *testing.B) {
b.N = 100000
for i := 0; i < b.N; i++ {
p.Push(randomdata.Number(0, 100000))
pl := &PriorityList{}
for i2 := 0; i2 < 5; i2++ {
cur := pl.head
for n := 0; n < i2; n++ {
cur = cur.next
}
pl.nodeInsert(cur, i2)
}
}
}
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
}
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.Next()
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)
}
}
func TestHeap(t *testing.T) {
@ -73,35 +120,3 @@ 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()
}