优先级队列和堆

时间:2014-03-20 19:19:10

标签: data-structures go

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

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

    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
}

main.go文件:

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))
    }
}

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

当我这样做时,这给我留下了以下问题:

heap.Push(q, item)

该项目未附加到队列中。

我试图写出队列指针地址,它显示不同的地址。这就解释了为什么它不起作用,但是对于地图而言,不能将参考类型作为参考类型吗?

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

希望你能帮忙!

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

1 个答案:

答案 0 :(得分:3)

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

诀窍是对heap.XXX函数的所有调用都要求你将堆作为指针传递(例如:heap.Init(&pq))。您发布的代码中的情况并非如此。这是您的代码的工作版本。您可以在Go playground上运行它。

请注意,在此代码中,我将队列显式初始化为指针:q := new(PriorityQueue)。这就是我传递给所有heap函数的内容。

这里出现的混乱主要是因为你实际上是在实现2个接口。 heap.Interfacesort.Interface(后者是先前类型定义的一部分)。但是对于非指针接收器,排序接口很好,而另一个不是。

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
}