当前位置: 首页 > 面试题库 >

优先队列和堆

宰父志新
2023-03-14
问题内容

我正在尝试根据文档中提供的示例实现优先级队列。文件: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)用作堆类型。函数参数中的接口:pq.PriorityQueue没有实现堆。接口(Pop方法具有指针接收器)


问题答案:

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

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

请注意,在这段代码中,我明确地将队列初始化为指针:q := new(PriorityQueue)。这就是我传递给所有heap功能的东西。

之所以引起这种混乱,主要是因为您实际上要实现2个接口。的heap.Interfacesort.Interface(后者是现有的类型定义的一部分)。但是sort接口对于非指针接收器来说是很好的,而另一个接口则不是。

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
}


 类似资料:
  • 注意:我知道可以用比较器创建优先级队列,然后重复调用Add。

  • 我不熟悉堆,二进制堆,我试图理解为什么我们需要使用二进制堆实现优先级队列。我还了解到二进制堆的底层数据结构也是一个数组。 所以我的问题是,为什么我们不能使用一个数组,按降序(对于最大堆)或升序(对于最小堆)排序来表示优先级队列?这里我可能错了,但我认为,如果以这种方式实现,findMax、findMin、insert和delete等操作的时间复杂度将几乎保持不变。那么,我们是否可以不使用排序数组来

  • 考虑下面的优先级类声明<代码>类优先级队列 我的想法: 我能想到的一件事是,这将强制优先级队列使用对象比较器,并且不会提供实现其自定义比较器的能力,因为类的用户可能希望基于某个不同的比较器构建队列。

  • 简介 举个例子。我有一个用户表,这个表根据用户名被Hash到不同的数据库实例上,我要找出这些用户中最热门的5个,怎么做?我是这么做的: 在每个数据库实例上找出最热门的5个 将每个数据库实例上的这5条数据按照热门程度排序,最后取出前5条 这个过程看似简单,但是你应用服务器上的代码要写不少。首先需要Query N个列表,加入到一个新列表中,排序,再取前5。这个过程不但代码繁琐,而且牵涉到多个列表,非常

  • 优先级队列(Priority Queue) 注:队列是一种特征为FIFO的数据结构,每次从队列中取出的是最早加入队列中的元素。但是,许多应用需要另一种队列,每次从队列中取出的应是具有最高优先权的元素,这种队列就是优先级队列(Priority Queue),也称为优先权队列。 1. 优先级队列的概念 1.1 优先级队列的定义 优先级队列是不同于先进先出队列的另一种队列。每次从队列中取出的是具有最高优

  • 我正在编写一个涉及堆实现的代码,在我的bubbleUp方法中,在我的while循环行中,我似乎遇到了一个取消引用的错误。这可能是一个相当基本的问题,但解决这个问题的最佳方法是什么?我在实现removeHigh方法时也遇到了一些问题,该方法旨在从队列中移除最高的元素。