堆栈是一种简单的线性数据结构,其工作原理就像一堆盘子?️。它遵循后进先出 (LIFO) 原则。将其视为一堆盘子:您只能添加或删除堆顶部的盘子。
为了更好的理解栈,让我们来一次短暂的想象之旅吧?.
想象一下您在一家高档餐厅??️,厨房工作人员正在为忙碌的夜晚做准备???。在餐具区,有一大堆盘子等待使用。当食客到来、订单纷至沓来时,工作人员会从最上面的盘子中取出盘子。当添加干净的盘子时,它们会直接放在上面。这个简单的系统确保了位于堆栈底部的放置时间最长的盘子最后被使用,而顶部刚清洁过的盘子首先被使用✨。
本质上,这就是堆栈数据结构的工作原理。堆栈是一种遵循后进先出 (LIFO) 原则的线性数据结构。就像我们的一堆盘子一样,添加到堆栈中的最后一个项目是第一个被删除的项目。
在这个关于堆栈数据结构的综合教程中,我们将通过简单、适合初学者的方法探索以下主题:
你准备好了吗?让我们深入探讨
堆栈是一种遵循后进先出(LIFO)原则的线性数据结构。这意味着最后添加到堆栈的元素将是第一个被删除的元素。将其想象为一摞书:您只能从书堆顶部添加或删除书籍。
在我们继续流程并编写一些代码之前,了解在哪里以及在哪里不使用堆栈是很有帮助的。下表详细给出了堆栈的明确优缺点。
优点 | 缺点 |
---|---|
简单易实现 | 访问受限(只有顶部元素可以直接访问) |
高效的后进先出 (LIFO) 操作 | 不适合元素的随机访问 |
入栈和出栈操作的恒定时间 O(1) | 如果管理不当可能导致堆栈溢出 |
对于跟踪算法中的状态很有用(例如深度优先搜索) | 不适合搜索或访问任意元素 |
帮助内存管理(例如,编程语言中的调用堆栈) | 某些实现中的固定大小(基于数组的堆栈) |
用于反转数据 | 可能需要在动态实现中调整大小,这可能成本高昂 |
自然支持递归算法 | 对于需要频繁遍历的大型数据集效率不高 |
帮助表达式求值和语法解析 | 如果在空堆栈上调用弹出操作,则可能发生下溢 |
在软件中的撤消机制中很有用 | 与更复杂的数据结构相比,功能有限 |
对于某些类型的数据组织(例如浏览器历史记录)有效 | 不适合需要类队列 (FIFO) 行为的问题 |
可以在堆栈上执行的基本操作是:
堆栈在计算机科学和软件开发中无处不在。以下是一些常见的应用:
撤消功能:在文本编辑器或图形设计软件中,每个操作都被推入堆栈。当您点击“撤消”时,最近的操作将从堆栈中弹出并反转。
浏览器历史记录:当您访问新页面时,它将被推送到堆栈上。 “后退”按钮将当前页面从堆栈中弹出,显示上一页。
函数调用堆栈:在编程语言中,函数调用是使用堆栈来管理的。当一个函数被调用时,它被压入调用栈。当它返回时,它会弹出。
表达式计算:堆栈用于计算算术表达式,特别是后缀表示法的表达式。
回溯算法:在解决迷宫或解谜等问题中,堆栈可以跟踪所采取的路径,以便在需要时轻松回溯。
现在,让我们用 JavaScript 实现一个 Stack。重要的是要知道在 JavaScript 中实现堆栈有不同的方法。实现堆栈的常见方法之一是使用数组,另一种方法是使用链表。在本文中,我们将使用链表(单链表)实现堆栈。
我希望你还记得链表是如何工作的吗?您可能需要查看我们本系列之前的一篇文章中的链表实现。
现在,让我们开始使用单链表实现我们的堆栈。我们可以?
首先,我们将创建一个 Node 类来表示我们的堆栈单个项目。
class Node { constructor(data) { this.data = data; this.next = null; } }
然后,我们将创建一个 Stack 类来表示我们的堆栈。
class Stack { constructor() { this.top = null; this.size = 0; } // Stack Operations will be implemented here ? }
push操作将一个新元素添加到栈顶。它创建一个新的 StackNode,将其下一个指针设置为当前顶部,然后更新顶部以指向这个新节点。最后,它增加大小。
// Push element to the top of the stack push(element) { const newNode = new Node(element); newNode.next = this.top; this.top = newNode; this.size ; }
出栈操作从堆栈中删除最顶层的元素。它首先检查堆栈是否为空。如果是,则返回错误消息。否则,它删除顶部元素,更新顶部指针到下一个节点,并减少大小。最后,它返回被删除的元素。
// Remove and return the top element pop() { if (this.isEmpty()) { return "Stack is empty"; } const poppedElement = this.top.data; this.top = this.top.next; this.size--; return poppedElement; }
peek 操作返回顶部元素而不删除它。它首先检查堆栈是否为空。如果是,则返回错误消息。否则,返回顶部元素的数据。
// Return the top element without removing it peek() { if (this.isEmpty()) { return "Stack is empty"; } return this.top.data; }
isEmpty 操作检查堆栈是否为空。如果堆栈为空则返回 true,否则返回 false。
// Check if the stack is empty isEmpty() { return this.size === 0; }
getSize操作返回堆栈的大小。它返回堆栈中元素的数量。
// Return the size of the stack getSize() { return this.size; }
打印操作打印堆栈。它返回顶部元素的数据。
// Print the stack print() { let current = this.top; let result = ""; while (current) { result = current.data " "; current = current.next; } console.log(result.trim()); }
// Usage example const customStack = new CustomStack(); customStack.push(10); customStack.push(20); customStack.push(30); console.log(customStack.pop()); // 30 console.log(customStack.peek()); // 20 console.log(customStack.getSize()); // 2 console.log(customStack.isEmpty()); // false customStack.print(); // 20 10
在此实现中,我们使用链表(单链表)结构来表示我们的堆栈。每个元素都是一个节点,具有数据值和对下一个节点的引用。堆栈顶部始终是最近添加的节点。
堆栈是计算机科学中的基本数据结构,遵循后进先出 (LIFO) 原则。它们用于各种应用程序,包括管理函数调用、实现撤消功能以及计算算术表达式。
在本教程中,我们介绍了堆栈的基础知识、使用它们的优缺点,以及它们在 JavaScript 中的实现(使用链表)。了解堆栈不仅仅是了解如何实现它们,还要认识到它们何时是解决问题的正确工具。
当您继续软件开发之旅时,您会发现堆栈是您解决问题的工具箱中不可或缺的工具。它们简单而强大,掌握它们将显着增强您设计高效算法和数据结构的能力。
确保您不会错过本系列的任何部分,并与我联系以更深入地讨论软件开发(Web、服务器、移动或抓取/自动化)、数据结构和算法以及其他令人兴奋的技术主题,关注我:
敬请期待并快乐编码????
免責聲明: 提供的所有資源部分來自互聯網,如果有侵犯您的版權或其他權益,請說明詳細緣由並提供版權或權益證明然後發到郵箱:[email protected] 我們會在第一時間內為您處理。
Copyright© 2022 湘ICP备2022001581号-3