通过链表实现栈功能
Array | 功能 | 返回 |
---|---|---|
push | 底部插入 | 数组长度 |
unshift | 顶部插入 | 数组长度 |
pop | 底部删除 | 删除的元素 |
shift | 顶部删除 | 删除的元素 |
栈是一种只能在一端进行操作的数据结构,它遵守先进后出(LIFO-last in first out)。
JavaScript中模拟栈操作很简单,比如上面表格中的push+pop或者unshift+shift,都具备模拟栈的功能。
链表是一种非连续、非顺序的存储结构,它是由节点构成,而每一个节点都具备两个部分,其一为节点存储的数据,其二是相邻节点的引用地址。
单向链表实现栈功能
单向链表(单链表)是链表的一种,其特点是链表的链接方向是单向的,对链表的访问要通过顺序读取从头部开始。1
function createNode(){
let address;//self address
let nextNode;//next node address
let data;//self data
function getAddress(){
return address;
}
function setNextNode(_nextNode){
nextNode = _nextNode;
}
function getNextNode(){
return nextNode;
}
function setData(_data){
data = _data;
}
function getData(){
return data;
}
return address = {
getAddress : getAddress,
setNextNode : setNextNode,
getNextNode : getNextNode,
setData : setData,
getData : getData,
}
};
let stack = (function(){
let headNode = null;
let footNode = null;
function push(_node){
if(!headNode){
headNode = _node;
}else{
footNode.setNextNode(_node);
}
footNode = _node;
}
function pop(){
if(!headNode){
return headNode;
}
if(headNode === footNode){
return headNode = footNode = null;
}
let node = findFootNodePrevNode(headNode,footNode);
if(!node){
return headNode = footNode = null;
}else{
footNode = node;
node.setNextNode(null);
return footNode;
}
}
function foreach(){
forEachNode(headNode);
}
return {
push : push,
pop : pop,
foreach : foreach
}
})();
/**
* 三种情况
* 1. headNode === footNode 只有一个节点 这种在调用这个方法前已经判断了 不存在
* 2. headNode != null && footNode == null 这种算数据有问题了 不考虑
* 3. headNode的子节点 === footNode
* @param {*} headNode
* @param {*} footNode
*/
function findFootNodePrevNode(headNode,footNode){
let node = headNode.getNextNode();
if(node === footNode){
return headNode;
}else{
return findFootNodePrevNode(node,footNode);
}
}
function forEachNode(node){
if(!!node){
console.log('node.data.name : ' + (node.getData() || 'unKnown'));
let nextNode = node.getNextNode();
forEachNode(nextNode);
}
}
测试代码:
双向链表实现栈功能
双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。2
function createNode(){
let address;//self address
let nextNode;//next node address
let prevNode;//previous node address
let data;//self data
function getAddress(){
return address;
}
function getNextNode(){
return nextNode;
}
function setNextNode(_nextNode){
nextNode = _nextNode;
}
function getPrevNode(){
return prevNode;
}
function setPrevNode(_prevNode){
prevNode = _prevNode;
}
function setData(_data){
data = _data;
}
function getData(){
return data;
}
return address = {
getAddress : getAddress,
setNextNode : setNextNode,
getNextNode : getNextNode,
setPrevNode : setPrevNode,
getPrevNode : getPrevNode,
setData : setData,
getData : getData,
}
};
let stack = (function(){
let headNode = null;
let footNode = null;
function push(_node){
if(!headNode){
headNode = _node;
}else{
_node.setPrevNode(footNode);
footNode.setNextNode(_node);
}
footNode = _node;
}
function pop(){
if(!headNode){
return headNode;
}
if(headNode === footNode){
return headNode = footNode = null;
}
footNode = footNode.getPrevNode();
footNode.setNextNode(null);
}
function foreach(){
forEachNode(headNode);
}
return {
push : push,
pop : pop,
foreach : foreach
}
})();
function forEachNode(node){
if(!!node){
console.log('node.data.name : ' + (node.getData() || 'unKnown'));
let nextNode = node.getNextNode();
forEachNode(nextNode);
}
}
测试代码: