总体而言,我正在尝试使用优先级队列来实现Dijkstra的算法。
根据golang-nuts的成员所述,Go中惯用的方法是将堆接口与自定义的基础数据结构一起使用。所以我像这样创建了Node.go和PQueue.go:
//Node.go
package pqueue
type Node struct {
row int
col int
myVal int
sumVal int
}
func (n *Node) Init(r, c, mv, sv int) {
n.row = r
n.col = c
n.myVal = mv
n.sumVal = sv
}
func (n *Node) Equals(o *Node) bool {
return n.row == o.row && n.col == o.col
}
和PQueue.go:
// PQueue.go
package pqueue
import "container/vector"
import "container/heap"
type PQueue struct {
data vector.Vector
size int
}
func (pq *PQueue) Init() {
heap.Init(pq)
}
func (pq *PQueue) IsEmpty() bool {
return pq.size == 0
}
func (pq *PQueue) Push(i interface{}) {
heap.Push(pq, i)
pq.size++
}
func (pq *PQueue) Pop() interface{} {
pq.size--
return heap.Pop(pq)
}
func (pq *PQueue) Len() int {
return pq.size
}
func (pq *PQueue) Less(i, j int) bool {
I := pq.data.At(i).(Node)
J := pq.data.At(j).(Node)
return (I.sumVal + I.myVal) < (J.sumVal + J.myVal)
}
func (pq *PQueue) Swap(i, j int) {
temp := pq.data.At(i).(Node)
pq.data.Set(i, pq.data.At(j).(Node))
pq.data.Set(j, temp)
}
和main.go :(动作在SolveMatrix中)
// Euler 81
package main
import "fmt"
import "io/ioutil"
import "strings"
import "strconv"
import "./pqueue"
const MATSIZE = 5
const MATNAME = "matrix_small.txt"
func main() {
var matrix [MATSIZE][MATSIZE]int
contents, err := ioutil.ReadFile(MATNAME)
if err != nil {
panic("FILE IO ERROR!")
}
inFileStr := string(contents)
byrows := strings.Split(inFileStr, "\n", -1)
for row := 0; row < MATSIZE; row++ {
byrows[row] = (byrows[row])[0 : len(byrows[row])-1]
bycols := strings.Split(byrows[row], ",", -1)
for col := 0; col < MATSIZE; col++ {
matrix[row][col], _ = strconv.Atoi(bycols[col])
}
}
PrintMatrix(matrix)
sum, len := SolveMatrix(matrix)
fmt.Printf("len: %d, sum: %d\n", len, sum)
}
func PrintMatrix(mat [MATSIZE][MATSIZE]int) {
for r := 0; r < MATSIZE; r++ {
for c := 0; c < MATSIZE; c++ {
fmt.Printf("%d ", mat[r][c])
}
fmt.Print("\n")
}
}
func SolveMatrix(mat [MATSIZE][MATSIZE]int) (int, int) {
var PQ pqueue.PQueue
var firstNode pqueue.Node
var endNode pqueue.Node
msm1 := MATSIZE - 1
firstNode.Init(0, 0, mat[0][0], 0)
endNode.Init(msm1, msm1, mat[msm1][msm1], 0)
if PQ.IsEmpty() { // make compiler stfu about unused variable
fmt.Print("empty")
}
PQ.Push(firstNode) // problem
return 0, 0
}
问题是,在编译时我收到错误消息:
[~/Code/Euler/81] $ make
6g -o pqueue.6 Node.go PQueue.go
6g main.go
main.go:58: implicit assignment of unexported field 'row' of pqueue.Node in function argument
make: *** [all] Error 1
注释掉PQ.Push(firstNode)行确实使编译器满意。但是我不明白为什么我会首先收到错误消息。推送不会以任何方式修改参数。
更新:为了以后在搜索中遇到此问题的人,上面的代码充满了严重的误解。请在下面查看可使用的更有用的模板:Node.go:
// Node.go
package pqueue
import "fmt"
type Node struct {
row int
col int
myVal int
sumVal int
parent *Node
}
func NewNode(r, c, mv, sv int, n *Node) *Node {
return &Node{r, c, mv, sv, n}
}
func (n *Node) Eq(o *Node) bool {
return n.row == o.row && n.col == o.col
}
func (n *Node) String() string {
return fmt.Sprintf("{%d, %d, %d, %d}", n.row, n.col, n.myVal, n.sumVal)
}
func (n *Node) Row() int {
return n.row
}
func (n *Node) Col() int {
return n.col
}
func (n *Node) SetParent(p *Node) {
n.parent = p
}
func (n *Node) Parent() *Node {
return n.parent
}
func (n *Node) MyVal() int {
return n.myVal
}
func (n *Node) SumVal() int {
return n.sumVal
}
func (n *Node) SetSumVal(sv int) {
n.sumVal = sv
}
PQueue.go:
// PQueue.go
package pqueue
type PQueue []*Node
func (pq *PQueue) IsEmpty() bool {
return len(*pq) == 0
}
func (pq *PQueue) Push(i interface{}) {
a := *pq
n := len(a)
a = a[0 : n+1]
r := i.(*Node)
a[n] = r
*pq = a
}
func (pq *PQueue) Pop() interface{} {
a := *pq
*pq = a[0 : len(a)-1]
r := a[len(a)-1]
return r
}
func (pq *PQueue) Len() int {
return len(*pq)
}
// post: true iff is i less than j
func (pq *PQueue) Less(i, j int) bool {
I := (*pq)[i]
J := (*pq)[j]
return (I.sumVal + I.myVal) < (J.sumVal + J.myVal)
}
func (pq *PQueue) Swap(i, j int) {
(*pq)[i], (*pq)[j] = (*pq)[j], (*pq)[i]
}
func (pq *PQueue) String() string {
var build string = "{"
for _, v := range *pq {
build += v.String()
}
build += "}"
return build
}
package main
var PQ pqueue.PQueue
var firstNode pqueue.Node
PQ.Push(firstNode)
变量firstNode
通过值传递,这意味着在函数调用中参数将隐式分配给参数PQ.Push(firstNode)
。该类型pqueue.Node
包含私有字段,例如row
未从出口package pqueue
到package main
:“pqueue.Node的未导出字段‘行’的隐式分配的功能参数。”
在中Node.go
,将此功能添加到package pqueue
:
func NewNode() *Node {
return &Node{}
}
在中PQueue.go
,将此功能添加到package pqueue
:
func NewPQueue() *PQueue {
return &PQueue{}
}
然后。在中package main
,您可以编写:
PQ := pqueue.NewPQueue()
firstNode := pqueue.NewNode()
PQ.Push(firstNode)
我正在编写一个涉及堆实现的代码,在我的bubbleUp方法中,在我的while循环行中,我似乎遇到了一个取消引用的错误。这可能是一个相当基本的问题,但解决这个问题的最佳方法是什么?我在实现removeHigh方法时也遇到了一些问题,该方法旨在从队列中移除最高的元素。
我目前正在尝试实现min heap PQ,但是我在实现的正确性方面遇到了一些问题,我似乎无法找出我做错了什么——它没有输出最低优先级,也没有对它们进行正确排序。 使用以下测试数据: 我得到以下结果: 我希望结果是按升序排列的——起初我认为这可能是因为交换了错误的孩子,但最后一个输出是最大的优先级,所以这没有意义。我花了几个小时试图研究堆优先级队列,但我找不到任何帮助。 以下是CMP要求的更好的代码
注意:我知道可以用比较器创建优先级队列,然后重复调用Add。
我正在使用优先级队列实现Dijkstra的算法,我想要一个函数从堆中删除一个元素,但我只能从Dijkstra的主节点索引中向它发送顶点索引,我找不到它在堆上的位置,我负担不起进行二进制搜索。有什么想法吗?
问题 怎样实现一个按优先级排序的队列? 并且在这个队列上面每次 pop 操作总是返回优先级最高的那个元素 解决方案 下面的类利用 heapq 模块实现了一个简单的优先级队列: import heapq class PriorityQueue: def __init__(self): self._queue = [] self._index = 0
在谷歌搜索了几天之后,我相信我完全迷路了。我想实现一种优先级队列,它大约有3个队列: 高优先级队列(每日),需要先处理 中等优先级队列(每周),如果队列#1中没有项目,将进行处理。(此队列中的ok消息根本不处理) 低优先级队列(每月),如果队列#1中没有项目,将进行处理 最初,我有以下流程,让消费者使用所有三个队列中的消息,并检查队列#1、#2和#3中是否有任何项目。然后我意识到这是错误的,因为: