TODO: 完善avl+list的结合
This commit is contained in:
parent
0403bebea4
commit
6e249d4634
BIN
priority_queue/debug.test
Executable file
BIN
priority_queue/debug.test
Executable file
Binary file not shown.
58
priority_queue/priority_list.go
Normal file
58
priority_queue/priority_list.go
Normal 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
|
||||||
|
}
|
@ -1,190 +1,74 @@
|
|||||||
package plist
|
package plist
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/davecgh/go-spew/spew"
|
"github.com/emirpasic/gods/trees/avltree"
|
||||||
"github.com/emirpasic/gods/utils"
|
"github.com/emirpasic/gods/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
// PriorityQueue 优先队列 适合数据量不大, 加索引
|
// PriorityQueue 优先队列 适合数据量不大, 加索引
|
||||||
type PriorityQueue struct {
|
type PriorityQueue struct {
|
||||||
index *Index
|
avl *avltree.Tree
|
||||||
indexlimit int
|
|
||||||
node *Node
|
|
||||||
size int
|
size int
|
||||||
comparator utils.Comparator
|
comparator utils.Comparator
|
||||||
|
splitlimit int
|
||||||
}
|
}
|
||||||
|
|
||||||
type Index struct {
|
func NewWithIntComparator() *PriorityQueue {
|
||||||
node *Node
|
pq := new(PriorityQueue)
|
||||||
next *Index
|
pq.comparator = func(v1, v2 interface{}) int {
|
||||||
nlen int
|
if v1.(int) > v2.(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) {
|
|
||||||
return 1
|
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 {
|
func (pq *PriorityQueue) Push(value interface{}) {
|
||||||
content := ""
|
var pl *PriorityList
|
||||||
for cur := pq.node; cur != nil; cur = cur.next {
|
pq.size++
|
||||||
// var prevcontent string
|
|
||||||
// if cur.prev != nil {
|
|
||||||
// prevcontent = "(" + spew.Sprint(cur.prev.value) + "<-)"
|
|
||||||
// } else {
|
|
||||||
// prevcontent = "(nil)"
|
|
||||||
// }
|
|
||||||
|
|
||||||
// content += spew.Sprint(cur.value) + prevcontent + "-"
|
floor, ok := pq.avl.Floor(value)
|
||||||
content += spew.Sprint(cur.value) + "-"
|
if ok {
|
||||||
}
|
|
||||||
|
|
||||||
if content != "" {
|
pl = floor.Value.(*PriorityList)
|
||||||
if content[len(content)-1] == '-' {
|
cur := pl.head
|
||||||
content = content[:len(content)-1]
|
pl.size++
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
idxContent := ""
|
if pq.comparator(value, cur.value) > 0 {
|
||||||
for idx := pq.index; idx != nil; idx = idx.next {
|
|
||||||
idxContent += spew.Sprint(idx.node.value) + "(" + spew.Sprint(idx.nlen) + ")-"
|
|
||||||
}
|
|
||||||
|
|
||||||
return content + "\n" + idxContent
|
temp := pl.head
|
||||||
}
|
pl.head = &Node{value: value}
|
||||||
|
pl.head.next = temp
|
||||||
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 {
|
|
||||||
// // 分裂
|
|
||||||
|
|
||||||
// }
|
|
||||||
|
|
||||||
return
|
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.avl.Put(pl.head.value, pl)
|
||||||
pq.size++
|
|
||||||
idx.nlen++
|
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]
|
|
||||||
// }
|
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
package plist
|
package plist
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"log"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/emirpasic/gods/trees/avltree"
|
||||||
|
|
||||||
"github.com/emirpasic/gods/utils"
|
"github.com/emirpasic/gods/utils"
|
||||||
|
|
||||||
"github.com/Pallinder/go-randomdata"
|
"github.com/Pallinder/go-randomdata"
|
||||||
@ -11,53 +12,99 @@ import (
|
|||||||
"github.com/emirpasic/gods/trees/binaryheap"
|
"github.com/emirpasic/gods/trees/binaryheap"
|
||||||
)
|
)
|
||||||
|
|
||||||
type PriorityQ struct {
|
func TestPList(t *testing.T) {
|
||||||
heap *binaryheap.Heap
|
pl := &PriorityList{}
|
||||||
comparator utils.Comparator
|
|
||||||
topk int
|
|
||||||
next *PriorityQ
|
|
||||||
}
|
|
||||||
|
|
||||||
func (pq *PriorityQ) Push(v interface{}) {
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestNPQ(t *testing.T) {
|
|
||||||
h1 := binaryheap.NewWithIntComparator()
|
|
||||||
|
|
||||||
for i := 0; i < 10; i++ {
|
for i := 0; i < 10; i++ {
|
||||||
h1.Push(i)
|
pl.nodeInsert(nil, randomdata.Number(0, 10))
|
||||||
}
|
}
|
||||||
|
t.Error(pl.String())
|
||||||
|
|
||||||
h1.Values()[0] = 3
|
cur := pl.head
|
||||||
|
for i := 0; i < 5; i++ {
|
||||||
log.Println(h1)
|
cur = cur.next
|
||||||
|
}
|
||||||
|
pl.nodeInsert(cur, 11)
|
||||||
|
|
||||||
|
t.Error(pl.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPriorityQueue(t *testing.T) {
|
func TestPQ(t *testing.T) {
|
||||||
p := NewWithInt()
|
|
||||||
|
|
||||||
for i := 0; i < 100; i++ {
|
pq := NewWithIntComparator()
|
||||||
p.Push(randomdata.Number(0, 10000))
|
for i := 0; i < 1; i++ {
|
||||||
t.Log(p.String())
|
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) {
|
func BenchmarkPQ(b *testing.B) {
|
||||||
p := NewWithInt()
|
pq := NewWithIntComparator()
|
||||||
|
|
||||||
// for i := 0; i < 10000; i++ {
|
b.N = 1000000
|
||||||
// p.Push(randomdata.Number(0, 100000))
|
for i := b.N; i > 0; i-- {
|
||||||
// // p.Values()
|
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++ {
|
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) {
|
func TestHeap(t *testing.T) {
|
||||||
@ -73,35 +120,3 @@ func TestHeap(t *testing.T) {
|
|||||||
utils.Sort(heap.Values(), utils.IntComparator)
|
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()
|
|
||||||
}
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user