如何避免优先级队列中的饥饿
Posted
技术标签:
【中文标题】如何避免优先级队列中的饥饿【英文标题】:How to avoid starvation in a priority queue 【发布时间】:2018-08-24 23:40:47 【问题描述】:我正在尝试创建一个队列,以避免队列中的元素时间过长。我正在使用链接列表。我想要实现它的方式是,如果添加更高的优先级,则被推送的优先级会添加 0.4。我还需要为链表实现排序,但这已经很有意义了。我真的不明白我应该如何将这个 0.4 添加到已被取代的优先级中。
class Node:
def __init__(self, data=None):
self.data = data
self.next = None
class LinkedList:
def __init__(self,):
self.head = Node()
def append(self, data):
new_node = Node(data)
current = self.head
while current.next is not None:
current = current.next
current.next = new_node
def __str__(self):
data = []
current = self.head
while current is not None:
data.append(current.data)
current = current.next
return "[%s]" %(', '.join(str(i) for i in data))
def __repr__(self):
return self.__str__()
def length(self):
current = self.head
total = 0
while current.next is not None:
total += 1
current = current.next
return total
def display(self):
elements = []
current_node = self.head
while current_node.next is not None:
current_node = current_node.next
elements.append(current_node.data)
print("Elements ", elements)
def get(self, index):
if index >= self.length():
print("Error: Index is out of range!")
return None
current_index = 0
current_node = self.head
while True:
current_node = current_node.next
if current_index == index:
return current_node.data
current_index += 1
def remove(self):
current = self.head
if current is not None:
self.head = current.next
else:
print("Queue is empty!")
def main():
queue = LinkedList()
queue.append(5)
queue.append(2)
queue.display()
main()
【问题讨论】:
编写一个函数,将其命名为get_true_priority(base_priority, age)
,这样它就会产生“避免饥饿”的有用输出(可能还有一些其他规则应该遵守,例如单调的年龄?)。这个函数可以绘制在图表上,我可能会首先绘制我“预期”它如何工作的图表,然后将其返回到代码中。
你不需要链表,Python list
就可以了。您的班级需要 2 个结构:一个按当前优先级对项目进行排序或堆积,另一个 - 按剩余时间“直到添加另一个 0.4”。更新优先级得到更新的项目的列表位置。
【参考方案1】:
我建议使用 python 的heapq 而不是链表。因为您正在进行自定义比较,所以您可能希望实现类似于heapq with custom compare predicate 中描述的内容。
除了优先级之外,添加一个包含项目添加到堆中的时间的字段。然后,您的实际优先级是分配的优先级和项目在堆中的时间长度的函数。例如,优先级可能是这样的:
elapsed_time = current_time - added_time;
real_priority = assigned_priority * elapsed_time;
您可能希望将乘数设为已用时间的一小部分。
另一种可能性是,如果您想确保某些东西在队列中的停留时间不会超过某个设定的时间。例如,如果您想确保事情不会停留超过 5 分钟,您可以添加 dequeue_time
字段。然后你的比较变成这样:
// assume items a and b are being compared
if (a.dequeue_time < current_time)
if (b.dequeue_time < a.dequeue_time)
// b sorts before a
else if (b.dequeue_time > a.dequeue_time)
// return a sorts before b
else // dequeue times are equal
return result of comparing a.priority to b.priority
else
// here, return result of comparing a.priority and b.priority
heapq 将比您的链表更有效,尤其是当您的队列中的项目数量增加时。另外,它已经被编写并且已知工作。只需提供比较功能即可。
【讨论】:
以上是关于如何避免优先级队列中的饥饿的主要内容,如果未能解决你的问题,请参考以下文章
使用最小优先级队列时,如何跟踪 Dijkstra 算法中的最短路径?