在python中实现支持撤消功能的队列

时间:2018-10-22 08:13:28

标签: python queue

有人要求我在python中创建一个具有以下3个命令的队列:

  • 排队
  • 流行
  • 撤消

撤消命令将撤消上一个入队或弹出命令。

这是我写的: 它需要命令的数量,然后是命令本身。 我使用第二个队列来存储第一个队列的先前状态。

from collections import deque

queue_1 = deque()
queue_2 = deque()
num_of_commands = int(input())
commands = []
for i in range(num_of_commands):
    commands.append(input())

for i in range(len(commands)):
    queue_2 = queue_1.copy()
    if 'enqueue' in commands[i]:
        queue_1.append(int((commands[i].split())[1]))
    elif 'pop' in commands[i]:
        if len(queue_1) != 0:
            print(queue_1.popleft())
    if i < len(commands) - 1:
        if ((commands[i + 1].split())[0]) == 'undo':
            queue_1 = queue_2.copy()

示例输入:

10
enqueue 1
enqueue 2
pop
undo
pop
enqueue 3
undo
pop
enqueue 10
pop

示例输出:

1
1
2
10

但是我的问题是,这不支持连续的撤消命令。如何更改它以支持多个连续的撤消命令?

1 个答案:

答案 0 :(得分:1)

这里重要的问题,是否需要“可撤销的撤销”? )

无论如何,我强烈建议将逻辑封装到单个类中,当您处理松散的对象时,很容易迷失逻辑。

让我们假设您不需要撤消撤消,这是一个粗略的实现:

class QueueWithUndo:
    def __init__(self, history=10):
        self.q = deque()
        self.undo_q = deque(maxlen=history)

    def enqueue(self, task):
        self.undo_q.append((self.q.pop, ))
        self.q.append(task)

    def pop(self):
        result = self.q.popleft()
        self.undo_q.append((self.q.append, result))
        return result

    def undo(self):
        op, *task = self.undo_q.pop()
        op(*task)

想法很简单— 1个双端队列用于任务,1个大小受限(或非大小限制)双端队列,可跟踪如何“撤消”操作。普通的任务双端队列用作FIFO队列-因此您将其附加在一侧,从另一侧弹出。撤消双端队列用作LIFO /堆栈-最后一个上下文是用于撤消事物的内容。

棘手的是,每个操作都会颠倒普通队列和队列队列,作为参数。即您需要保留弹出式撤销的上下文。