优先队列和堆 [英] Priority queue and heap

查看:157
本文介绍了优先队列和堆的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试根据文档中提供的示例实现优先级队列。
文档: priorityQueue



简而言之,它看起来像这样(不包括所有内容):

  package pq 

类型项目结构{
容器接口{}
优先级int
索引int
}

类型PriorityQueue [] *项

func NewItem(value interface {},prio int)* Item {
return& Item {container:value,priority:prio}
}

func(pq PriorityQueue )Len()int {
return len(pq)
}

func(pq PriorityQueue)Less(i,j int)bool {
return pq [i ] .priority> pq [j] .priority
}

func(pq * PriorityQueue)Swap(i,j int){
(* pq)[i],(* pq) j] =(* pq)[j],(* pq)[i]
(* pq)[i] .index = i
(* pq)[j] .index = j
}

func(pq PriorityQueue)Push(x interface {}){
fmt.Printf(adr:%p\\\
,& pq)
n := len(pq)
item:= x。(* Item)
item.index = n
pq = append(pq,item)
}

func(pq * PriorityQueue)Pop()interface {} {
old:= * pq
n:= len(old)
itm:= old [n - 1]
itm.index = -1
* pq = old [0:n-1]
return itm.container
}

main.go 文件:

  func main(){
q:= pq.PriorityQueue {}
heap.Init(q)
fmt.Printf(\\\
Adr:%p\\ \\ n,& q)
q.Push(pq.NewItem(h,2))

for i:= 0; i< 5; i ++ {
item:= pq.NewItem(test,i * 13%7)
heap.Push(q,item)
}

for q .Len()> 0 {
fmt.Println(Item:+ heap.Pop(q)。(string))
}
}

正如你可以看到,与示例比较时,我不使用指针,因为这样做会给我一个编译错误告诉我,我的优先级队列没有正确实现接口



当我这样做时,这会让我遇到以下问题:

  heap.Push(q,item)

该项未附加到队列。 p>

我试图写出队列指针地址,并显示不同的地址。这解释了为什么它不起作用,但是不能使用地图长时间不使用引用类型?



更具体地说:我如何解决我的问题? p>

希望你可以帮助!



编辑:添加完整的代码和错误:不能使用q(键入pq.PriorityQueue)作为类型heap.Interface在函数参数中:
pq.PriorityQueue不实现heap.Interface(Pop方法有指针接收器)

解决方案

如示例代码所示, Push 方法必须有一个指针接收器。



诀窍是所有对 heap.XXX 函数的调用,要求您以一个指针的形式传递堆(例如: heap.Init(& pq) )。在您发布的代码中不是这样。这是您的代码的工作版本。您可以在 Go playground 上运行。



注意,在这段代码中,我明确地将队列初始化为一个指针: q:= new(PriorityQueue)。这是我传递给所有的函数。



这里的混乱主要是因为你本质上实现2个接口
heap.Interface sort.Interface (后者是之前的类型定义的一部分) 。但是非接收器的排序界面很好,而另一个则不是。

  package main 

importfmt
importcontainer / heap

func main(){
q:= new(PriorityQueue)

heap。 Init(q)

fmt.Printf(\\\
Adr:%p\\\
,& q)
q.Push(NewItem(h,2))

for i:= 0; i< 5; i ++ {
heap.Push(q,NewItem(test,i * 13%7))
}

for q.Len()> 0 {
fmt.Println(Item:+ heap.Pop(q)。(string))
}
}

类型项目结构{
容器接口{}
优先级int
索引int
}

类型PriorityQueue [] *项

func NewItem(值接口{},prio int)* Item {
return& Item {container:value,priority:prio}
}

func(pq PriorityQueue)Len()int {
return len(pq)
}

func(pq PriorityQueue)Less(i,j int)bool {
return pq [i] .priority> pq [j] .priority
}

func(pq PriorityQueue)Swap(i,j int){
pq [i],pq [j] = pq [j] ,pq [i]
pq [i] .index = i
pq [j] .index = j
}

func(pq * PriorityQueue)Push x interface {}){
fmt.Printf(adr:%p\\\
,pq)
n:= len(* pq)
item:= x。
item.index = n
* pq = append(* pq,item)
}

func(pq * PriorityQueue)Pop()interface {} {
old:= * pq
n:= len(old)
itm:= old [n-1]
itm.index = -1
* pq = old [ 0:n-1]
return itm.container
}


I'm trying to implement a priority queue based on the example provided in the documentation. Docs: priorityQueue

In short it looks like this (not everything is included):

    package pq

    type Item struct {
        container interface{}
        priority  int
        index     int
    }

    type PriorityQueue []*Item

    func NewItem(value interface{}, prio int) *Item {
        return &Item {container: value, priority: prio}
    }

func (pq PriorityQueue) Len() int {
    return len(pq)
}

func (pq PriorityQueue) Less(i, j int) bool {
    return pq[i].priority > pq[j].priority
}

func (pq *PriorityQueue) Swap(i, j int) {
    (*pq)[i], (*pq)[j] = (*pq)[j], (*pq)[i]
    (*pq)[i].index = i
    (*pq)[j].index = j
}

    func (pq PriorityQueue) Push(x interface{}) {
        fmt.Printf("adr: %p\n", &pq)
        n := len(pq)
        item := x.(*Item)
        item.index = n
        pq = append(pq, item)
    }

func (pq *PriorityQueue) Pop() interface{} {
    old := *pq
    n := len(old)
    itm := old[n - 1]
    itm.index = -1
    *pq = old[0 : n-1]
    return itm.container
}

The main.go file:

func main() {
    q := pq.PriorityQueue{}
    heap.Init(q)
    fmt.Printf("\nAdr: %p\n", &q)
    q.Push(pq.NewItem("h", 2))

    for i := 0; i < 5; i++ {
        item := pq.NewItem("test", i * 13 % 7)
        heap.Push(q, item)
    }

    for q.Len() > 0 {
        fmt.Println("Item: " + heap.Pop(q).(string))
    }
}

As you can see when comparing to the example I do not use pointers since doing that will give me a compile error telling me that my priority queue does not implement the interface properly.

This leaves me with the following problem when I do:

heap.Push(q, item)

that the item is not appended to the queue.

I've tried to write out the queues pointer address and it shows different addresses. This explains why it does not work, but souldn't slices not be reference types a long with maps?

And more specificly: How do i solve my problem?

Hope you can help!

Edit: Added full code and error: cannot use q (type pq.PriorityQueue) as type heap.Interface in function argument: pq.PriorityQueue does not implement heap.Interface (Pop method has pointer receiver)

解决方案

As the example code shows, the Push method must have a pointer receiver.

The trick is that all the calls to heap.XXX functions, require that you pass your heap in as a pointer (e.g.: heap.Init(&pq)). This is not the case in the code you posted. Here is a working version of your code. You can run it on the Go playground.

Note that in this code, I explicitly initialize the queue as a pointer: q := new(PriorityQueue). And this is what I pass in to all the heap functions.

The confusion here arises mostly because you are essentially implementing 2 interfaces. The heap.Interface and the sort.Interface (The latter is part of the prior's type definition). But the sort interface is fine with non-pointer receivers, while the other one is not.

package main

import "fmt"
import "container/heap"

func main() {
    q := new(PriorityQueue)

    heap.Init(q)

    fmt.Printf("\nAdr: %p\n", &q)
    q.Push(NewItem("h", 2))

    for i := 0; i < 5; i++ {
        heap.Push(q, NewItem("test", i*13%7))
    }

    for q.Len() > 0 {
        fmt.Println("Item: " + heap.Pop(q).(string))
    }
}

type Item struct {
    container interface{}
    priority  int
    index     int
}

type PriorityQueue []*Item

func NewItem(value interface{}, prio int) *Item {
    return &Item{container: value, priority: prio}
}

func (pq PriorityQueue) Len() int {
    return len(pq)
}

func (pq PriorityQueue) Less(i, j int) bool {
    return pq[i].priority > pq[j].priority
}

func (pq PriorityQueue) Swap(i, j int) {
    pq[i], pq[j] = pq[j], pq[i]
    pq[i].index = i
    pq[j].index = j
}

func (pq *PriorityQueue) Push(x interface{}) {
    fmt.Printf("adr: %p\n", pq)
    n := len(*pq)
    item := x.(*Item)
    item.index = n
    *pq = append(*pq, item)
}

func (pq *PriorityQueue) Pop() interface{} {
    old := *pq
    n := len(old)
    itm := old[n-1]
    itm.index = -1
    *pq = old[0 : n-1]
    return itm.container
}

这篇关于优先队列和堆的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆