数据结构与算法-栈(Stack)

本文介绍了栈这种运算受限的线性表,限定仅在表头进行插入和删除操作,具有后入先出特点。采用数组实现栈,还阐述了栈在判断回文和递归演示方面的应用,强调栈是一种数据处理逻辑思想。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

栈(stack)又名堆栈,它是一种运算受限的线性表

定义:栈是限定仅在表头进行插入和删除操作的线性表。要搞清楚这个概念,首先要明白”栈“原来的意思,如此才能把握本质。"栈“者,存储货物或供旅客住宿的地方,可引申为仓库、中转站,所以引入到计算机领域里,就是指数据暂时存储的地方,所以才有进栈、出栈的说法。

比如我们在洗盘子时,一碟盘子可以想象成一个栈,只能从最上面取盘子,盘子洗净后,放在另一个地方也只能摞在盘子的最上面。这种后入先出(LIFO,last-in-first-out)的数据结构被称为栈。

栈的实现

实现一个栈,就得决定存储数据的底层数据结构,这里采用数组。

// 实现Stack类的构造函数
function Stack () {
    this.dataStore = [] // 保存栈内元素
    this.top = 0 // 记录栈顶位置
}
Stack.prototype = {
    constructor: Stack,
    push: function (element) {
        this.dataStore[this.top] = element
        this.top++
    },
    pop: function () {
        return this.dataStore[--this.top]
    },
    peek: function () {
        return this.dataStore[this.top - 1]
    },
    length: function () {
        return this.top
    },
    clear: function () {
        this.top = 0
    }
}
复制代码

栈的应用

1.回文

一个单词,短语或数字,从前往后写和从后往前写都是一样的,就是回文。

将拿到的字符串的每个字符按照从左到右的顺序压入栈,当字符串中的字符都入栈后,栈内就保存了一个反转后的字符串,判断两个字符串是否相等即可。

function isPalindrome (word) {
    var s = new Stack()
    for (var i = 0; i < word.length; i++) {
        s.push(word[i])
    }
    var rword = ''
    while (s.length() > 0) {
        rword += s.pop()
    }
    if (word === rword) {
        return true
    } else {
        return false
    }
}
复制代码

2.递归演示

用栈模拟实现递归

首先将数字从5到1压入栈,然后使用一个循环,将数字挨个弹出连乘。

// 5! = 5 * 4 * 3 * 2 * 1
function fact(n) {
    var s = new Stack()
    while (n > 1) {
        s.push(n--)
    }
    var product = 1
    while (s.length() > 0) {
        product *= s.pop()
    }
    return product
}
复制代码

栈是一种思想,对数据的处理逻辑,比如在生活中的做事情的先后顺序。计算机是人开发出来的,可以把计算机想象成一个人在做事情,只是它按照人为事先定义好的程序执行,所以机器做事时如果对某一资源有先后关系,比如栈这种后入先出,就要按照栈(这种思想,人为抽象出来叫栈,所以不要纠结它为什么叫栈)执行

转载于:https://juejin.im/post/5ce7cdb3f265da1bbc6fb03b

### 数据结构概述 是一种特殊的线性表,其特点是仅允许在一端进行插入和删除操作。这一端被称为顶,而另一端称为底[^2]。由于所有的操作都集中在顶执行,因此遵循后进先出(LIFO, Last In First Out)的原则。 #### 的核心特性 - **单一入口/出口**:所有元素的进出均通过顶完成。 - **动态调整大小**:可以通过数组或链表实现,并支持动态扩展容量以适应更数据存储需求[^3]。 以下是基于C语言的一个简单实现: ```c typedef struct { int* arr; int top; int capacity; } Stack; void initStack(Stack* s, int size) { s->arr = (int*)malloc(size * sizeof(int)); s->top = -1; s->capacity = size; } bool isFull(Stack* s) { return s->top == s->capacity - 1; } bool isEmpty(Stack* s) { return s->top == -1; } void push(Stack* s, int value) { if (!isFull(s)) { s->arr[++s->top] = value; } } int pop(Stack* s) { if (!isEmpty(s)) { return s->arr[s->top--]; } return -1; // 错误处理 } ``` --- ### 的应用场景 #### 1. 表达式求值括号匹配 常用于解析算术表达式以及验证括号是否正确配对。例如,在检查字符串中的括号合法性时,可以利用记录未闭合的左括号,并逐一尝试其对应的右括号相匹配[^4]。 #### 2. 函数调用管理 程序运行过程中涉及大量子过程调用,操作系统会借助保存返回地址及相关参数信息以便稍后恢复上下文环境[^1]。 #### 3. 迷宫路径寻找 当解决迷宫问题或者遍历复杂网络节点的时候,采用深度优先搜索策略往往依赖于显式的堆机制来追踪已探索过的路线方向[^2]。 #### 4. 文本编辑器撤销功能 为了提供用户友好的体验,许应用程序实现了“Undo”命令,这背后正是依靠内部维护了一个历史动作列表作为隐含形式存在的实例[^3]。 --- ### 可视化案例分析 假设我们有一个简单的四则运算表达式 `(3 + (4 - 9) * (3 / 4) * (3 + 2))` ,要计算该公式的最终数值结果,则需按照特定顺序逐步拆解并评估各部分子表达式的贡献度。此时便可通过创建两个独立的工作区分别存放待处理的操作符中间临时变量来进行高效组织管理工作流程[^4]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值