我正在自学麻省理工学院的算法导论:http://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-006-introduction-to-algorithms-fall-2011/index.htm
我怀疑不是概念性的。更多的是为什么技术上正确且从CSLR中取出的解决方案无法使用问题集2中提供的特定测试代码。我相信这将有助于将来尝试自学该课程的任何人。
在问题集2中,有一个编码练习,其中需要将基于数组的优先级队列实现(Python类)重写为基于堆的优先级队列实现。可以在此处获取问题集和解决方案:http://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-006-introduction-to-algorithms-fall-2011/assignments/
所以这是麻省理工学院提供的解决方案:
class PriorityQueue:
"""Heap-based priority queue implementation."""
def __init__(self):
"""Initially empty priority queue."""
self.heap = [None]
def __len__(self):
# Number of elements in the queue.
return len(self.heap) - 1
def append(self, key):
"""Inserts an element in the priority queue."""
if key is None:
raise ValueError('Cannot insert None in the queue')
i = len(self.heap)
self.heap.append(key)
while i > 1:
parent = i // 2
if key < self.heap[parent]:
self.heap[i], self.heap[parent] = self.heap[parent], key
i = parent
else:
break
def min(self):
"""Returns the smallest element in the queue."""
return self.heap[1]
def pop(self):
"""Removes the minimum element in the queue.
Returns:
The value of the removed element.
"""
heap = self.heap
popped_key = heap[1]
if len(heap) == 2:
return heap.pop()
heap[1] = key = heap.pop()
i = 1
while True:
left = i * 2
if len(heap) <= left:
break
left_key = heap[left]
right = i * 2 + 1
right_key = right < len(heap) and heap[right]
if right_key and right_key < left_key:
child_key = right_key
child = right
else:
child_key = left_key
child = left
if key <= child_key:
break
self.heap[i], self.heap[child] = child_key, key
i = child
return popped_key
根据我从CSLR学习的内容,这是我的解决方案:
class PriorityQueue:
"""binary min-heap implementation of priority-queue"""
def __init__(self):
"""Initially empty priority queue."""
self.heap = []
def __len__(self):
# Number of elements in the heap.
return len(self.heap)
def parent(self, i):
return i // 2
def left(self, i):
return 2*i
def right(self, i):
return 2*i + 1
def decreaseKey(self, i, key):
currentKey = self.heap[i]
if key > currentKey:
raise ValueError("New key is larger than current key")
currentKey = key
parentKey = self.heap[self.parent(i)]
while i > 1 and parentKey > currentKey:
currentKey, parentKey = parentKey, currentKey
i = self.parent(i)
def append(self, key):
"""Inserts an element in the priority heap."""
if key is None:
raise ValueError('Cannot insert None in the heap')
self.heap.append(float("inf"))
self.decreaseKey(len(self.heap) - 1, key)
def min(self):
"""The smallest element in the heap."""
if len(self.heap) == 0:
return None
return self.heap[0]
def pop(self):
"""Removes the minimum element in the heap.
Returns:
The value of the removed element.
"""
if len(self.heap) == 0:
return None
min = self.min()
self.heap[0] = self.heap[-1]
self.minHeapify(0)
return min
def minHeapify(self, i):
l = self.left(i)
r = self.right(i)
leftKey = self.heap[l]
rightKey = self.heap[r]
currentKey = self.heap[i]
heapSize = len(self.heap)
if l < heapSize and leftKey < currentKey:
smallest = l
else:
smallest = i
if r <= heapSize and rightKey < smallest:
smallest = r
if smallest != i:
currentKey, self.heap[smallest] = self.heap[smallest], currentKey
self.minHeapify(smallest)
我得到的错误是:
Traceback (most recent call last):
File "circuit.py", line 659, in <module>
sim.run()
File "circuit.py", line 541, in run
in_transition[0]))
File "circuit.py", line 382, in append
self.decreaseKey(len(self.heap) - 1, key)
File "circuit.py", line 367, in decreaseKey
if key > currentKey:
File "circuit.py", line 300, in __gt__
return (self.time > other.time or
AttributeError: 'float' object has no attribute 'time'
我认为这意味着当我在类PriorityQueue(我创建的)的属性之间进行比较时,它是出于某种原因使用先前定义的类的__gt__方法,称为Transition。
除此之外,当我将提供的解决方案与我自己的解决方案(基于CSLR)进行比较时,他们基本上都在做同样的事情。
答案 0 :(得分:1)
self.heap
应包含Transition
个对象(具有time
属性)。
在PriorityQueue.append
中,您插入float
,而Transition
对象应该是time
对象,其def append(self, key):
"""Inserts an element in the priority heap."""
if key is None:
raise ValueError('Cannot insert None in the heap')
self.heap.append(Transition(gate, new_output, float("inf")))
self.decreaseKey(len(self.heap) - 1, key)
属性设置为无穷大。
gate
编辑:也许我需要准确一点,虽然这应该可以解决问题,但我认为不应该这样做。官方修正仍然更好。
Edit2:当然,您需要将new_output
和[2,3,-2,4]
替换为合理的值。
答案 1 :(得分:0)
问题可能与您i > 1
中的比较decreaseKey
有关。鉴于根位于索引0,比较1而不是0是非常奇怪的。当1处的子节点低于根时,代码将无法交换它们。
麻省理工学院提供的解决方案具有相同的奇怪比较,但他们通过在索引0(注意self.heap = [None]
和return len(self.heap) - 1
)放置一个死元素来证明它的合理性,因此它们的根确实是1。