前言:
近日重拾数据结构,拿出曾经的教材,再次认真学习,先从栈开始。
1.栈定义
栈(stack)后进先出的线性表(LIFO结构)。栈顶就是表尾端,栈底是表头端。
存储方式:
- 顺序存储:用一组地址连续的存储单元一次存放自栈底到栈顶的数据元素,同时附设指针top指示栈顶元素在顺序栈中的位置。打个比方就是一排教室挨着的,你现在站在最后一间教室,你就是那个top指针,哈哈。。。找到张图片
- 链式存储: 栈的链式存储结构是通过由结点构成的单链表实现的,此时表头指针被称为栈顶指针,由栈顶指针指向的表头结点被称为栈顶结点,整个单链表被称为链栈。存储单元不一定连续,由当前结点指针指向下一个地址单元。
附注 下一篇 讲讲链式存储和顺序存储的比较
2 . js模拟栈
可以用js的数组的来模拟栈的几个方法。
栈的基本功能(资料)
Stack | 创建一个空栈 |
pop | pop栈顶元素,并返回该元素 |
push | push一个元素到栈顶 |
isEmpty | 栈是否为空 |
lenth | 栈的长度 |
peak | 返回栈顶元素 |
clear | 清空栈 |
打印栈内所有元素 |
function Stack(){ this.stack = []; } Stack.prototype.pop = function (){ return this.stack.pop(); } Stack.prototype.push = function (element){ this.stack.push(element); } Stack.prototype.length = function (){ return this.stack.length; } Stack.prototype.peak = function (){ return this.stack[this.length()-1]; } Stack.prototype.clear = function (){ this.stack = []; } Stack.prototype.isEmpty = function (){ return this.stack.length === 0 ? true : false; } Stack.prototype.print = function (){ var length = this.stack.length; for(var i = 0; i < length; i++){ console.log(this.stack[i]); } }
以上用了原型的写法,为了让栈可扩展。
瞬间发现了更好的写法,如下 :原链接
/** * 栈的构造函数 */ function Stack() { /** * 用数组来模拟栈 * @type {Array} */ var items = []; /** * 将元素送入栈,放置于数组的最后一位 * @param {Any} element 接受的元素,不限制类型 */ this.push = function(element) { items.push(element); }; /** * 弹出栈顶元素 * @return {Any} 返回被弹出的值 */ this.pop = function() { return items.pop(); }; /** * 查看栈顶元素 * @return {Any} 返回栈顶元素 */ this.peek = function() { return items[items.length - 1]; } /** * 确定栈是否为空 * @return {Boolean} 若栈为空则返回true,不为空则返回false */ this.isEmpty = function() { return items.length === 0 }; /** * 清空栈中所有内容 */ this.clear = function() { items = []; }; /** * 返回栈的长度 * @return {Number} 栈的长度 */ this.size = function() { return items.length; }; /** * 以字符串显示栈中所有内容 */ this.print = function() { console.log(items.toString()); }; }
优点: 数组私有化,除了提供的几个方法以外,不可以随意被修改。一个实例就可以是一个栈。缺点正在寻找中.....
3. 栈的应用
数据转换
原理:N=(N div d)* d + N mod d(其中 div为整除运算,mod 为求余运算),若将计算过程得到余数顺序进栈,再按出栈顺序打印就能得到对应的binary进制数
function Stack() { /** * 用数组来模拟栈 * @type {Array} */ var items = []; /** * 将元素送入栈,放置于数组的最后一位 * @param {Any} element 接受的元素,不限制类型 */ this.push = function(element) { items.push(element); }; /** * 弹出栈顶元素 * @return {Any} 返回被弹出的值 */ this.pop = function() { return items.pop(); }; /** * 查看栈顶元素 * @return {Any} 返回栈顶元素 */ this.peek = function() { return items[items.length - 1]; } /** * 确定栈是否为空 * @return {Boolean} 若栈为空则返回true,不为空则返回false */ this.isEmpty = function() { return items.length === 0 }; /** * 清空栈中所有内容 */ this.clear = function() { items = []; }; /** * 返回栈的长度 * @return {Number} 栈的长度 */ this.size = function() { return items.length; }; /** * 以字符串显示栈中所有内容 */ this.print = function() { console.log(items.toString()); }; } function conversion(number,binary){ var stack = new Stack(); var result = ""; while(number>0){ stack.push(number%binary); number = Math.floor(number/binary); } while (!stack.isEmpty()){ result +=stack.pop(); } // 打印binary进制 console.log(result); return result; }
这是栈应用 最简单也比较直接的例子,但其广泛运用在软件系统中,如括号匹配、迷宫求解、表达式求值等。