你们应该都使用过浏览器的后退和前进功能,它就是咱们今天的主题:撤销和回退。其实不光是在浏览器里面,在众多的工具软件内也都有相似的功能,远的不说,例如:vscode、ppt。git
在说实现思路以前,我先上一张图:github
为了更直观的展现,我用点击小球代替了对网站的访问。算法
A 为红色小球;B 为绿色小球;C 为蓝色小球浏览器
为何叫它是特殊的栈呢,由于传统的栈是没有 #shift() 功能的。那这里为何须要有这个函数呢,请带着问题继续往下看。bash
这里偷懒直接使用了 Array 的内置函数,传统上来说的话不该该使用 - -#数据结构
function createStack() {
var list = [];
return {
/** * 入栈 * @param {*} data */
push(data) {
list.push(data);
},
/** * 出栈 */
pop() {
return list.pop();
},
size() {
return list.length;
},
empty() {
return list.length === 0;
},
clear() {
list = [];
},
//删除头结点(栈底)
shift() {
list.shift();
},
peek() {
return list[list.length - 1];
},
getList() {
return list;
}
}
}
复制代码
function createRecord() {
let undoStack = createStack();
let rollbackStack = createStack();
const MAX_LIMIT = 6;//最大限制点
return {
//获取可撤销栈 栈顶的数据
//用于展现
getTopValue() {
return undoStack.peek();
},
//添加记录
//把数据直接添加到可撤销栈内
//而且清空可回退栈
addRecord(data) {
//当可撤销栈的大小大于最大的限制的话
//那么须要删除头结点
if (undoStack.size() >= MAX_LIMIT) {
undoStack.shift();
}
undoStack.push(data);
rollbackStack.clear();
},
//撤销
//检测可撤销栈是否为空,为空的话什么也不作
//否则把可撤销栈出栈的数据添加到可回退栈内
undoRecord() {
if (undoStack.empty()) return;
const data = undoStack.pop();
rollbackStack.push(data);
},
//回退
//检测可回退栈是否为空,为空的话什么也不作
//把可回退栈出栈的数据添加到可撤销栈内
rollbackRecord() {
if (rollbackStack.empty()) return;
const data = rollbackStack.pop();
undoStack.push(data);
},
getUndoStack() {
return undoStack.getList();
},
getrollbackStack() {
return rollbackStack.getList();
}
}
}
复制代码
咱们在使用 vscode 写代码的时候有没有发现撤销到必定的数量时,就撤销不回去了。是的,这个逻辑就是在 #addRecord() 内处理的。当‘可撤销栈’的大小大于限制数时,那么须要抛弃掉最初的数据,也就是删除头结点。这也是说明为何咱们实现的 Stack 内有 #shift() 功能。数据结构和算法
以上的逻辑我也是在公司项目逻辑中抽离出来的,由于接手的好几个项目都要实现此功能。固然了公司项目中我又加了 Command 模式来搭配使用,若是你们有兴趣的话,后续我能够在更新如何搭配 Command 模式使用。最后想说的是,数据结构和算法谁学谁知道,真香。函数
代码连接工具
Demo展现连接网站
若是此教程对你有帮助的话,请赏赐一个小星星 -_-!