美文网首页数据结构与算法学习笔记
数据结构与算法学习篇 -- 栈

数据结构与算法学习篇 -- 栈

作者: 小人物的秘密花园 | 来源:发表于2019-03-05 11:56 被阅读0次

学习资料

《学习JavaScript数据结构与算法》-- 第二版

参考资料

ES6入门

定义

栈是一种遵循先进后出,后进先出(LIFO)的有序集合;
栈顶
栈底

实现

通过创建一个类来表示栈,使用数组这种数据结构来存储栈中的数组,栈顶对应数组最后一位元素,栈底对应数组的第一位元素;

栈的方法:

1.push:向栈中添加元素

调用数组的push方法

2.pop:删除栈中的元素

调用数组的pop方法

3.peek:返回栈顶元素,不对栈进行任何的修改,不会删除栈顶元素,只是返回栈顶元素

返回数组的最后一位元素;

4.isEmpty: 判断栈是否为空,为空,则为true,反之为false;

判断数组的长度是否0;

5.clear:清空栈;

6.size:返回栈的长度

返回数组的长度

栈的实现方式ES5

/**
 * @Descroption 通过创建类的方式创建栈,使用数组来保存栈中的数据
 * 栈顶对应数组的最后一个元素,栈底对应数组的
 * @author xl
 * @createTime 2019-03-05
*/
function Stack() {
  let items = [];
  // 向栈添加元素
  this.push = function(item) {
    items.push(item);
  };

  // 从栈移除元素
  this.pop = function() {
    return items.pop();
  };

  // 返回栈顶元素
  this.peek = function() {
    return items[items.length - 1];
  };

  // 检查栈是否为空
  this.isEmpty = function() {
    if (items.length === 0) {
      return true;
    } else {
      return false;
    }
  };

  // 栈的长度
  this.size = function() {
    return items.length;
  };

  // 打印栈元素
  this.print = function() {
    console.log(items.toString());
  };

  // 清空栈
  this.clear = function() {
    items = [];
  };
}

// 栈的使用

// 初始化栈
let stack = new Stack();
console.log(stack.isEmpty());
stack.push(1)
stack.push(2)
console.log(stack.peek());
console.log(stack.size());
console.log(stack.print());
stack.pop();
stack.pop();
console.log(stack.peek());
console.log(stack.size());
console.log(stack.print());

栈的实现方式ES6

class Stack {
  constructor() {
    this.items = [];
  }
  // 栈方法
  push(item) {
    this.items.push(item);
  }
  ...
}

这种实现方式的优点:
1.代码简洁,美观,
2.ES6的类是介于原型的,基于原型的类比基于函数的类更节省内存

这种实现方式的缺点:
1.ES6的类是介于原型的,但不能够声明私有属性(变量)或方法

解决ES6中使用类定义栈不能声明私有属性或方法的解决方法:

1.利用ES6中限定作用域的Symbol实现类

let _items = Symbol();
class Stack {
  constructor() {
    this[_items] = [];
  }
  // 栈方法
  push(item) {
    this[_items].push(item);
  }
  pop() {
    return this[_items].pop();
  }
  peek() {
    return this[_items][this[_items].length - 1];
  }
  // 检查栈是否为空
  isEmpty() {
    if (this[_items].length === 0) {
      return true;
    } else {
      return false;
    }
  };

  // 栈的长度
  size() {
    return this[_items].length;
  };

  // 打印栈元素
  print() {
    console.log(this[_items].toString());
  };

  // 清空栈
  clear() {
    this[_items] = [];
  };
}

问题:
这种方式创建的一个假的私有变量,ES6中新增的Object.getOwnPropertySymbols()能够获取到类中所有使用Symbol声明的属性,并且获取到的属性可以被更改

let stack = new Stack();
stack.push(1)
let objectSymbols = Object.getOwnPropertySymbols(stack);
console.log(objectSymbols);
stack[objectSymbols[0]].push(3)
stack.print() // 1,3

2.利用ES6的WeakMap实现类
WeakMap可以声明私有变量,加闭包用于限定items

let Stack1 = (function() {
// 利用WeakMap 实现类
const items = new WeakMap();
class Stack1 {
  constructor() {
    items.set(this,[]);
  }
  // 栈方法
  push(item) {
    let s = items.get(this);
    s.push(item);
  }
  pop() {
    let s = items.get(this);
    return s.pop();
  }
  peek() {
    let s = items.get(this);
    return s[s.length - 1];
  }
  // 检查栈是否为空
  isEmpty() {
    let s = items.get(this);
    if (s.length === 0) {
      return true;
    } else {
      return false;
    }
  };

  // 栈的长度
  size() {
    let s = items.get(this);
    return s.length;
  };

  // 打印栈元素
  print() {
    let s = items.get(this);
    console.log(s.toString());
  };

  // 清空栈
  clear() {
    items.set(this,[]) 
  };
}
return Stack1;
})();

let stack1 = new Stack1();
stack1.push(1)
stack1.push(2)
console.log(stack1.size());
console.log(stack1.print());
console.log(stack1.peek());
console.log(stack1.isEmpty());
console.log(stack1.clear());
console.log(stack1.isEmpty());

这种方式的缺点:
扩展类无法继承私有属性;

相关文章

网友评论

    本文标题:数据结构与算法学习篇 -- 栈

    本文链接:https://www.haomeiwen.com/subject/eatnuqtx.html