使用容器/堆实现优先级队列

2024-01-11

从整体上看,我正在尝试使用优先级队列来实现 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) 行确实可以满足编译器的要求。但我不明白为什么我首先会收到错误消息。 Push 不会以任何方式修改参数。


更新: 为了那些将来在搜索中遇到这种情况的人,上面的代码充满了严重的误解。请看下面的更有用的模板: 节点.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 to package main:“在函数参数中隐式分配 pqueue.Node 的未导出字段“行”。”

In Node.go,将此功能添加到package pqueue:

func NewNode() *Node {
    return &Node{}
}

In PQueue.go,将此功能添加到package pqueue:

func NewPQueue() *PQueue {
    return &PQueue{}
}

然后。在package main, 你可以写:

PQ := pqueue.NewPQueue()
firstNode := pqueue.NewNode()
PQ.Push(firstNode)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用容器/堆实现优先级队列 的相关文章

  • IntelliJ 2017.1.2 GOLANG 调试不适用于包中的断点

    我的应用程序由一个 main go 文件和一些包组成 当在 main go 中命中断点时 IntelliJ 按预期工作 显示变量值等 但是 当在不同的包中设置断点时 除了被命中之外 不会显示任何变量 并且不会跳过 进入功能按预期工作 被击中
  • 读取一个文本文件,替换其中的单词,输出到另一个文本文件

    所以我试图在 GO 中编写一个程序来获取一个充满代码的文本文件并将其转换为 GO 代码 然后将该文件保存到 GO 文件或文本文件中 我一直在试图弄清楚如何保存对文本文件所做的更改 但我可以看到更改的唯一方法是通过 println 语句 因为
  • 使用 Golang 通道处理 HTTP 请求

    我正在尝试构建一个简单的 Golang Appengine 应用程序 它使用通道来处理每个 http 请求 原因是我希望每个请求执行合理的大型内存计算 并且每个请求都以线程安全的方式执行 即来自并发请求的计算不会混合 这一点很重要 本质上
  • formatFloat :将浮点数转换为字符串[重复]

    这个问题在这里已经有答案了 http golang org pkg strconv http golang org pkg strconv http play golang org p 4VNRgW8WoB http play golang
  • 当所有通道都关闭时中断 select 语句

    我有两个独立生成数据的 goroutine 每个将其发送到一个通道 在我的主 goroutine 中 我想在每个输出进入时使用它们 但不关心它们进入的顺序 每个通道在耗尽其输出时都会自行关闭 虽然 select 语句是像这样独立使用输入的最
  • 在 Go 中修改导入的库

    我的问题 弹性节拍 https www elastic co products beats是一个用 Go 编写的日志传送程序的开源项目 它具有多种日志输出功能 包括控制台 Elasticsearch 和 Redis 我想将我自己的输出添加到
  • Golang 网络爬虫 NTLM 身份验证

    Golang 网络抓取工具需要从经过 NTLM 验证的网页中提取信息 有了有效的用户名和密码 网络抓取工具如何与服务器进行 NTLM 4 次握手 以获得对后面受保护网页的访问权限 url username password http www
  • Golang标志:忽略丢失的标志并解析多个重复的标志

    我是 Golang 新手 一直无法使用 flag 找到这个问题的解决方案 如何使用 flag 以便我的程序可以处理此类调用 其中 term 标志可能出现可变次数 包括 0 次 myprogram f flag1 myprogram f fl
  • Go中如何从json字符串中获取键值

    我想尝试从 Go 中的 JSON 获取键值 但我不确定如何操作 我已经能够使用 simplejson 读取 json 值 但是我无法找到如何获取键值 有人能指出我正确的方向和 或帮助我吗 谢谢你 您可以通过执行以下操作来获取 JSON 结构
  • 如何在 Go 应用程序中处理打开/关闭数据库连接?

    我的 Web API 应用程序中有一组函数 他们对 Postgres 数据库中的数据执行一些操作 func CreateUser db err sql Open postgres user postgres password passwor
  • for 循环初始值设定项中的结构

    知道为什么 for 循环初始值设定项中的这个结构表达式在编译时会出现语法错误吗 在这种情况下 指向结构的指针工作正常 但 ofc 我需要如下所示的局部变量 感谢您的建议 type Request struct id int line byt
  • 如何在 Go 中解组具有多个项目的简单 xml?

    我想从以下 xml 中获取人物 People 的一部分
  • 我怎么知道我的所有 goroutine 确实正在使用 golang 的同步包等待一个条件

    我有一个应用程序 我正在创建多个 goroutine 来同时执行某个任务 所有工作协程都会等待条件 事件发生 一旦事件被触发 它们就会开始执行 创建完所有goroutines后 主线程在发送广播信号之前应该知道所有goroutines确实处
  • 鸭子在 Go 中打字

    我想写一个Join函数接受任意对象String 方法 package main import fmt strings type myint int func i myint String string return fmt Sprintf
  • 模板中的 bson.ObjectId

    我有一个具有 bson ObjectId 类型的结构 例如如下所示 type Test struct Id bson ObjectId Name string Foo string 我想在 html 模板中呈现它 Name Food a h
  • 打印到 stdout 会导致阻塞的 goroutine 运行吗?

    作为一个愚蠢的基本线程练习 我一直在尝试实现理发师睡觉的问题 http en wikipedia org wiki Sleeping barber problem在戈兰 对于通道来说 这应该很容易 但我遇到了一个 heisenbug 也就是
  • 这两种方式哪一种是惯用的方式? time.Sleep() 还是自动收报机?

    我必须每分钟执行一些语句 我不确定我应该遵循以下哪一项 如果有人能解释内存和 CPU 方面的优缺点 那就太好了 时间 Sleep func main go func for time Sleep time Minute fmt Printl
  • GoLang ssh:尽管将其设置为 nil,但仍出现“必须指定 HosKeyCallback”错误

    我正在尝试使用 GoLang 连接到远程服务器 在客户端配置中 除了用户和密码之外 我将 HostKeyCallback 设置为 nil 以便它接受每个主机 config ssh ClientConfig User user HostKey
  • go中有memset的类似物吗?

    在 C 中 我可以使用某些值初始化数组memset https msdn microsoft com en us library aa246471 28v vs 60 29 aspx const int MAX 1000000 int is
  • 如何将 SQLite 数据库捆绑到 Go 二进制文件中?

    我尝试使用 go bindata 和 packr 但这些包没有显示如何将 SQLite 数据库文件打包到二进制文件中 我不需要以任何方式更新数据库 我只想在启动时从中读取数据 如何将 SQLite 数据库文件嵌入到 Go 二进制文件中 SQ

随机推荐

  • 在 Android 中使用 MQTT 的基本步骤

    我是 Android 新手 希望使用 MQTT 作为来自服务器的 Android 推送通知程序 我读过有关 MQTT 的内容 但不太了解 如果有人使用过这个库 请告诉我我必须做什么才能开始使用它 我有一个 Java 服务器 在 Window
  • Javascript - 生成范围内的随机数,不包括某些数字

    基本上我正在创建一个网格并在其上绘制点 并且没有两个点可以位于完全相同的位置 3 4 与 4 3 不同 y 坐标必须在 2 和 7 之间 因此 2 3 4 5 6 7 x 坐标必须在 1 和 7 之间 我有一个 getRandom 函数 如
  • Python:BaseHTTPRequestHandler - 阅读原始文章

    如何阅读原始 http 帖子 STRING 我找到了几种用于读取帖子的解析版本的解决方案 但是我正在处理的项目提交了没有标头的原始 xml 有效负载 所以我试图找到一种方法来读取发布数据 而不将其解析为键 gt 值数组 self rfile
  • ByteBuffer 到 bigdecimal、二进制、字符串

    请检查本文底部的编辑我有一个字节缓冲区 128 位 其中有数字 我需要将其转换为大十进制 二进制 字符串 因为这些是使用 jdbc 时相应的 sql 映射 我可以使用库 API 来执行此操作吗 我看到 String valueof 不接受字
  • PHP CS Fixer File Watcher 导致 PHPStorm 中的文件缓存冲突

    I use a 文件观察者定义为这样 这是我的watchers xml file
  • 查找窗口错误 183

    有谁知道什么会导致FindWindow http msdn microsoft com en us library windows desktop ms633499 28v vs 85 29 aspx返回错误的函数 ALREADY EXIS
  • Flutter Web中如何获取本地IP

    我正在尝试在 Flutter Web 应用程序中获取本地 IP 地址 在互联网上搜索我发现了这个包 get ip0 4 0 它声明它正在网络下工作 我有这个功能 Future
  • C# 在运行时启用/禁用网络跟踪?

    在示例中 我可以发现跟踪是通过配置文件启用的 例如
  • 正确使用cudaDeviceReset()

    由于我怀疑 黑匣子 GPU 在一些较大的代码中没有完全关闭 其他人也许也是 https stackoverflow com questions 10294595 handling ctrlc exception with gpu 我会包括一
  • php - array_fill 负索引

    使用时php 数组填充 http php net manual en function array fill php和负指数 为什么php只填充第一个负索引 然后跳转到0 例如 array fill 4 4 10 应该填满 4 3 2 1
  • Windows 8 Consumer Preview + Visual Studio 11 Developer Preview 中的套接字 BUG

    我正在 Visual Studio 11 开发人员预览版中编写一个应用程序 在该应用程序使用 reader InputStreamOptions InputStreamOptions Partial 运行一段时间后出现此错误 选项集 An
  • Docker 镜像损坏?删除图层?

    系统重新启动后 现有的 docker 映像似乎已损坏 我尝试了以下方法 在该机器内重建一个泊坞窗 这有效 该图像运行良好 我拉了一个已经存在的图像 它说图层已经存在 但这个图像似乎仍然被损坏了 我觉得删除图像会有帮助 当我尝试删除时 似乎只
  • Pandas-创建一个新列,填充另一列中的观察数量

    我有一个 DataFrame 对象df 中的列值之一df is ID有许多行具有相同的 ID 我想创建一个新列num totals计算每个 ID 的观察次数 例如 这样的事情 ID Num Totals 1 3 1 3 1 3 2 2 2
  • 如何使用 Jersey (JAX-RS 2.0) 客户端启用 gzip 压缩以进行内容编码?

    我有一个使用 JAX RS 2 0 的 Jersey 实现的 Java 应用程序 我想在客户端启用 gzip 压缩 服务器已启用它 并且我已通过在 Chrome 中查看开发人员工具中客户端正在使用的特定 URL 的 大小 内容 来验证这一点
  • 自定义 UITextField 委托设置为 self 启动无限循环

    我正在编写 iPhone 应用程序 其中需要自定义 UITextField 类 对于我的文本字段 我需要缩进 文本之前的图像和最大字符数 为此 我创建了基于 UITextField 的自定义类 我所有的文本字段都将基于这个新类 我使用 Go
  • 如何从 Javascript 中的 HH:MM AM 时间字符串中减去小时?

    从格式如下的时间字符串中减去几个小时的最佳方法是什么 8 32 AM 我考虑过在冒号处拆分字符串 但是当从上午 1 00 减去 3 小时时 我得到 2 00 AM 而不是所需的晚上 10 00 最可靠的方法是将其转换为JS日期对象 然后你对
  • CMake 错误:在 Windows 上执行 make 失败

    我在尝试构建时遇到错误纳米信息项目 https github com nanomsg nanomsg在 Windows 7 中 cmake Building for NMake Makefiles The C compiler identi
  • 如何在php中验证正确的域名和子域

    如何去除www and validate有效的域名 有效域名 domain com subdomain domain com sub domain domain com 无效域名 www domain com www subdomain d
  • 我验证用户 Android 应用内订阅的步骤是否正确?

    我正在制作一个不需要用户帐户 登录的应用程序 并允许用户购买订阅 我想使用 Google Play 开发者 API 来验证用户是否已购买 有效订阅 从所有文档中 我收集了以下步骤 它们是否正确 您能回答其中的两个问题吗 创建一个服务帐号 h
  • 使用容器/堆实现优先级队列

    从整体上看 我正在尝试使用优先级队列来实现 Dijkstra 算法 根据 golang nuts 成员的说法 在 Go 中执行此操作的惯用方法是使用具有自定义底层数据结构的堆接口 所以我创建了 Node go 和 PQueue go 如下所