还要完成index
This commit is contained in:
parent
36d7f0208b
commit
3ff7e7e855
@ -1,24 +1,36 @@
|
|||||||
package plist
|
package plist
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"log"
|
"github.com/davecgh/go-spew/spew"
|
||||||
|
|
||||||
"github.com/emirpasic/gods/utils"
|
"github.com/emirpasic/gods/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
// PriorityQueue 优先队列 适合数据量不大, 加索引
|
// PriorityQueue 优先队列 适合数据量不大, 加索引
|
||||||
type PriorityQueue struct {
|
type PriorityQueue struct {
|
||||||
left, right, mid int
|
index *Index
|
||||||
datas []interface{}
|
indexlimit int
|
||||||
|
node *Node
|
||||||
size int
|
size int
|
||||||
comparator utils.Comparator
|
comparator utils.Comparator
|
||||||
isSorted bool
|
}
|
||||||
|
|
||||||
|
type Index struct {
|
||||||
|
node *Node
|
||||||
|
next *Index
|
||||||
|
nlen int
|
||||||
|
}
|
||||||
|
|
||||||
|
type Node struct {
|
||||||
|
value interface{}
|
||||||
|
|
||||||
|
prev *Node
|
||||||
|
next *Node
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewWithInt compare use int
|
// NewWithInt compare use int
|
||||||
func NewWithInt() *PriorityQueue {
|
func NewWithInt() *PriorityQueue {
|
||||||
p := new(PriorityQueue)
|
p := new(PriorityQueue)
|
||||||
p.datas = make([]interface{}, 8)
|
p.indexlimit = 10
|
||||||
p.comparator = func(a, b interface{}) int {
|
p.comparator = func(a, b interface{}) int {
|
||||||
if a.(int) > b.(int) {
|
if a.(int) > b.(int) {
|
||||||
return 1
|
return 1
|
||||||
@ -28,174 +40,110 @@ func NewWithInt() *PriorityQueue {
|
|||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pq *PriorityQueue) reArrange() {
|
func (pq *PriorityQueue) String() string {
|
||||||
|
content := ""
|
||||||
}
|
for cur := pq.node; cur != nil; cur = cur.next {
|
||||||
|
var prevcontent string
|
||||||
func (pq *PriorityQueue) reMakeMemory() {
|
if cur.prev != nil {
|
||||||
|
prevcontent = "(" + spew.Sprint(cur.prev.value) + "<-)"
|
||||||
var incSize int
|
|
||||||
if pq.size >= 1048 {
|
|
||||||
incSize = pq.size / 2
|
|
||||||
} else {
|
} else {
|
||||||
incSize = pq.size
|
prevcontent = "(nil)"
|
||||||
}
|
}
|
||||||
|
|
||||||
capacity := pq.size + incSize
|
content += spew.Sprint(cur.value) + prevcontent + "-"
|
||||||
temp := make([]interface{}, capacity)
|
|
||||||
|
|
||||||
mid := capacity / 2
|
|
||||||
left := mid - pq.size/2 - 1
|
|
||||||
|
|
||||||
x := pq.datas
|
|
||||||
copy(temp[left+1:], pq.datas[pq.left+1:pq.right])
|
|
||||||
pq.datas = temp
|
|
||||||
pq.left = left
|
|
||||||
pq.mid = mid
|
|
||||||
pq.right = pq.size + pq.left
|
|
||||||
|
|
||||||
log.Println(x, pq.datas, pq.left, pq.right)
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
if content[len(content)-1] == '-' {
|
||||||
func (pq *PriorityQueue) search(v interface{}) int {
|
content = content[:len(content)-1]
|
||||||
// left := pq.left
|
|
||||||
// right := pq.right
|
|
||||||
|
|
||||||
data := pq.datas[pq.left+1 : pq.right]
|
|
||||||
left := 0
|
|
||||||
mid := 0
|
|
||||||
right := len(data)
|
|
||||||
|
|
||||||
for left < right-1 {
|
|
||||||
mid = (left + right) / 2 // 4 10 7 10 8 10 9 10 | 4 10 4 7 4 5
|
|
||||||
if pq.comparator(v, data[mid]) > 0 {
|
|
||||||
left = mid
|
|
||||||
} else {
|
|
||||||
right = mid
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if pq.comparator(v, data[left]) > 0 {
|
|
||||||
return left + 1
|
|
||||||
} else {
|
|
||||||
return left
|
|
||||||
}
|
}
|
||||||
|
return content
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pq *PriorityQueue) Push(v interface{}) {
|
func (pq *PriorityQueue) Push(v interface{}) {
|
||||||
|
|
||||||
defer func() {
|
node := new(Node)
|
||||||
if err := recover(); err != nil {
|
node.value = v
|
||||||
|
|
||||||
log.Println(pq.datas)
|
if pq.node == nil {
|
||||||
log.Println(pq.left, pq.right, pq.size)
|
//创建索引
|
||||||
log.Panic(err)
|
index := new(Index)
|
||||||
|
index.nlen = 1
|
||||||
|
index.node = node
|
||||||
|
|
||||||
|
return
|
||||||
}
|
}
|
||||||
}()
|
// find the node of index to start
|
||||||
|
idx := pq.index
|
||||||
|
|
||||||
if pq.size == 0 {
|
for {
|
||||||
|
|
||||||
pq.mid = len(pq.datas) / 2
|
if idx.next == nil {
|
||||||
pq.left = pq.mid - 1
|
break
|
||||||
pq.right = pq.mid + 1
|
|
||||||
|
|
||||||
pq.datas[pq.mid] = v
|
|
||||||
|
|
||||||
log.Println(pq.datas)
|
|
||||||
log.Println(pq.left)
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
// if pq.comparator(v, pq.datas[pq.mid]) > 0 {
|
|
||||||
|
|
||||||
// if pq.right >= len(pq.datas) {
|
|
||||||
// // 重建 datas
|
|
||||||
// pq.reMakeMemory()
|
|
||||||
// }
|
|
||||||
|
|
||||||
// pq.datas[pq.right] = v
|
|
||||||
// pq.right++
|
|
||||||
|
|
||||||
// } else {
|
|
||||||
|
|
||||||
// if pq.left-1 < 0 {
|
|
||||||
// // 重建 datas
|
|
||||||
// pq.reMakeMemory()
|
|
||||||
// }
|
|
||||||
// pq.left--
|
|
||||||
// pq.datas[pq.left] = v
|
|
||||||
// }
|
|
||||||
|
|
||||||
idx := pq.search(v)
|
|
||||||
log.Println("idx:", idx)
|
|
||||||
if idx > pq.size/2 {
|
|
||||||
|
|
||||||
if pq.right >= len(pq.datas) {
|
|
||||||
pq.reMakeMemory()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
offset := pq.left + 1 + idx
|
if pq.comparator(v, idx.next.node.value) > 0 {
|
||||||
copy(pq.datas[offset+1:], pq.datas[offset:pq.right])
|
break
|
||||||
pq.datas[offset] = v
|
|
||||||
pq.right++
|
|
||||||
// log.Println("right: ", pq.datas)
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
if pq.left < 0 {
|
|
||||||
// 重建 datas
|
|
||||||
pq.reMakeMemory()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
offset := pq.left + 1 + idx
|
idx = idx.next
|
||||||
copy(pq.datas[pq.left:], pq.datas[pq.left+1:offset])
|
|
||||||
pq.datas[offset] = v
|
|
||||||
pq.left--
|
|
||||||
|
|
||||||
// log.Println("left: ", pq.datas)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
// cur.prev = node
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for cur.next != nil {
|
||||||
|
|
||||||
|
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++
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
cur = cur.next
|
||||||
|
}
|
||||||
|
|
||||||
|
cur.next = node
|
||||||
|
|
||||||
|
// node.prev = cur
|
||||||
pq.size++
|
pq.size++
|
||||||
log.Println("push:", pq.datas)
|
|
||||||
// if pq.isSorted {
|
|
||||||
// pq.isSorted = false
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// func (pq *PriorityQueue) PopTop() (interface{}, bool) {
|
// func (pq *PriorityQueue) Top() (interface{}, bool) {
|
||||||
|
// return pq.Get(0)
|
||||||
// return v, isok
|
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// func (pq *PriorityQueue) PopBottom() (interface{}, bool) {
|
// func (pq *PriorityQueue) Bottom() (interface{}, bool) {
|
||||||
|
// return pq.Get(pq.right - 1)
|
||||||
// return v, isok
|
|
||||||
// }
|
// }
|
||||||
|
|
||||||
func (pq *PriorityQueue) Top() (interface{}, bool) {
|
// func (pq *PriorityQueue) Get(index int) (interface{}, bool) {
|
||||||
return pq.Get(0)
|
// if index < pq.size {
|
||||||
}
|
// return pq.Values()[index], true
|
||||||
|
// }
|
||||||
func (pq *PriorityQueue) Bottom() (interface{}, bool) {
|
// return nil, false
|
||||||
return pq.Get(pq.right - 1)
|
// }
|
||||||
}
|
|
||||||
|
// func (pq *PriorityQueue) Values() []interface{} {
|
||||||
func (pq *PriorityQueue) Get(index int) (interface{}, bool) {
|
// // values := pq.datas[pq.left:pq.right]
|
||||||
if index < pq.size {
|
// // if !pq.isSorted {
|
||||||
return pq.Values()[index], true
|
// // utils.Sort(values, pq.comparator)
|
||||||
}
|
// // pq.isSorted = true
|
||||||
return nil, false
|
// // }
|
||||||
}
|
// return pq.datas[pq.left:pq.right]
|
||||||
|
|
||||||
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,10 +1,9 @@
|
|||||||
package plist
|
package plist
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"log"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/davecgh/go-spew/spew"
|
|
||||||
|
|
||||||
"github.com/emirpasic/gods/utils"
|
"github.com/emirpasic/gods/utils"
|
||||||
|
|
||||||
"github.com/Pallinder/go-randomdata"
|
"github.com/Pallinder/go-randomdata"
|
||||||
@ -12,42 +11,37 @@ import (
|
|||||||
"github.com/emirpasic/gods/trees/binaryheap"
|
"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()
|
||||||
|
|
||||||
|
for i := 0; i < 10; i++ {
|
||||||
|
h1.Push(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
h1.Values()[0] = 3
|
||||||
|
|
||||||
|
log.Println(h1)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
func TestPriorityQueue(t *testing.T) {
|
func TestPriorityQueue(t *testing.T) {
|
||||||
p := NewWithInt()
|
p := NewWithInt()
|
||||||
|
|
||||||
for i := 0; i < 20; i++ {
|
for i := 0; i < 10; i++ {
|
||||||
p.Push(randomdata.Number(0, 10000))
|
p.Push(randomdata.Number(0, 10000))
|
||||||
}
|
}
|
||||||
|
|
||||||
data := p.Values()
|
t.Error(p.String())
|
||||||
t.Error(data)
|
|
||||||
|
|
||||||
content := ""
|
|
||||||
last := 0
|
|
||||||
for i := 0; i < len(data); i++ {
|
|
||||||
if i == 0 {
|
|
||||||
content += "\n"
|
|
||||||
} else if i%5 == 0 {
|
|
||||||
content += spew.Sprintln(data[last:i])
|
|
||||||
last = i
|
|
||||||
}
|
|
||||||
}
|
|
||||||
content += spew.Sprintln(data[last:])
|
|
||||||
t.Error(content)
|
|
||||||
|
|
||||||
lleft := p.search(0)
|
|
||||||
lmid := p.search(5000)
|
|
||||||
lright := p.search(10000)
|
|
||||||
|
|
||||||
t.Error(lleft, lmid, lright)
|
|
||||||
t.Error(p.left+lleft, p.left+lmid, p.left+lright)
|
|
||||||
|
|
||||||
t.Error(p.datas, p.size, len(p.Values()))
|
|
||||||
|
|
||||||
for _, idx := range []int{5, 0, 21, 19} {
|
|
||||||
t.Error(p.Get(idx))
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkPriorityQueue(b *testing.B) {
|
func BenchmarkPriorityQueue(b *testing.B) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user