使用 Memento 进行撤消/重做:堆栈、队列还是仅使用 LinkedList?
实现 Memento 模式(用于撤消/重做)时最好的是什么
在女巫集合中 保留纪念品?
基本上,我需要这个(c =更改,u =撤消,r =重做):
0
*c
-1 0
*c
-2 -1 0
*c
-3 -2 -1 0
<u
-2 -1 0 1
*c
-3 -2 -1 0
变体:
- LinkedList - 原则上可能,可能没有优化。
- 队列 - IMO,不适合此任务。
- 堆栈 - 不适合撤消和重做;
- 双栈 - 也许是最佳选择,但无法控制撤消最大大小。
What is the best having when implementing Memento pattern (for Undo/Redo)
in witch collection to Keep Mementos?
Basically, I need this(c = change, u = undo, r = redo):
0
*c
-1 0
*c
-2 -1 0
*c
-3 -2 -1 0
<u
-2 -1 0 1
*c
-3 -2 -1 0
Variants:
- LinkedList - possible in principle, maybe not optimized.
- Queue - not adapted for this task, IMO.
- Stack - not adapted for undo AND redo;
- Double Stack - maybe optimal, but can't control the undo maximum size.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
最后我用了LinkedList
Finally, I used LinkedList
优选地使用双端队列来有效地支持撤消重做操作。当用户输入单词时,节点被插入到队列中,并且头指针指向当前位置。当触发撤消操作时,只需将头移动到前一个节点,并在重做操作时将头指针移动到列表中的下一个位置。如果进行编辑操作,则删除 head 右侧的所有节点并插入到 head 的末尾。这样我们就可以以O(1)时间复杂度执行撤消重做。
A double ended queue is used preferably to support undo redo operations efficiently. As the user types words, nodes are inserted into the queue and head pointer points to the current location. When an undo operation is triggered, just move the head to the previous node and on redo operation move the head pointer to next location in the list. In case of edit operation, remove all the nodes to the right of head and insert at the end of head. This way we can perform undo redo in O(1) time complexity.
当您撤消时,您将希望恢复到最近覆盖的数据。因此,您要使用的纪念品将是最后添加到集合中的纪念品。由于堆栈是后进先出 (LIFO),因此它们应该非常适合您的意图。
注意:您可能需要研究命令模式,因为它对于实现撤消功能非常有用。
编辑:没有注意到你想要重做。从堆栈中弹出内容将会清除它,因此这对您的目的没有多大用处。链接列表应该可以工作。
When you undo you are going to want to revert to the most recently overwritten data. So the memento you will want to use will be the last one added to the collection. As stacks are last in first out (LIFO) they should be ideal for your intentions.
Note: you might want to look into the command pattern as it is very useful for implementing undo functionality.
Edit: did not notice that you wanted redo. Popping stuff off your stack will get rid of it so that will not be of much use for your purposes. Linked list should work.
您是否希望用户能够选择多个项目进行撤消或重做?
如果是这种情况,那么您可能需要使用通用 List 或 ObservableCollection(如果是 WPF/Silverlight),以便可以在 UI 中显示项目。您可以使用两个列表:一个用于撤消,一个用于重做。
Do you want the user to be able to select more than one item for undo or redo?
If that is the case, then you would want to use a generic List or ObservableCollection (if WPF/Silverlight) so that the items could be displayed in the UI. You could use two lists: one for undo and one for redo.
使用双向链表。当用户使用撤消/重做时,他们可能会多次索引状态(例如,执行 4 次撤消,然后意识到他们走得太远并执行重做)。单个堆栈或队列不支持这一点。
两个堆栈将支持撤消和重做,但我认为使用它们有点浪费。一旦用户执行编辑(创建新的备忘录),所有重做备忘录最终都会被删除。因此,应用程序运行的大多数时间不会有“重做”纪念品。
假设您在标记为 .net 后进行了垃圾收集:
当用户进行编辑时,您需要对双向链表执行的操作是将链表的头引用设置为当前备忘录。如果您使用堆栈,那么您必须创建一个新堆栈或弹出其中的所有内容,以便 gc 释放重做备忘录。
Use a doubly-linked list. When users are using undo/redo they may index the state several times (e.g. do 4 undos, then realize they went too far and do a redo). A single stack or a queue won't support that.
Two stacks will support undo and redo, but I think using them is kind of a waste. All redo mementos will end up being deleted as soon as the user performs an edit (that creates a new memento). So, most of the time an application is running there will be no 'redo' mementos.
Assuming you have garbage collection since you tagged it .net:
When a user makes an edit all you'll have to do with the doubly-linked list is set the head reference of the linked list to the current memento. If you use a stack then you'll have to either create a new stack or pop everything off it in order for the gc to free the redo mementos.