Python:在优先队列实现中使用我的堆

Posted

技术标签:

【中文标题】Python:在优先队列实现中使用我的堆【英文标题】:Python: Using my heap in a priority queue implementation 【发布时间】:2015-04-27 23:04:09 【问题描述】:

我在使用要在优先队列类中使用的定制堆类函数时遇到了真正的麻烦。我的堆类中的哪些函数用于我的 PriorityQueue 的“入队”、“出队”、“前”和“大小”函数时遇到问题。我知道对于“入队”,我需要使用我的插入功能,但我不知道该怎么做,因为我有优先权。有人可以帮我解决我需要做什么才能让我的 PriorityQueue 类使用我的 Heap 类中的函数以便正常工作吗?我一直坚持这个问题,我一直在寻找答案,包括使用内置的 python 函数,如 queue 和 heapq。

类堆(对象):

    def __init__(self, items=None):

        '''Post: A heap is created with specified items.'''

        self.heap = [None]
        if items is None:
            self.heap_size = 0
        else:
            self.heap += items
            self.heap_size = len(items)
            self._build_heap()

    def size(self):

        '''Post: Returns the number of items in the heap.'''

        return self.heap_size

    def _heapify(self, position):

        '''Pre: Items from 0 to position - 1 satisfy the Heap property.
       Post: Heap Property is satisfied for the entire heap.'''

        item = self.heap[position]
        while position * 2 <= self.heap_size:
            child = position * 2
            # If the right child, determine the maximum of two children.
            if (child != self.heap_size and self.heap[child+1] > self.heap[child]):
                child += 1
            if self.heap[child] > item:
                self.heap[position] = self.heap[child]
                position = child
            else:
                break
        self.heap[position] = item

    def delete_max(self):

        '''Pre: Heap property is satisfied
       Post: Maximum element in heap is removed and returned. '''

        if self.heap_size > 0:
            max_item = self.heap[1]
            self.heap[1] = self.heap[self.heap_size]
            self.heap_size -= 1
            self.heap.pop()
            if self.heap_size > 0:
                self._heapify(1)
            return max_item

    def insert(self, item):

        '''Pre: Heap Property is Satisfied.
       Post: Item is inserted in proper location in heap.'''

        self.heap_size += 1
        # extend the length of the list.
        self.heap.append(None)
        position = self.heap_size
        parent = position // 2
        while parent > 0 and self.heap[parent] < item:
            # Move the item down.
            self.heap[position] = self.heap[parent]
            position = parent
            parent = position // 2
        # Puts the new item in the correct spot.
        self.heap[position] = item

    def _build_heap(self):

        ''' Pre: Self.heap has values in 1 to self.heap_size
           Post: Heap property is satisfied for entire heap. '''

        # 1 through self.heap_size.

        for i in range(self.heap_size // 2, 0, -1): # Stops at 1.
            self._heapify(i)

    def heapsort(self):

        '''Pre: Heap Property is satisfied.
           Post: Items are sorted in self.heap[1:self.sorted_size].'''

        sorted_size = self.heap_size

        for i in range(0, sorted_size -1):
            # Since delete_max calls pop to remove an item, we need to append a dummy value to avoid an illegal index.
            self.heap.append(None)
            item = self.delete_max()
            self.heap[sorted_size - i] = item

所以这是可行的,但就像我之前所说的那样,我在如何从中创建优先级队列时遇到了麻烦?我知道要求代码是错误的,但是我很绝望,有人可以在这里帮助我吗?我对我希望我的优先代码做什么有基本的了解..

#PriorityQueue.py
from MyHeap import Heap


class PriorityQueue(object):

    def __init__(self):
        self.heap = None

    def enqueue(self, item, priority):
        '''Post: Item is inserted with specified priority in the PQ.'''
        self.heap.insert((priority, item))

    def first(self):
    '''Post: Returns but does not remove the highest priority item from the PQ.'''
        return self.heap[0]

    def dequeue(self):
    '''Post: Removes and returns the highest priority item from the PQ.'''
    if self.heap is None:
        raise ValueError("This queue is empty.")
    self.heap.delete_max()

    def size(self):
    '''Post: Returns the number of items in the PQ.'''
        return self.size

这是我到目前为止得到的,但我不知道它是否完全正确。谁能帮帮我?

我将代码编辑为最​​新版本。

【问题讨论】:

您是否遇到特定问题?确定代码是否正确的最好方法是对其进行测试。但是,从表面上看,dequeue 并没有像它所说的那样返回最高优先级的项目,而是只是删除它。显然 first 仍然没有实现(提示:它是单行的)。 我需要创建一个 init 函数吗?像这样的东西? def __init__(self): self.head = None 然后为前面做这个? def first(self): return self.head[0] ? 你完全在正确的轨道上,但你为什么需要一个self.head?你已经有了self.heap,最大值只能在堆中的一个特定位置......(虽然init函数通常对所有类来说都是一件好事 - 我不完全确定你是如何'正在初始化 self.heap 没有一个) @seaotternerd 好的,我想我明白你的意思了。我编辑了我的代码,你能看看到目前为止你觉得合适吗? 是的,这看起来很适合 first()。您需要添加类似于 dequeue 的内容,以便可以返回已删除的项目。此外,当您可以只使用堆的 size() 方法时,不为 PriorityQueue 类维护单独的大小变量可能更简单。 【参考方案1】:

由于这大概是家庭作业,我所能做的就是给出提示,这通常作为 cmets 更容易完成。由于这最终成为了一系列相当彻底的提示,因此我在这里将它们总结为答案。

在大多数情况下,PriorityQueue 类中的方法将映射到您已经在 Heap 类中实现的方法:

PriorityQueue.enqueue() 很容易映射到 Heap.insert() PriorityQueue.first() 没有对应的堆方法,但是还是可以一行实现的。您只需要返回最大值,该最大值将始终位于堆中的特定位置。 PriorityQueue.dequeue() 有点复杂。需要先保存top item的值,以便调用heap.delete_max()后返回 堆类已经有一个size() 方法,PriorityQueue.size() 可以调用它,而不是在PriorityQueue 类中维护一个单独的大小变量。

此外,您需要一个 init 函数,这应该会创建一个新的 Heap 对象,该对象将由该类维护。

为了创建一个迭代器,您需要创建一个新类。它将需要维护一个整数变量(我们称之为self.index),指示其当前在队列中的位置。您还需要一个增加self.index 并返回先前索引位置的值的方法。应该是这样的。

【讨论】:

以上是关于Python:在优先队列实现中使用我的堆的主要内容,如果未能解决你的问题,请参考以下文章

基于event 实现的线程安全的优先队列(python实现)

《算法》笔记 6 - 优先队列与堆排序

Python中heapq与优先队列详细

JavaScript实现堆

JavaScript实现堆

.NET 6 优先队列 PriorityQueue