web前端算法简介之栈

栈是一种数据结构,它是一种特殊的线性表。

栈具有 先进后出(LIFO)的特性 ,也就是最后进入栈的元素最先出栈,而最先进入栈的元素最后出栈。

栈通常有两个基本操作:压栈(push)出栈(pop)

压栈是将元素加入栈顶,而出栈是将栈顶元素移除。

栈可以用来进行函数调用的处理、表达式求值、以及其他需要后进先出特性的算法和数据结构。

栈通常用于实现递归算法表达式求值、以及其他需要临时存储临时数据的场景。

举个例子:

假设我们有一个整数栈,我们可以使用栈来模拟浏览器的"后退"功能。

每当用户访问一个新的网页时,我们将该网页的信息入栈。

当用户想要返回上一页时,我们可以从栈中弹出最近访问的网页信息,实现类似后退功能的效果。

栈的基本操作包括:

栈(Stack)是一种线性数据结构,只允许在一端进行插入和删除操作。栈的典型应用场景是函数调用栈、表达式求值、括号匹配等。

栈的操作主要包括以下几种:

初始化栈(InitStack)
  • 这是创建一个空栈的过程,通常包括分配一定的存储空间。
判断栈是否为空(IsStackEmpty)
  • 检查栈中是否没有元素,如果栈顶指针指向NULL或者栈的大小为0,那么栈为空。
入栈(Push)
  • 将一个元素添加到栈顶。例如,如果我们有一个栈S,我们想要将元素e推入栈中,我们可以这样做:

    复制代码
    Push(S, e)

    这将使得e成为新的栈顶元素。

出栈(Pop)
  • 删除栈顶元素并返回其值。例如,从栈S中弹出栈顶元素:

    复制代码
    value = Pop(S)

    这将删除栈顶元素,并将它的值赋给变量value。剩余的元素会向上移动,新的栈顶元素变为原来栈顶元素的下一个元素。

获取栈顶元素(GetTop)
  • 返回栈顶元素的值但不删除它。例如:

    复制代码
    top_element = GetTop(S)
获取栈的大小(StackSize)
  • 返回栈中元素的数量。
销毁栈(DestroyStack)
  • 释放栈占用的内存资源。

这些操作都是基于栈的后进先出(LIFO)原则进行的,即最后进入栈的元素最先被移出。

以下是一个简单的栈的实现示例,使用JavaScript语言实现:

javascript 复制代码
class Stack {
  constructor() {
    this.items = [];
  }

  push(item) {
    this.items.push(item);
  }

  pop() {
    return this.items.pop();
  }

  top() {
    return this.items[this.items.length - 1];
  }

  isEmpty() {
    return this.items.length === 0;
  }
}

// 使用示例:
const stack = new Stack();
stack.push(1);
stack.push(2);
stack.push(3);
console.log(stack.pop()); // 输出3
console.log(stack.top()); // 输出2
console.log(stack.isEmpty()); // 输出false

在上面的示例中,我们定义了一个Stack类,包含了常用的栈操作方法:

  • push、
  • pop、
  • top
  • isEmpty。

我们可以通过创建一个Stack的实例来使用这些方法,对栈进行添加、删除、获取栈顶元素和判断是否为空等操作。

更多详细内容,请微信搜索"前端爱好者"戳我 查看

关于栈的前端算法题

有效的括号

leetcode地址:https://leetcode.cn/problems/valid-parentheses/

给定一个只包括 '(',')','{','}','[',']' 的字符串 s ,判断字符串是否有效。

有效字符串需满足:

  • 左括号必须用相同类型的右括号闭合。
  • 左括号必须以正确的顺序闭合。
  • 每个右括号都有一个对应的相同类型的左括号。

示例 1:

复制代码
输入:s = "()"
输出:true
示例 2:

输入:s = "()[]{}"
输出:true
示例 3:

输入:s = "(]"
输出:false

提示:

复制代码
1 <= s.length <= 104
s 仅由括号 '()[]{}' 组成

实现代码

JavaScript 复制代码
/**
 * @param {string} s
 * @return {boolean}
 */
var isValid = function (s) {
    // 新建一个数组(创建一个栈)
    var stack = []

    // 循环数组
    for (let i = 0; i < s.length; i++) {
        // 记录当前字符
        const start = s[i]

        // 如果当前字符等于小括号或者大括号或者中括号的左半边,则入栈
        if (s[i] == '(' || s[i] == '{' || s[i] == '[') {
            stack.push(s[i])
        } else {
            // 取出栈内最后一个元素
            const end = stack[stack.length - 1]
             // 如果当前字符等于小括号或者大括号或者中括号的有半边,则出栈
            if (start == ')' && end == '(' || start == '}' && end == '{' || start == ']' && end == '[') {
                stack.pop();
            } else {
                return false
            }
        }
    }

    return stack.length == 0
};

删除字符串中的所有相邻重复项

leetcode地址:https://leetcode.cn/problems/remove-all-adjacent-duplicates-in-string/

给出由小写字母组成的字符串 'S',重复项删除操作会选择两个相邻且相同的字母,并删除它们

在 S 上反复执行重复项删除操作,直到无法继续删除。

在完成所有重复项删除操作后返回最终的字符串。答案保证唯一。

示例:

复制代码
输入:"abbaca"
输出:"ca"
解释:
例如,在 "abbaca" 中,我们可以删除 "bb" 由于两字母相邻且相同,这是此时唯一可以执行删除操作的重复项。之后我们得到字符串 "aaca",其中又只有 "aa" 可以执行重复项删除操作,所以最后的字符串为 "ca"。

提示:

复制代码
1 <= S.length <= 20000
S 仅由小写英文字母组成。

实现代码

js 复制代码
/**
 * @param {string} s
 * @return {string}
 */
var removeDuplicates = function (s) {
    // 新建一个栈,空栈
    let stack = []

    //循环字符串
    for (value of s) {
        let prev = stack.pop() // 删掉头部元素

        // 当前删除元素不等于当前循环元素,则入栈,并且当前循环元素也入栈
        // 如果二者相等,则没有入栈,直接抛弃掉了
        if (prev != value) {
            stack.push(prev)
            stack.push(value)
        }
    }

    return stack.join('')

};

简化路径

给你一个字符串 path ,表示指向某一文件或目录的 Unix 风格 绝对路径 (以 '/' 开头),请你将其转化为更加简洁的规范路径。

在 Unix 风格的文件系统中,一个点(.)表示当前目录本身;此外,两个点 (...) 表示将目录切换到上一级(指向父目录);两者都可以是复杂相对路径的组成部分。任意多个连续的斜杠(即,'//')都被视为单个斜杠 '/' 。 对于此问题,任何其他格式的点(例如,'...')均被视为文件/目录名称。

请注意,返回的 规范路径 必须遵循下述格式:

  • 始终以斜杠 '/' 开头。
  • 两个目录名之间必须只有一个斜杠 '/' 。
  • 最后一个目录名(如果存在)不能 以 '/' 结尾。
  • 此外,路径仅包含从根目录到目标文件或目录的路径上的目录(即,不含 '.' 或 '...')。

返回简化后得到的 规范路径 。

复制代码
示例 1:

输入:path = "/home/"
输出:"/home"
解释:注意,最后一个目录名后面没有斜杠。 
示例 2:

输入:path = "/../"
输出:"/"
解释:从根目录向上一级是不可行的,因为根目录是你可以到达的最高级。
示例 3:

输入:path = "/home//foo/"
输出:"/home/foo"
解释:在规范路径中,多个连续斜杠需要用一个斜杠替换。
示例 4:

输入:path = "/a/./b/../../c/"
输出:"/c"

提示:

复制代码
1 <= path.length <= 3000
path 由英文字母,数字,'.','/' 或 '_' 组成。
path 是一个有效的 Unix 风格绝对路径。

实现源码

js 复制代码
/**
 * @param {string} path
 * @return {string}
 */
var simplifyPath = function (path) {
    // 新建一个栈,空栈
    let stack = []
    let str = ''; // 返回的字符

    // 拆分数组
    let arr = path.split('/')

    // 循环拆分的数组
    arr.forEach(item => {
        // item存在并且等于'..',则出栈
        if (item && item == '..') {
            stack.pop()
        } else if (item && item != '.') {
            // item存在并且不等于'.',则进栈
            stack.push(item)
        }
    })

    // 判断数组、栈是否有值,如果有值,则需要join一下,最后前面拼接字符串'//
    arr.length ? str = '/' + stack.join('/') : str = '/'

    // 返回字符串
    return str
};
相关推荐
Lee川2 分钟前
🎬 从标签到屏幕:揭秘现代网页构建与适配之道
前端·面试
Jay Kay15 分钟前
GVPO:Group Variance Policy Optimization
人工智能·算法·机器学习
Epiphany.55627 分钟前
蓝桥杯备赛题目-----爆破
算法·职场和发展·蓝桥杯
Ticnix29 分钟前
ECharts初始化、销毁、resize 适配组件封装(含完整封装代码)
前端·echarts
纯爱掌门人32 分钟前
终焉轮回里,藏着 AI 与人类的答案
前端·人工智能·aigc
twl36 分钟前
OpenClaw 深度技术解析
前端
崔庆才丨静觅39 分钟前
比官方便宜一半以上!Grok API 申请及使用
前端
星光不问赶路人1 小时前
vue3使用jsx语法详解
前端·vue.js
YuTaoShao1 小时前
【LeetCode 每日一题】1653. 使字符串平衡的最少删除次数——(解法三)DP 空间优化
算法·leetcode·职场和发展
天蓝色的鱼鱼1 小时前
shadcn/ui,给你一个真正可控的UI组件库
前端