什么是堆栈?如何用简单的es6代码实现这个?
什么是堆栈?
堆栈是一种高效的数据结构(基于 LIFO 原理的有序集合)。由于只能在栈顶添加或删除数据,因此此类操作快速且易于实现。堆栈用于编程语言实现的各个方面。在编程语言中,编译器也使用堆栈,计算机内存也使用堆栈来存储变量和方法调用,以及浏览器的返回函数。除了计算机上的很多堆栈应用之外,现实生活中也有实际的例子。比如我们从书堆里取出书本,从餐边柜里的盘子堆里取出最上面的盘子等等:
如何轻松使用JS实现栈?
如何用JS模拟一个简单的堆栈?首先,我们创建一个 stack-array.js 文件并声明 StackArray 类。代码如下:
class StackArray {
constructor() {
this.items = []; // {1}
}
}复制代码接下来做什么?我们需要一个可以存储堆栈元素的数据结构。为此,我们可以使用数组结构。我们还需要在堆栈中添加和删除数据元素。由于堆栈的后进先出原则,我们的添加和删除方法有点特殊。 ,Stack 类实现包括以下方法:
- push(element(s)):该方法将新添加的元素添加到堆栈顶部。
- pop():该方法删除栈顶元素,同时返回删除的元素
- peek():返回栈顶元素
- isEmpty():判断是否堆栈为空,如果为空则返回 true ,否则返回 False 。
- clear():清除堆栈中的所有元素。
- size():该方法返回栈中元素的数量,类似于数组的长度。
- toArray():以数组形式返回堆栈的元素。
- toString():将堆栈的内容作为字符串输出。
push()
该方法负责向堆栈添加新元素。最重要的特点是新元素只能添加到栈顶,即栈尾。为了恰好满足这个需求,我们可以使用数组push方法,代码如下:
push(element) {
this.items.push(element);
} 复制代码pop()
接下来我们实现pop()方法。该方法删除栈顶元素。由于它遵循 LIFO 原则,因此最后一个元素被删除。利用数组,我们可以自动弹出如下代码:
pop() {
return this.items.pop();
} 复制代码peek(), isEmpty(), size(), clear()
核心的增删改查就完成了,现在我们实现相关的helper方法,peek() 方法让我们看看堆栈的最后一个元素。实现代码如下:
peek() {
return this.items[this.items.length - 1];
} 复制代码isEmpty()方法也很简单。只需评估栈数组的长度是否为0即可。代码如下:
isEmpty() {
return this.items.length === 0;
} 复制代码size()方法更简单。使用Array的length方法就足够了。代码如下
size() {
return this.items.length;
} 复制代码最后应用最简单的清理方法clear(),将stack变量重置为空并设置值:
clear() {
this.items = [];
}复制代码最终完成的stack-array.js代码如下:
export default class StackArray {
constructor() {
this.items = [];
}
push(element) {
this.items.push(element);
}
pop() {
return this.items.pop();
}
peek() {
return this.items[this.items.length - 1];
}
isEmpty() {
return this.items.length === 0;
}
size() {
return this.items.length;
}
clear() {
this.items = [];
}
toArray() {
return this.items;
}
toString() {
return this.items.toString();
}
}复制代码接下来,我们创建一个文件 stackdemo.js 并导入文件 stack- array.js。让我们练习一下如何使用我们创建的 StackArray 类。代码如下:
import StackArray from 'stack-array.js';
const stack = new StackArray();
console.log('stack.isEmpty() => ', stack.isEmpty()); // outputs true
stack.push(5);
stack.push(8);
console.log('stack after push 5 and 8 => ', stack.toString());
console.log('stack.peek() => ', stack.peek()); // outputs 8
stack.push(11);
console.log('stack.size() after push 11 => ', stack.size()); // outputs 3
console.log('stack.isEmpty() => ', stack.isEmpty()); // outputs false
stack.push(15);
stack.pop();
stack.pop();
console.log('stack.size() after push 15 and pop twice => ', stack.size()); // outputs 2复制代码我们可以新建一个stackdemo.html并导入。 stackdemo.js(),只需打开stackdemo.html。栈的工作图如下:
调用push()方法后的效果:
执行pop()方法后的效果:
创建一个更高效的基于对象的栈类
In上一节,我们快速实现了一个基于数组的堆栈。我们知道数组是有序数组。如果存储的数据量很大,内容就太多了。 ,如果长度太大,会消耗更多的计算机内存并增加算法的复杂度(O(n),我们在后面的文章中介绍)。为了解决这个问题,我们采用更原始的方法来实现。首先,我们在 stack.js 文件中声明 stack 类。代码如下:
class Stack {
constructor() {
this.count = 0;
this.items = {};
}
// methods
} 复制代码push()
在JS中,对象是一组键值对的集合。我们可以使用枚举变量作为 items 对象的键。元素就是它的值,添加新元素后,count 变量加 1。代码实现如下:
push(element) {
this.items[this.count] = element;
this.count++;
}复制代码例如我们可以向空栈中添加新元素5和8,代码如下:
const stack = new Stack();
stack.push(5);
stack.push(8);复制代码当输出栈对象的项数和数量时,效果为如下:
isEmpty()
为了判断栈是否为空,我们只需要判断count变量是否为0即可 代码如下:
isEmpty() {
return this.count === 0;
}复制代码pop()
重写这个方法,首先要检查栈是否为空。如果不是,则返回未定义。如果没有,我们将 count 变量减 1 并删除相应的属性。代码如下:
pop() {
if (this.isEmpty()) {
return undefined;
}
this.count--;
const result = this.items[this.count];
delete this.items[this.count];
return result;
}复制代码接下来我们重写其他方法。完整代码如下:
export default class Stack {
constructor() {
this.count = 0;
this.items = {};
}
push(element) {
this.items[this.count] = element;
this.count++;
}
pop() {
if (this.isEmpty()) {
return undefined;
}
this.count--;
const result = this.items[this.count];
delete this.items[this.count];
return result;
}
peek() {
if (this.isEmpty()) {
return undefined;
}
return this.items[this.count - 1];
}
isEmpty() {
return this.count === 0;
}
size() {
return this.count;
}
clear() {
/* while (!this.isEmpty()) {
this.pop();
} */
this.items = {};
this.count = 0;
}
toString() {
if (this.isEmpty()) {
return '';
}
let objString = `${this.items[0]}`;
for (let i = 1; i < this.count; i++) {
objString = `${objString},${this.items[i]}`;
}
return objString;
}
}复制代码我们的课虽然完成了,但是你觉得有问题吗?由于我们创建的类的属性对所有开发者都是公开的,所以我们希望只能在栈顶添加元素而不希望向其他位置添加元素,但是Stack类中声明的属性和枚举是不受保护。这是一个JS规则问题。难道我们就没有办法改变这一点吗?答案是肯定的,我们可以利用ES6新添加的Symbol数据类型来获取私有属性作为对象属性(关于Symbol数据类型,作者在这篇文章中已经介绍过《【ES6基础】Symbol介绍:独一无二的值》),并在此基础上重写stack-array.js上的代码,代码如下:
const _items = Symbol('stackItems');
class Stack {
constructor() {
this[_items] = [];
}
push(element) {
this[_items].push(element);
}
pop() {
return this[_items].pop();
}
peek() {
return this[_items][this[_items].length - 1];
}
isEmpty() {
return this[_items].length === 0;
}
size() {
return this[_items].length;
}
clear() {
this[_items] = [];
}
print() {
console.log(this.toString());
}
toString() {
return this[_items].toString();
}
}
const stack = new Stack();
const objectSymbols = Object.getOwnPropertySymbols(stack);
console.log(objectSymbols.length); // 1
console.log(objectSymbols); // [Symbol()]
console.log(objectSymbols[0]); // Symbol()
stack[objectSymbols[0]].push(1);
stack.print(); // 5, 8, 1复制代码实际应用示例
Pina有各种解决实际问题的应用程序。例如,我们经常使用各种软件的撤消功能,尤其是在Java和C#编程语言中。堆栈用于存储变量和调用方法,可能会引发堆栈溢出异常,尤其是在使用递归算法时。接下来我们就亲自实现一下十进制转二进制的功能。
我们已经熟悉十进制了。然而,二进制表示在计算机科学中非常重要,因为计算机中的所有内容都是由二进制数(0和1)表示的。如果没有十进制数和二进制数之间来回转换的能力,与计算机的通信将会很困难。要将十进制数转换为二进制,我们需要将要转换的数除以2,然后将结果除以2,以此类推,直到结果为0。具体示意图如图:
根据上图的逻辑解释,完成的功能代码如下:
function decimalToBinary(decNumber) {
const remStack = new Stack();
let number = decNumber;
let rem;
let binaryString = '';
while (number > 0) {
rem = Math.floor(number % 2);
remStack.push(rem);
number = Math.floor(number / 2);
}
while (!remStack.isEmpty()) {
binaryString += remStack.pop().toString();
}
return binaryString;
}复制代码从上面的代码中,我们定义了一个栈,使用循环来处理要处理的数字,将模块的剩余部分压入堆栈,然后将其逐个弹出,连接成字符串作为输出。然后我们测试一下十进制到二进制的转换是否符合预期,如下面的测试代码所示:
console.log(decimalToBinary(233)); // 11101001
console.log(decimalToBinary(10)); // 1010
console.log(decimalToBinary(1000)); // 1111101000”复制代码练习题
我们只是练习一下十进制到二进制的转换,以使其更加通用,因为在实际应用中,不仅有是二进制转换要求,比如八进制、十六进制等。现在我想给大家留下作业。实现 baseConverter(decNumber, base) 函数。第一个参数是要转换的十进制数,第二个参数是要转换的参数,从十进制2转换为36。欢迎您在留言区发布代码。第
在这篇文章中,我们将了解什么是数据结构,并深入学习堆栈数据结构和堆栈的JS代码实现,并解释不同的实现方法。同时了解堆栈在计算机领域的作用应用并练习用
将十进制数转换为二进制作者:前端专家
链接:https://juejin.im/post/5ce0b01df265da1bb47d33eb
来源:掘金
版权归作者所有。商业转载请联系作者获取授权。非商业转载请注明出处。
版权声明
本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。
code前端网