简体   繁体   中英

Implement a queue in python that supports undo feature

I've been asked to create a queue in python that has these 3 commands:

  • enqueue
  • pop
  • undo

The undo command will undo the previous enqueue or pop command.

Here's what I've written: It takes the number of commands and then the commands themselves. I used the second queue to store the previous state of the first queue.

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()

Example input:

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

Example output:

1
1
2
10

But my problem is that this doesn't support consecutive undo commands. How can I change it to support multiple consecutive undo commands?

Important question here, if you need to have "undoable undo"? )

In any case, I highly recommend encapsulating logic into single class, it's easy to get lost with logic while you're manipulating loose objects.

Lets assume you don't need to undo undos, a little bit sketchy implementation:

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)

Idea is simple — 1 deque for tasks, 1 size-restricted (or not) deque that keeps tracking on how to "undo" operations. Normal task deque is used as FIFO queue — so you append on one side, pop from opposite. Undo deque is used as LIFO/stack — last context is what used to undo things.

The tricky thing is that normal and unto queues are inverted every operation, as well as arguments. Ie you need to keep context for pop undo.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM