123
This commit is contained in:
parent
0fb5a2ca4a
commit
5c3828542b
|
@ -1,58 +0,0 @@
|
||||||
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,41 +1,33 @@
|
||||||
package plist
|
package plist
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"log"
|
"log"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/davecgh/go-spew/spew"
|
"github.com/davecgh/go-spew/spew"
|
||||||
"github.com/emirpasic/gods/trees/avltree"
|
|
||||||
|
"github.com/emirpasic/gods/trees/binaryheap"
|
||||||
|
|
||||||
"github.com/emirpasic/gods/utils"
|
"github.com/emirpasic/gods/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
// PriorityQueue 优先队列 适合数据量不大, 加索引
|
// PriorityQueue 优先队列 适合数据量不大, 加索引
|
||||||
type PriorityQueue struct {
|
type PriorityQueue struct {
|
||||||
avl *avltree.Tree
|
heaps []*binaryheap.Heap
|
||||||
|
heapsCap int
|
||||||
|
cursor int
|
||||||
|
|
||||||
|
splitlimit int
|
||||||
size int
|
size int
|
||||||
comparator utils.Comparator
|
comparator utils.Comparator
|
||||||
splitlimit int
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pq *PriorityQueue) String() string {
|
func (pq *PriorityQueue) String() string {
|
||||||
|
|
||||||
content := ""
|
content := ""
|
||||||
iter := pq.avl.Iterator()
|
|
||||||
|
|
||||||
for !iter.Last() {
|
for i := pq.cursor; i < pq.heapsCap; i++ {
|
||||||
iter.Next()
|
content += spew.Sprint(pq.heaps[i].Values()) + "--"
|
||||||
}
|
|
||||||
|
|
||||||
for iter.Prev() {
|
|
||||||
pl := iter.Value().(*PriorityList)
|
|
||||||
|
|
||||||
cur := pl.head
|
|
||||||
for cur != nil {
|
|
||||||
content += spew.Sprint(cur.value) + "-"
|
|
||||||
cur = cur.next
|
|
||||||
}
|
|
||||||
content = strings.TrimRight(content, "-")
|
|
||||||
content += " ~ "
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return content
|
return content
|
||||||
|
@ -43,6 +35,11 @@ func (pq *PriorityQueue) String() string {
|
||||||
|
|
||||||
func NewWithIntComparator() *PriorityQueue {
|
func NewWithIntComparator() *PriorityQueue {
|
||||||
pq := new(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 {
|
pq.comparator = func(v1, v2 interface{}) int {
|
||||||
if v1.(int) > v2.(int) {
|
if v1.(int) > v2.(int) {
|
||||||
return 1
|
return 1
|
||||||
|
@ -51,78 +48,35 @@ func NewWithIntComparator() *PriorityQueue {
|
||||||
}
|
}
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
pq.avl = avltree.NewWith(pq.comparator)
|
pq.heaps[pq.cursor] = binaryheap.NewWith(pq.comparator)
|
||||||
pq.splitlimit = 8
|
|
||||||
pq.size = 0
|
|
||||||
return pq
|
return pq
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pq *PriorityQueue) Push(value interface{}) {
|
func (pq *PriorityQueue) Push(value interface{}) {
|
||||||
var pl *PriorityList
|
|
||||||
pq.size++
|
pq.size++
|
||||||
|
|
||||||
defer func() {
|
curheap := pq.heaps[pq.cursor]
|
||||||
if pl.size >= pq.splitlimit {
|
log.Println(pq.heaps)
|
||||||
moveIndex := pl.size / 2
|
if curheap.Size() >= pq.splitlimit {
|
||||||
cur := pl.head
|
if pq.cursor == 0 {
|
||||||
for i := 1; i < moveIndex; i++ {
|
// remake
|
||||||
cur = cur.next
|
}
|
||||||
|
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?"))
|
||||||
}
|
}
|
||||||
log.Println("pq:", pq.String())
|
heap.Push(v)
|
||||||
temp := cur.next
|
|
||||||
cur.next = nil
|
|
||||||
|
|
||||||
plsp := &PriorityList{}
|
|
||||||
plsp.head = temp
|
|
||||||
plsp.size = pl.size - moveIndex
|
|
||||||
|
|
||||||
pl.size = moveIndex
|
|
||||||
|
|
||||||
pq.avl.Put(plsp.head.value, plsp)
|
|
||||||
log.Println("list:", pl.head.value, pl.String())
|
|
||||||
log.Println("list:", plsp.head.value, plsp.String())
|
|
||||||
log.Println("pq:", pq.avl.Values())
|
|
||||||
log.Println("pq:", pq.String(), "\n----------")
|
|
||||||
}
|
}
|
||||||
}()
|
pq.heaps[pq.cursor] = heap
|
||||||
|
|
||||||
floor, ok := pq.avl.Floor(value)
|
|
||||||
if ok {
|
|
||||||
|
|
||||||
pl = floor.Value.(*PriorityList)
|
|
||||||
cur := pl.head
|
|
||||||
pl.size++
|
|
||||||
|
|
||||||
if pq.comparator(value, cur.value) > 0 {
|
|
||||||
|
|
||||||
temp := pl.head
|
|
||||||
pl.head = &Node{value: value}
|
|
||||||
pl.head.next = temp
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
|
} else {
|
||||||
|
curheap.Push(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
pl = &PriorityList{}
|
|
||||||
pl.head = &Node{value: value}
|
|
||||||
pl.size++
|
|
||||||
|
|
||||||
pq.avl.Put(pl.head.value, pl)
|
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,22 +12,6 @@ import (
|
||||||
"github.com/emirpasic/gods/trees/binaryheap"
|
"github.com/emirpasic/gods/trees/binaryheap"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestPList(t *testing.T) {
|
|
||||||
pl := &PriorityList{}
|
|
||||||
for i := 0; i < 10; i++ {
|
|
||||||
pl.nodeInsert(nil, randomdata.Number(0, 10))
|
|
||||||
}
|
|
||||||
t.Error(pl.String())
|
|
||||||
|
|
||||||
cur := pl.head
|
|
||||||
for i := 0; i < 5; i++ {
|
|
||||||
cur = cur.next
|
|
||||||
}
|
|
||||||
pl.nodeInsert(cur, 11)
|
|
||||||
|
|
||||||
t.Error(pl.String())
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestPQ(t *testing.T) {
|
func TestPQ(t *testing.T) {
|
||||||
|
|
||||||
var l []int
|
var l []int
|
||||||
|
@ -48,40 +32,10 @@ func TestPQ(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkPQ(b *testing.B) {
|
func BenchmarkPQ(b *testing.B) {
|
||||||
pq := NewWithIntComparator()
|
|
||||||
|
|
||||||
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())
|
// b.Log("all:", pq.avl.Size(), pq.avl.Values())
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkPList(b *testing.B) {
|
|
||||||
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
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) {
|
func TestAvl(t *testing.T) {
|
||||||
|
|
||||||
comparator := func(v1, v2 interface{}) int {
|
comparator := func(v1, v2 interface{}) int {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user