【轻松掌握数据结构与算法】栈:后进先出的数据结构

看图轻松理解数据结构与算法系列(基于数组的栈) 前言 推出一个新系列,《看图轻松理解数据结构和算法》,主要使用图片来描述常见的数据结构和算法,轻松阅读并理解掌握。本系列包括各种堆、各种队列、各种列表、各种树、各种图、各种排序等等几十篇的样子。 栈 栈是一种线性存储结构且运算受限的线性表,它的插入和删除运算操作被限制在表的一端,该端称为栈顶,而另外一端则称为栈底。 栈中的数据以后进先出(Last In First Out 即LIFO)... 阅读详情

栈(Stack)是一种后进先出(LIFO, Last In First Out)的数据结构,它只允许在一端进行插入和删除操作。栈在计算机科学中有着广泛的应用,例如函数调用、表达式求值、括号匹配等。本文将详细介绍栈的基本概念、操作以及应用场景,并通过示例和图表来帮助你更好地理解栈。

栈的基本概念

栈是一种线性数据结构,它遵循后进先出的原则。栈的主要操作包括:

  • push:将一个元素添加到栈顶。

  • pop:移除栈顶的元素并返回。

  • peek 或 top:返回栈顶的元素但不移除。

  • is_empty:检查栈是否为空。

  • size:返回栈中元素的数量。

栈的实现

栈可以通过数组或链表来实现。数组实现的栈具有固定的大小,而链表实现的栈可以动态扩展。

数组实现的栈
class Stack:
    def __init__(self, capacity):
        self.capacity = capacity
        self.stack = [None] * capacity
        self.top = -1

    def push(self, value):
        if self.top == self.capacity - 1:
            raise Exception("Stack overflow")
        self.top += 1
        self.stack[self.top] = value

    def pop(self):
        if self.top == -1:
            raise Exception("Stack underflow")
        value = self.stack[self.top]
        self.top -= 1
        return value

    def peek(self):
        if self.top == -1:
            return None
        return self.stack[self.top]

    def is_empty(self):
        return self.top == -1

    def size(self):
        return self.top + 1
链表实现的栈
class ListNode:
    def __init__(self, value=0, next=None):
        self.value = value
        self.next = next

class Stack:
    def __init__(self):
        self.head = None

    def push(self, value):
        new_node = ListNode(value)
        new_node.next = self.head
        self.head = new_node

    def pop(self):
        if self.head is None:
            raise Exception("Stack underflow")
        value = self.head.value
        self.head = self.head.next
        return value

    def peek(self):
        if self.head is None:
            return None
        return self.head.value

    def is_empty(self):
        return self.head is None

    def size(self):
        count = 0
        current = self.head
        while current:
            count += 1
            current = current.next
        return count

栈的操作示意图

1. push 操作

概念:将一个元素添加到栈顶。

示意图:

初始状态:
栈顶
+---+    push(3)
|   |    +---+
|   |    | 3 |
|   |    |   |
+---+    +---+

2. pop 操作

概念:移除栈顶的元素并返回。

示意图:

初始状态:
栈顶
+---+    pop()
| 3 |    +---+
| 2 |    | 2 |
| 1 |    | 1 |
+---+    +---+

3. peek 操作

概念:返回栈顶的元素但不移除。

示意图:

初始状态:
栈顶
+---+    peek()
| 3 |    返回 3
| 2 |
| 1 |
+---+

4. is_empty 操作

概念:检查栈是否为空。

示意图:

初始状态:
栈顶
+---+    is_empty()
| 3 |    返回 False
| 2 |
| 1 |
+---+

空栈:
栈顶
+---+    is_empty()
|   |    返回 True
+---+

5. size 操作

概念:返回栈中元素的数量。

示意图:

初始状态:
栈顶
+---+    size()
| 3 |    返回 3
| 2 |
| 1 |
+---+

栈的应用场景

栈在许多计算机科学问题中都有广泛的应用。以下是一些常见的应用场景和详细的示例。

1. 括号匹配

括号匹配问题是一个经典的栈应用。给定一个字符串,包含多种类型的括号(如()、[]、{}),需要检查括号是否正确匹配。

def is_valid_parentheses(s):
    stack = []
    mapping = {")": "(", "]": "[", "}": "{"}
    for char in s:
        if char in mapping:
            top_element = stack.pop() if stack else '#'
            if mapping[char] != top_element:
                return False
        else:
            stack.append(char)
    return not stack

# 示例
print(is_valid_parentheses("()"))  # True
print(is_valid_parentheses("()[]{}"))  # True
print(is_valid_parentheses("(]"))  # False
print(is_valid_parentheses("([)]"))  # False
print(is_valid_parentheses("{[]}"))  # True

2. 表达式求值

栈可以用于计算算术表达式的值,特别是处理包含括号的表达式。以下是一个示例,展示如何使用栈来计算中缀表达式的值。

def precedence(op):
    if op in ('+', '-'):
        return 1
    if op in ('*', '/'):
        return 2
    return 0

def apply_op(a, b, op):
    if op == '+': return a + b
    if op == '-': return a - b
    if op == '*': return a * b
    if op == '/': return a // b

def evaluate(expression):
    numbers = []
    ops = []
    i = 0
    while i < len(expression):
        if expression[i] == ' ':
            i += 1
            continue
        elif expression[i] == '(':
            ops.append(expression[i])
        elif expression[i].isdigit():
            val = 0
            while i < len(expression) and expression[i].isdigit():
                val = val * 10 + int(expression[i])
                i += 1
            numbers.append(val)
            i -= 1
        elif expression[i] == ')':
            while ops[-1] != '(':
                op = ops.pop()
                val2 = numbers.pop()
                val1 = numbers.pop()
                numbers.append(apply_op(val1, val2, op))
            ops.pop()
        else:
            while (len(ops) != 0 and precedence(ops[-1]) >= precedence(expression[i])):
                op = ops.pop()
                val2 = numbers.pop()
                val1 = numbers.pop()
                numbers.append(apply_op(val1, val2, op))
            ops.append(expression[i])
        i += 1
    while len(ops) != 0:
        op = ops.pop()
        val2 = numbers.pop()
        val1 = numbers.pop()
        numbers.append(apply_op(val1, val2, op))
    return numbers[0]

# 示例
print(evaluate("10 + 2 * 6"))  # 22
print(evaluate("100 * 2 + 12"))  # 212
print(evaluate("100 * ( 2 + 12 )"))  # 1400
print(evaluate("100 * ( 2 + 12 ) / 14"))  # 100

3. 函数调用栈

在编程语言中,函数调用是通过栈来管理的。每次调用函数时,都会在栈上创建一个新的帧,包含函数的局部变量和返回地址。当函数返回时,当前帧被弹出,控制权返回到调用者。以下是一个简单的示例,展示如何使用栈来模拟函数调用。

def factorial(n):
    if n == 0 or n == 1:
        return 1
    return n * factorial(n - 1)

# 模拟函数调用栈
call_stack = []
call_stack.append(("factorial", 5))
while call_stack:
    func, arg = call_stack.pop()
    if arg == 0 or arg == 1:
        result = 1
    else:
        call_stack.append(("multiply", (arg, call_stack)))
        call_stack.append(("factorial", arg - 1))
        continue
    while call_stack and call_stack[-1][0] == "multiply":
        _, (n, prev_call_stack) = call_stack.pop()
        result *= n
        call_stack = prev_call_stack
    if call_stack:
        call_stack[-1] = (call_stack[-1][0], result)
    else:
        print(result)

# 输出结果
120

4. 逆波兰表达式求值

逆波兰表达式(RPN)是一种不需要括号来表示运算符优先级的表达式。栈可以用于高效地计算逆波兰表达式的值。

def evaluate_rpn(tokens):
    stack = []
    for token in tokens:
        if token in "+-*/":
            b = stack.pop()
            a = stack.pop()
            if token == '+':
                stack.append(a + b)
            elif token == '-':
                stack.append(a - b)
            elif token == '*':
                stack.append(a * b)
            elif token == '/':
                stack.append(int(a / b))
        else:
            stack.append(int(token))
    return stack[0]

# 示例
print(evaluate_rpn(["2", "1", "+", "3", "*"]))  # 9
print(evaluate_rpn(["4", "13", "5", "/", "+"]))  # 6
print(evaluate_rpn(["10", "6", "9", "3", "+", "-11", "*", "/", "*", "17", "+", "5", "+"]))  # 22

5. 最小栈

设计一个支持 push、pop、top 操作,并能在常数时间内检索到最小元素的栈。

class MinStack:
    def __init__(self):
        self.stack = []
        self.min_stack = []

    def push(self, x):
        self.stack.append(x)
        if not self.min_stack or x <= self.min_stack[-1]:
            self.min_stack.append(x)

    def pop(self):
        if self.stack:
            if self.stack[-1] == self.min_stack[-1]:
                self.min_stack.pop()
            return self.stack.pop()
        raise Exception("Stack underflow")

    def top(self):
        if self.stack:
            return self.stack[-1]
        raise Exception("Stack underflow")

    def getMin(self):
        if self.min_stack:
            return self.min_stack[-1]
        raise Exception("Stack underflow")

# 示例
min_stack = MinStack()
min_stack.push(-2)
min_stack.push(0)
min_stack.push(-3)
print(min_stack.getMin())  # -3
min_stack.pop()
print(min_stack.top())  # 0
print(min_stack.getMin())  # -2

总结

栈是一种灵活的数据结构,适用于需要动态大小和高效插入、删除操作的场景。通过理解栈的基本概念和操作,你可以更好地应用栈来解决实际问题。希望本文的示例和图表能帮助你更好地理解和掌握栈。

C++中的栈数据结构与应用实战 本文还有配套的精品资源,点击获取 简介:栈是一种遵循后进先出原则的数据结构,在C++中使用STL的 <stack> 库实现。它在算法和功能实现中扮演基础角色,特别是用于递归、表达式求值、内存管理等方面。本文详细介绍了栈的基本概念、操作以及在实际编程中的多种应用场景,提供了一个使用栈的简单示例代码。通过学习栈的使用,程序员可以有效提升代码效率和问题解... 阅读详情

相关推荐

机器学习【学校智慧食堂及其应用】

本文主要介绍机器学习【智慧食堂及其应用】

qq_201729558 2571

栈和队列详讲

栈和队列详讲 一、定义 栈和队列,是2中常用的,重要的数据结构 栈和队列都是限定插入和删除,只能在表的**“端点”**进行的线性表 栈——后进先出 队列——先进先出 二、栈stack 1.栈的基本概念 运算规则:后进先出(Last In First Out)简称LIFO结构 队尾(栈顶)插入,删除 ,插入,称为入栈/压栈(push),删除,称为出栈/弹栈(pop) 逻辑结构:一对一关系,有一个直接前驱,和一个直接后续 存储结构:顺序栈(常见)/链式栈 实现方式:关键是编写入栈和出栈的函

qq_42925518的博客 1977

VBA一键汇总多个工作簿-名称相同的工作表-的指定区域数据

VBA一键汇总多个工作簿-名称相同的工作表-的指定区域数据 日常工作,我们经常需要汇总相同格式的工作簿的某个工作表的数据 如1月业绩、2月业绩。。。。12月业绩等 姓名 数量 数据22 22 数据23 23 数据24 24 数据25 25 数据26 26 数据27 27 数据28 28 数据29 29 数据30 30 数据31 31 数据32 32 数据33 33 数据34

陈表达的博客 5982

数据结构之栈

一.什么是栈 二.几道小题开胃 三.栈的代码实现 1.创建项目 2.创建栈结构 3.栈的初始化 4.入栈操作 5.出栈操作 6.返回栈顶元素 7.求栈元素个数 8.判断栈是否为空 9.栈的销毁 四.总结: 五.原码链接 ...

chuxinchangcun的博客 1万+

数据仓库ODS层详解- 功能、设计与最佳实践

数据仓库ODS层是大数据分析的基石,为企业决策提供可靠数据源。本文深入探讨ODS层设计原则、实施要点和最佳实践,涵盖金融、零售等行业应用。重点关注云环境下ODS层部署策略,以及实时数据集成、数据湖技术等创新趋势。文章还分析了数据体量增长、实时性需求等挑战,提供实用解决方案。whether助您构建高效、安全、可扩展的ODS层,为数字化转型奠定坚实基础。#数据仓库 #ODS层 #大数据分析 #云计算 #数据湖

一个8年大数据开发工程师的碎碎念 1万+

UDS自动化测试-Service 0x27(CAPL调用dll实现key计算)

相信读者基于Diagnostic/ISO TP Confighration中cdd、dll文件的测试并不陌生,本文基于其的基础上,介绍在capl中调用内置的函数diagGenerateKeyFromSeed实现27服务解锁,从而进行诊断自动化测试。本文基于4个byte的Seed、16个byte的Key的安全访问,实现27服务的自动化测试。需要加载项目使用的cdd文件,如果没有的情况下可以使用canoe例程中默认的cdd文件。

诊断协议那些事儿's blog 2054

后进先出的数据结构——栈

​ 栈的特性在本质上与数组和链表无异,都是用于存储一批相同类型的数据,因此他的底层实现无非就是两种:数组和链表。

qq_55092103的博客 1363

开源数字人、虚拟直播部署教程

对,你无看错,是欧美的。在直播带货案例里,我们把模型导入到ue4,我们给模型在ue4里预设了四个动作(站着、站着说话、坐着、坐着说话),三个表情(平静、开发、愤怒),三个镜头(全局、近矩说话、看显示器播放商品展示)。我们只需要把目标主播的直播给录制下来,提取样本数据,然后训练一个从粉丝的不同刺激的组合,到主播的不同响应方式的多元逻辑回归的数学模型参数即可。

南七小僧的学海无涯 4560

顺序栈的详解

栈是一种特殊的数据结构,它的特点是后进先出(Last In First Out,LIFO)。栈是一种线性结构,它可以用来存储一组具有相同类型的数据元素。栈的基本操作包括压入(push)和弹出(pop),其中压入操作将数据元素添加到栈的顶部,弹出操作将栈顶的数据元素移除并返回。/* 堆空间 */int top;/* 栈顶指针 */}SeqStack;/* 1. 初始化 *//* 2. 进(入)栈 *//* 3. 出栈 *//* 4. 取栈顶元素 *//* 5. 栈为空?*/

qq_54938554的博客 4031

如何对TBSS的结果进行统计学的分析,已完成置换检验,如何在最终的TBSS输出结果提取除具体值及如何做进一步相关性分析??

🏆本文收录于 《全栈 Bug 调优(实战版)》 专栏。专栏聚焦真实项目中的各类疑难 Bug,从成因剖析 → 排查路径 → 解决方案 → 预防优化全链路拆解,形成一套可复用、可沉淀的实战知识体系。无论你是初入职场的开发者,还是负责复杂项目的资深工程师,都可以在这里构建一套属于自己的「问题诊断与性能调优」方法论,助你稳步进阶、放大技术价值。

**My Coding Family** 1439

C#的GDI+绘图详解

/消除锯齿 或 AntiAlias。// 1.在窗体或控件的Paint事件中,用PaintEventArgs e 创建绘图对象 ---- 控件或窗体重绘时。//为控件创建绘图对象。//--------------------以上方法三选一。//2.创建绘图对象 panel1中绘图。

weixin_50920631的博客 3457

栈操作应遵循的原则是什么?

栈是一种遵循"先进后出"(Last In, First Out,LIFO)原则的数据结构。遵循这些原则可以确保栈的正常操作和数据的正确性。

qq_74474809的博客 3090

Codex 自定义模型操作指南:CLI 与桌面客户端双端实操

检查版本 codex --version # 预期输出类似:codex-cli 0.133.0-alpha.1 # 如未安装 npm install -g @openai/codex假设你要接入DeepSeek,在# 临时设置(当前终端会话有效)export DEEPSEEK_API_KEY="sk-你的 DeepSeek API Key"# 永久设置(推荐,写入 shell 配置)

篮球界最会写bug的人;程序猿中打球最菜的人。 454

【数据结构与算法-Day 12】深入浅出栈:从“后进先出”原理到数组与链表双实现

在探索了数组和链表这两种基础线性结构后,今天我们将学习一种非常重要但又受限的线性数据结构——**栈 (Stack)**。栈以其独特的 “后进先出” (LIFO) 原则,在计算机科学领域扮演着不可或缺的角色,从我们日常使用的软件中的“撤销”功能,到支撑现代编程语言运行的函数调用,背后都有栈的身影。本文将系统地剖析栈的定义、核心特性与操作,并手把手带你用**数组**和**链表**两种方式实现一个功能完备的栈,深入对比它们的优劣与适用场景,为你彻底掌握栈结构打下坚实的基础。

吴师兄大模型的博客 1095

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

【数据结构指南】栈

怕学栈太复杂?这篇博客带你快速搞定核心难点!不用啃晦涩理论,想搞懂栈其实很简单:记住 “栈顶操作、后进先出”,知道栈顶、栈底、空栈这些基础概念,再掌握入栈、出栈核心操作就够了。

一枚菜鸟程序员的飞行之路 1601

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

C++数据结构之:栈Stack

it人员无论是使用哪种高级语言开发东东,想要更高效有层次的开发程序的话都躲不开三件套:数据结构,算法和设计模式。数据结构是相互之间存在一种或多种特定关系的数据元素的集合,即带“结构”的数据元素的集合,“结构”就是指数据元素之间存在的关系,分为逻辑结构和存储结构。此系列专注讲解数据结构数组、链表、队列、栈、树、哈希表、图,通过介绍概念以及提及一些可能适用的场景,并以C++代码简易实现,多方面认识数据结构,最后为避免重复造轮子会浅提对应的STL容器。本文介绍的是栈Stack。

weixin_45068267的博客 1751

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

【轻松掌握数据结构】栈

本章主要讲栈的概念及其应用,简单易懂~ 本文以生动形象的"书箱"比喻介绍了栈(Stack)这一数据结构。栈是一种遵循"后进先出"(LIFO)原则的线性表,主要操作包括压栈(push)和出栈(pop)。文章详细讲解了栈的基本概念,并通过Java代码示例演示了Stack类的常用方法如peek()、size()、empty()等。最后通过选择题和编程题展示了栈的实际应用场景,如括号匹配等问题。全文语言通俗易懂,配合代码实例和图示,帮助读者快速理解栈的核心特性和使用方法。

哦虎!的博客 590

数据结构入门:栈

无论你是计算机科学专业的学生、程序设计的爱好者,还是正在准备面试的求职者,本文将为你提供一份全面而深入的栈和队列指南。让我们一起探索栈和队列的双重魅力,为你的编程之路增添新的色彩。int top;}Stack;栈中有栈顶(top),有栈的容量(size),还有存储的数据(a);栈是一种重要的数据结构,它以后进先出的方式操作数据。栈在递归算法、表达式求值、函数调用等场景中发挥着重要作用。通过学习栈,我们能够更好地理解数据结构的本质和算法的设计思想。

2202_75605090的博客 7579

【Java】轻松掌握栈的基本操作

轻松掌握栈的基本操作1、栈的基本概念2、栈的实现3、栈常见的算法题目 1、栈的基本概念 如何理解栈 对于栈,首先列举一个生活案例,家里的厨房通常都放有很多盘子。每次洗好的盘子总是堆叠在一起,如图所示,ABC三个盘子: 我们在洗碗的时候,先洗好的放在下面,后洗好的放在上面 反过来每次使用盘子的时候,总是先拿上面的盘子,后拿下面的盘子 如果用专业术语表示,则为:后进先出、先进后出,这就是栈的特性 2、栈的实现 栈的使用场景非常广泛,所以在编程各类语言中都有栈的实现,例如在 Java 中,栈的数据结构类是

叮当猫的博客 8834

栈(LIFO,Last In First Out)是一种数据结构,它遵循后进先出的原则

这意味着最后一个被添加到栈中的元素将是第一个被移除的元素,而第一个被添加到栈中的元素将是最后一个被移除的元素。遍历字符串,遇到左括号时将其压入栈中,遇到右括号时尝试弹出栈顶的左括号。如果栈为空或栈顶的左括号与当前的右括号不匹配,则说明括号不匹配。遍历字符串,遇到左括号时将其压入栈中,遇到右括号时尝试弹出栈顶的左括号。通过这些作用,栈在操作系统中扮演着至关重要的角色,不仅支持了高效的函数调用和进程管理,还确保了线程调度的正确性和效率。总之,栈在编程中的用途非常广泛,它在许多算法和程序设计中都发挥着重要作用。

[Blog][Domain] programb.blog.youkuaiyun.com 901

【C++进阶】深入STL之 栈与队列:数据结构探索之旅

在编程的世界里,数据结构是构建高效、可靠程序的基础。它们就像是我们编程工具箱中的精密工具,帮助我们解决各种复杂的问题。而在C++的STL中,栈(Stack)和队列(Queue)是两种非常重要的数据结构,它们以不同的方式管理和操作数据,为我们的程序提供了极大的灵活性,为了真正掌握它们,我们需要深入学习它们在STL中的实现方式,理解它们背后的原理和机制,以及学习如何在实际编程中有效地使用它们,让我们一起踏上学习STL栈与队列的旅程吧!

EterNity_TiMe_的计算机学习之路 3351

深入理解 JavaScript 栈 (Stack):后进先出 (LIFO) 的数据结构

栈(Stack)是一种遵循后进先出(LIFO)原则的数据结构,常用于函数调用、表达式求值等场景。本文介绍了JavaScript中栈的两种实现方式:基于数组和基于链表。数组实现利用原生方法push()和pop()实现高效操作;链表实现则通过节点操作模拟栈行为。两种方式均支持入栈、出栈、查看栈顶等基本操作,但数组实现通常性能更优。文章还讨论了栈的应用场景、时间复杂度分析及最佳实践,为算法和系统设计奠定基础。

weixin_42107409的博客 672

Java数据结构与算法中级篇之栈、队列、链表

数据是基础,算法是灵魂 版权声明,本文来自门心叼龙的博客,属于原创内容,转载请注明出处。https://blog.youkuaiyun.com/geduo_83/article/details/86466640 源码下载地址:https://download.youkuaiyun.com/download/geduo_83/10913510 初级篇:Java数据结构与算法初级篇之数组、集合和散列表 中级篇:Ja...

门心叼龙的专栏 4769

从零开始学习数据结构与算法:Python实现

数据结构与算法是计算机科学中至关重要的概念之一,对于任何想要成为优秀程序员的人来说,深入理解它们是必不可少的。本文将介绍如何从零开始学习数据结构与算法,并使用Python语言实现一些基本的数据结构和算法,帮助读者入门。

一键难忘的博客 4093

数据结构与算法——栈

1. 概述 今天来看看栈这种线性数据结构,非常的基础,我举个例子你就能明白了。比如你桌子上堆放的一摞文件,最先放的在最下面,拿的时候也是最后拿,最后放的在最上面,拿的时候也先拿到。这种满足了 先进后出,后进先出 特点的数据结构,就叫做栈。 相信结合上图你能够看到,栈这种数据结构,插入和删除的操作都被局限在了栈的一端,插入数据叫做入栈,删除数据叫做出栈。 2. 栈的实现 栈有两种实现方式,...

roseduan 的个人博客 960

数据结构专栏:第四篇 栈与队列

这种行为模式,我们称之为。

u012133341的博客 759
上一篇: 【轻松掌握数据结构与算法】链表:灵活的数据结构
下一篇: 【轻松掌握数据结构与算法】队列:先进先出的数据结构
Whoisbug
博客等级 码龄9年 894粉丝 57原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值