栈数据结构简介
- 栈是一种遵循先进后出原则的数据结构
- 新添加或待删除的元素都位于栈的同一端称为栈顶,另一端称为栈底
- 在栈里新元素都靠近栈顶,旧元素都靠近栈底
- 栈在现实生活中类似于:一叠书,一叠盘子
- 栈在编程语言中多用于管理变量,方法的调用,同时也用于管理浏览器的历史记录(浏览器的返回按钮)
通过数组实现栈
- 通过数组的 push 和 pop 方法,JavaScript可以实现名为栈的数据结构
- 通过数组实现的栈的方法:
- push(element(s)): 添加一个或几个新元素到栈顶
- pop(): 删除栈顶的元素,同时返回被删除的元素
- peek() :返回栈顶的元素,但不对栈做任何修改
- isEmpty(): 判断栈里是否有元素,有则返回true,没有则返回false
- clear(): 清除栈里的所有元素
- size(): 返回栈里的元素个数,该方法和数组的length属性很类似
- 代码:
/*表示栈的类*/ class Stack { constructor() { this.items = []; // items 数组存储栈中的元素 } // push(element(s)): 添加一个或几个新元素到栈顶 push(element) { this.items.push(element); } // pop(): 删除栈顶的元素,同时返回被删除的元素 pop() { return this.items.pop(); } // peek() :返回栈顶的元素,但不对栈做任何修改 peek() { return this.items[this.items.length - 1]; } // isEmpty(): 判断栈里是否有元素,有则返回true,没有则返回false isEmpty() { return this.items.length === 0; } // clear(): 清除栈里的所有元素 clear() { this.items = []; } // size(): 返回栈里的元素个数,该方法和数组的length属性很类似 size() { return this.items.length; } }
通过对象实现栈
- 通过对象来实现栈,会占用更少的内存空间,同时也跟高效
- 通过对象实现的栈的方法:
- push(element): 添加一个新元素到栈顶
- pop(): 删除栈顶的元素,同时返回被删除的元素
- peek() :返回栈顶的元素,但不对栈做任何修改
- isEmpty(): 判断栈里是否有元素,有则返回true,没有则返回false
- clear(): 清除栈里的所有元素
- size(): 返回栈里的元素个数,该方法和数组的length属性很类似
- toString()
- 代码:
/*表示栈的类*/ class Stack { constructor() { this.items = {}; // items 对象存储栈中的元素 this.count = 0; // count 表示栈中元素的数量 } // push(element): 添加一个新元素到栈顶 push(element) { this.items[this.count] = element; this.count += 1; } // pop(): 删除栈顶的元素,同时返回被删除的元素 pop() { if (this.isEmpty()) { return undefined; } this.count -= 1; const result = this.items[this.count]; //存储栈顶的元素 delete this.items[this.count]; //删除栈顶的元素 return result; } // peek() :返回栈顶的元素,但不对栈做任何修改 peek() { if (this.isEmpty()) { return undefined; } return this.items[this.count - 1]; } // isEmpty(): 判断栈里是否有元素,有则返回true,没有则返回false isEmpty() { return this.count === 0; } // clear(): 清除栈里的所有元素 clear() { this.items = {}; this.count = 0; } // size(): 返回栈里的元素个数,该方法和数组的length属性很类似 size() { return this.count; } // toString() toString() { if (this.isEmpty()) { return ''; } let str = `${this.items[0]}`; for (let i = 1; i < this.count; i += 1) { str = `${str},${this.items[i]}`; } return str; } }
栈的运用
进制转换算法
- 将十进制转换成基数为2~36的任意进制
- 代码:
const baseConverter = (decNumber, base) => { const remStack = new Stack(); // 存储余数的栈 let number = decNumber; // 十进制数 let rem; // 余数 let str = ''; // 最终输出结果字符串 // 如果不是转换成 2~36 进制数 if (!(base >= 2 && base <= 36)) { return ''; } // 转换成 2~32 进制数 while (number > 0) { rem = Math.floor(number % base); remStack.push(rem); number = Math.floor(number / base); } // 生成base进制的字符串 const digits = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'; while (!remStack.isEmpty()) { str += digits[remStack.pop()]; } return str; }; console.log(baseConverter(100345, 2)); // 结果:11000011111111001 console.log(baseConverter(100345, 8)); // 结果:303771 console.log(baseConverter(100345, 16)); // 结果:187F9 console.log(baseConverter(100345, 35)); // 结果:2BW0