栈的定义、存储结构、基本操作、案例

news2024/11/10 18:44:08

📝个人主页:爱吃炫迈
💌系列专栏:数据结构与算法
🧑‍💻座右铭:道阻且长,行则将至💗

文章目录

  • 栈的存储
  • 栈的基本操作
    • 进栈
    • 出栈
    • 读栈顶元素
    • 记录栈内元素个数
    • 清除栈内所有元素
    • 测试
  • 案例
  • 💞总结💞



栈是仅限定在表尾进行插入或删除操作的线性表。

  • 因此,对线性表来说,表尾端称为栈顶,表头端称为栈底

栈的示意图

20190401234941324

如上图所示,假设某个栈S={a1,a2, a3 ,a4},则a1为栈底元素,a4为栈顶元素。栈中元素进栈顺序为a1,a2, a3 ,a4,出栈顺序为a4,a3 ,a2,a1。换句话说,栈的修改是按后进先出的原则进行的。因此栈又称为是后进先出(简称LIFO结构)的线性表。


栈的存储

和线性表类似,栈也有两种存储表示方法,顺序栈和链栈

  • 采用顺序存储的栈称为顺序栈,它利用一组地址连续的存储单元存放自栈底到栈顶的数据元素,同时附设一个指针(top)指示当前栈顶元素在顺序栈中的位置。
    请添加图片描述

基于JS数组实现

class ArrayStack {
  constructor() {
    this.stack = [];
  }
  // 压栈
  push(item) {
    return this.stack.push(item);
  }
  // 弹栈
  pop() {
    return this.stack.pop();
  }
  // 取栈顶元素
  peek() {
    if (this.stack.length >= 1)
      return this.stack[this.stack.length - 1];
  }
  // 清空栈
  clear() {
    this.stack = [];
  }
  // 判断栈是否为空
  isEmpty() {
    return this.stack.length === 0;
  }
}

基本JS对象实现

class ObjectStack {
  constructor() {
    this.stack = {};
    this.top = -1;
  }
  // 压栈
  push(item) {
    return this.stack[++this.top] = item;
  }
  // 弹栈
  pop() {
    if (this.top > -1) {
      const res = this.stack[this.top];
      delete this.stack[this.top--]
      return res;
    }
    return null;
  }
  // 取栈顶元素
  peek() {
    if (this.top > -1) {
      return this.stack[this.top];
    }
    return null;
  }
  // 清空栈
  clear() {
    this.stack = {};
    this.top = -1;
  }
  // 判断栈是否为空
  isEmpty() {
    return this.top === -1;
  }
}
  • 采用链式存储的栈称为链栈,链栈便于多个栈共享存储空间和提高其效率,且不存在栈满上溢的情况。通常采用单链表实现,并且所有操作都是在单链表的表头进行的。

Snipaste_2023-04-19_09-57-05

节点结构

数据域:数据域保存数据

指针域:指针域保存指向下一节点的指针。

class Node {
  constructor(value) {
    this.value = value;
    this.next = null;
  }
}

完整代码

class LinkStack {
  constructor() {
    this.top = null;
    this.count = 0;
  }
  // 压栈
  push(item) {
    const node = new Node(item);
    node.next = this.top;
    this.top = node;
    this.count++;
  }
  // 弹栈
  pop() {
    if (this.count > 0) {
      const res = this.top.value;
      this.top = this.top.next;
      this.count--;
      return res;
    }
    return null;
  }
  // 清空栈
  clear() {
    this.top = null;
    this.count = 0;
  }
  // 取栈顶元素
  peek() {
    if (this.count > 0) {
      return this.top.value;
    }
    return null;
  }
  // 判断栈是否为空
  isEmpty() {
    return this.count === 0;
  }
}

栈的基本操作

实现一个栈,当务之急是决定存储数据结构的底层数据结构,这里采用的是数据。

//定义一个Stack类的构造函数
function Stack(){
    this.dataStore = [] //保存栈内元素
    this.top = 0; //记录栈顶位置
    this.push = push; //元素入栈
    this.pop = pop; //元素出栈
    this.peek = peek; //预览栈顶元素
    this.clear = clear; //清除栈内所有元素
    this.length = length; //记录栈内元素个数
}

进栈

function push(element) {
    this.dataStore[this.top++] = element;
}

出栈

function pop() {
    return this.dataStore[--this.top];
}

读栈顶元素

function peek() {
    return this.dataStore[this.top - 1];
}

记录栈内元素个数

function length() {
    return this.top;
}

清除栈内所有元素

function clear() {
    this.top = 0;
}

测试

let s = new Stack();
s.push("jack");
s.push("kobe");
s.push("Tom");
console.log("length:" + s.length()); //lengeh:3
console.log("top:" + s.top); //top:3
console.log("peek:" + s.peek()); //peek:Tom
let popItem = s.pop();
console.log(popItem); //Tom
s.clear();
console.log("length:" + s.length()); //length:0
s.push("Lily");
console.log(s.peek()); //Lily

案例

题目描述 :有效的括号

Snipaste_2023-04-19_10-32-05

解题思路

  1. 构建栈,遍历字符串s
  2. 遇到左括号就压入栈中,遇到右括号则判断栈顶左括号是否与右括号相匹配,匹配就把栈顶左括号弹出栈,继续遍历字符串s,不匹配则可以直接返回false
  3. 遍历结束后,如果栈内没有剩余左括号,返回true

注意:有效字符串的长度一定为偶数,对于长度为奇数的字符串可以直接返回false

代码实现

var isValid = function(s) { 
    const stack = [];
    if(s.length % 2 == 1) {  
        return false;
    }
    for(let i = 0; i < s.length; i+=1) {  
        const c = s[i];
        if(c === '{' || c === '(' || c === '[') {  
            stack.push(c);
        } else {  
            const t = stack[stack.length - 1];
            if( 
                (t === '(' && c === ')') || 
                (t === '{' && c === '}') || 
                (t === '[' && c === ']')  
            ) {  
                stack.pop();
            } else { 
                return false ;
            }
        }
    }
    return stack.length === 0;
}

💞总结💞

希望我的文章能对你学习栈的知识点有所帮助!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/441065.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

详版Git命令播报

文章目录 下载安装Git 配置config文件配置用户信息查看配置信息 工作协作流程git四个区协作流程 初始化新仓库检出仓库git clonegit remote本地存有代码进行clone没有git仓库已存在git仓库 提交与修改git add 及 git statusgit diffgit commitgit resetgit rmgit mv 查看提交历…

DHCP故障定位

1.请分析可能的原因,定位并排除故障。 (1)存在仿冒DHCP服务器攻击 导致部分有线终端获取到错误的IP地址、网关等信息,进而导致无法访问网关。 解决办法:为了防止DHCP Server仿冒者攻击,将与合法DHCP服务器直接或间接连接的接口设置为信任接口,其他接口设置为非信信任接…

Flutter开发日常练习-pageview滑动视图动画

养小猫咪的伙伴来我的店铺逛逛吧!抖音商城搜索#早睡早起的猫咪小铺子 学着写一下滑动页面 pageview实现左右滑动视图 class SlidingContainer extends StatefulWidget {const SlidingContainer({super.key});overrideState<SlidingContainer> createState() > _Slidi…

【C语言学习3——基本的C语言语法知识2】

C语言学习3——基本的C语言语法知识 标识符关键词什么是字面常量&#xff1f;printf函数printf函数更多用法 #include命令 标识符 在前面的代码中&#xff0c;由我们自己命名&#xff0c;用于指代某一个实体的名称&#xff0c;例如:add&#xff0c;result&#xff0c;函数的参…

【Qt笔记】5.QWidget源码查阅

文章目录 1 概述2 相关成员函数详解2.1 构造函数2.2 设置尺寸2.3 槽函数 1 概述 QWidget类是所有用户界面对象的基类。从QObject和QPaintDevice里继承过来 class Q_WIDGETS_EXPORT QWidget : public QObject, public QPaintDevice由上可以看出qt是把其封装成dll供外部接口调用…

vue2引入Element UI的详细步骤

目录 一、Element UI介绍 Element UI的特点&#xff1a; vue3引入Element plus的文章&#xff1a; 二、操作步骤 三、快速上手测试&#xff08;可做可不做&#xff09; 一、Element UI介绍 Element UI是一个基于Vue.js的组件库&#xff0c;提供了一套丰富、美观、易用的…

《类和对象》(下篇)

本文主要讲解类和对象的一些其他小知识。 文章目录 前情回顾一、用运算符重载写一个输入流和输出流①流插入②流提取③流提取和流插入的优化 二、const成员三、用运算符重载改变数组 1、再谈构造函数1.1 构造函数体赋值(不相当于初始化)1.2 初始化列表①引出初始化列表②怎么用…

GBDT+LR论文翻译

0.摘要 在线广告允许广告客户仅针对可衡量的用户响应进行出价和付费&#xff0c;例如广告点击。因此&#xff0c;点击预测系统是大多数在线广告系统的核心。伴随每日活跃用户超过7.5亿&#xff0c;活跃广告客户超过100万的情况&#xff0c;预测Facebook广告点击是一项具有挑战…

【题解】P4055 [JSOI2009] 游戏

link 题目大意 题目说得比较清楚。 题解 前置知识&#xff1a;二分图最大匹配、基础博弈论。 每个点只能走一次的四联通点阵&#xff0c;可以想到二分图匹配。 将其套路地奇偶分点&#xff0c;相邻两点连边&#xff08;显然不能为 #&#xff09;。 先求一个最大匹配。 …

单片机 0~10V 输出电路的实现

聊聊单片机实现 0~10V 输出电路的几种方案 ...... by 矜辰所致目录 前言一、MCU 的 DAC二、PWM 加滤波电路2.1 PWM 输出 DAC2.2 PWM 接滤波器的RC值选择说明2.3 0~ 3.3V PWM 输出 0 ~10V方案一&#xff1a;RC 滤波器方案二&#xff1a;三极管 三、专用转换芯片结语 前言 好…

操作系统(3.1)--处理机调度和作业

目录 一、处理机调度层次 1.高级调度(High Level Scheduling) 2.低级调度&#xff08;Low Level Scheduling) 3.中级调度(Intermediate Scheduling) 二、处理机调度算法的目标 1.处理机调度算法的共同目标 2.批处理系统的目标 3.分时系统的目标 三、批处理系统中的作业…

【k8s完整实战教程3】k8s集群部署kubesphere

系列文章&#xff1a;这个系列已完结&#xff0c;如对您有帮助&#xff0c;求点赞收藏评论。 读者寄语&#xff1a;再小的帆&#xff0c;也能远航&#xff01; 【k8s完整实战教程0】前言【k8s完整实战教程1】源码管理-Coding【k8s完整实战教程2】腾讯云搭建k8s托管集群【k8s完…

【C++】海量数据面试题

海量数据面试题 文章目录 海量数据面试题一、哈希切割二、位图应用1.给定100亿个整数&#xff0c;设计算法找到只出现一次的整数2.求两个文件交集3.在100亿个整数中找到出现次数不超过2次的所有整数 三、布隆过滤器1.求两文件交集&#xff08;近似算法&#xff09;2.求两文件交…

气传导和骨传导耳机哪个好?简单科普这两种蓝牙耳机

在生活中&#xff0c;我们经常会用到耳机&#xff0c;特别是在日常娱乐听歌、运动休闲、户外通勤的时候&#xff0c;一款舒适的耳机是必不可少的。 而最近几年&#xff0c;随着科技的发展&#xff0c;各大品牌也相继推出了各种类型的耳机&#xff0c;其中比较热门的就有气传导…

如何在电脑上使用wink一键高清优化短视频画质

如何在电脑上使用wink一键高清优化短视频画质 文章目录 如何在电脑上使用wink一键高清优化短视频画质1.软件简介1.1痛点1.2解决方案 2.实际操作2.1准备工作2.1.1下载雷电模拟器2.1.2下载wink 2.2.安装软件2.2.1安装雷电模拟器2.2.2在雷电模拟器中安装wink 2.3雷电模拟器基本设置…

软件测试实验:Junit单元测试

目录 前言 实验目的 实验内容 实验要求 实验过程 题目一 题目一测试结果 题目二 题目二实验结果 总结 前言 软件测试是软件开发过程中不可缺少的一个环节&#xff0c;它可以保证软件的质量和功能&#xff0c;发现并修复软件的缺陷和错误。软件测试分为多种类型&…

《数据结构》---术语篇

目录 前言: 一.术语 1.1数据 1.2数据结构 1.3逻辑结构和物理结构 二.数据类型和抽象数据类型 ​​​​​​​ ❤博主CSDN&#xff1a;啊苏要学习 ▶专栏分类&#xff1a;数据结构◀ 学习数据结构是一件有趣的事情&#xff0c;希望读者能在我的博文切实感受到&#xff0c…

Numpy从入门到精通——随机生成数组|特定生成数组|规则生成数组

这个专栏名为《Numpy从入门到精通》&#xff0c;顾名思义&#xff0c;是记录自己学习numpy的学习过程&#xff0c;也方便自己之后复盘&#xff01;为深度学习的进一步学习奠定基础&#xff01;希望能给大家带来帮助&#xff0c;爱睡觉的咋祝您生活愉快&#xff01; 这一篇介绍《…

Qt内存管理及泄露后定位到内存泄漏位置的方法

Qt内存管理机制 Qt使用对象父子关系进行内存管理。在创建类的对象时&#xff0c;为对象指定父对象指针。当父对象在某一时刻被销毁释放时&#xff0c;父对象会先遍历其所有的子对象&#xff0c;并逐个将子对象销毁释放。 Qt内存管理代码示例 QLabel *label new QLabel;这里…

【==是判断相等吗?---错辣】C++和JAVA中判断字符串值相等的区别

文章目录 先上结论C中stringJAVA中String回顾结论 参考文章&#xff1a;这里&#xff1b;这里&#xff1b;这里 先上结论 C中的string类型可以使用和!来判断两个字符串的值是否相等&#xff1b;而JAVA不行&#xff0c;JAVA中和!是用来判断两个字符串的地址是否相同&#xff08…