当前位置: 首页 > news >正文

数据结构详细笔记——栈与队列

文章目录

  • 栈的三要素
    • 逻辑结构(定义)
    • 数据的运算(基本操作)
    • 存储结构(物理结构)
      • 顺序栈(顺序存储)
      • 链栈(链式存储)
  • 队列的三要素
    • 逻辑结构(定义)
    • 数据的运算(基本操作)
    • 存储结构(物理结构)
      • 顺序队列(顺序存储)
      • 链式队列(链式存储)
  • 队列的变种
  • 栈在括号匹配中的应用
  • 栈在表达式求值中的应用
    • 中缀表达式 ------>后缀表达式
    • 后缀表达式的计算
    • 中缀表达式 ------>前缀表达式
    • 前缀表达式的计算
    • 用栈实现中缀表达式的计算


栈的三要素

逻辑结构(定义)

栈是只允许在一端进行插入或删除操作的线性表

特点:后进先出(LIFO)

数据的运算(基本操作)

InitStack(&S)
初始化栈:构造一个空栈S,分配内存空间DestroyStack(&S)
销毁栈:销毁并释放栈S所占用的内存空间Push(&S,x)
进栈:若栈S未满,则将x加入使之成为新栈顶Pop(&S,&x)
出栈:若栈非空,则弹出栈顶元素,并用x返回GetTop(S,&x)
读栈顶元素:若栈S非空,则用x返回栈顶元素StackEmpty(S)
判断一个栈S是否为空,若S为空,则返回true,否则返回false

栈的常考题型
已知进栈顺序,问有哪些合法的出栈顺序?
出栈元素不同排列的个数为卡特兰数

存储结构(物理结构)

顺序栈(顺序存储)

顺序栈的定义

#define MaxSize 10
typedef struct{ELemType data[MaxSize];   // 静态数组存放栈中元素int top;                  // 栈顶指针
}SqStack;

初始化栈

void InitStack(SqStack &S){S.top = 0;
}

判空

bool StackEmpty(SqStack S){if(S.top == -1)return true;elsereturn false;
]

进栈操作

bool Push(SqStack &S,ElemType x){if(S.top == MaxSize - 1)renturn false;S.top = S.top + 1;   // 指针先加1S.data[S.top] = x;   // 新元素入栈return true;
}

出栈操作

bool Pop(SqStack &S, ElemType &x){if(S.top == -1)return false;x = S.data[S.top];S.top = S.top - 1;return true;
}

读栈顶元素

bool GetTop(SqStack S, ElemType &x){if(S.top == -1)return false;x = S.data[S.top];return true;
|

共享栈

#define MaxSize 10
typedef struct{ElemType data[MaxSize];int top0;      // 0号栈栈顶指针int top1;      // 1号栈栈顶指针
} ShStack;// 初始化栈
void InitStack(ShStack &S){S.top0 = -1;S.top1 = MaxSize;
}

栈满的条件: top0 + 1 = top1

链栈(链式存储)

链栈的定义
其操作相当于头插法建立单链表(只从表头进行增加删除操作)

typedef struct LinkNode{ELemType data;   // 数据域struct LinkNode *next;     // 指针域
}*LinkStack;

队列的三要素

逻辑结构(定义)

队列是只允许在一端进行插入,在另一端删除的线性表

特点:先进先出(FIFO)

数据的运算(基本操作)

InitQueue(&Q)
初始化队列:构造一个空队列QDestroyQueue(&Q)
销毁队列:销毁并释队列Q所占用的内存空间EnQueue(&Q,x)
入队:若队列Q未满,则将x加入使之成为新的队尾DeQueue(&Q,&x)
出队:若队列非空,删除队头元素,并用x返回GetHead(Q,&x)
读队头元素:若队列Q非空,则用x返回队头元素QueueEmpty(Q)
判断一个队列Q是否为空,若Q为空,则返回true,否则返回false

存储结构(物理结构)

顺序队列(顺序存储)

队列的顺序实现

#define MaxSize 10
typedef struct{ElemType data[MaxSize];int front,rear;
} SqQueue;

初始化队列

void InitQueue(SqQueue &Q){Q.rear = Q.front = 0;
}

判断队列是否为空

bool QueueEmpty(SqQueue Q){if(Q.rear == Qfront)return true;elsereturn false;
}

入队

bool EnQueue(SqQueue &Q,ElemType x){if((Q.rear + 1) % MaxSize == Q.front)return false;    //队满则报错Q.data[Q.rear] = x;Q.rear = (Q.rear + 1) % MaxSize;  //队尾指针加一取模return true;
} 

出队

bool DeQueue(SqQueue &Q,ElemType &x){if(Q.rear == Q.front)return false;   // 队空则报错x = Q.data[Q.front];Q.front = (Q.front + 1) % MaxSize;return true;
}

获取队头元素的值,用x返回

bool GetHead(SqQueue Q,ElemType &x){if(Q.rear == Q.front)return false;x = Q.data[Q.front];return true;
}

队列元素的个数:
(rear - front + MaxSzie)% MaxSize

链式队列(链式存储)

队列的链式实现

typedef struct LinkNode{    // 链式队列结点ElemType data;  struct LinkNode *next;
}LinkNode;typedef struct{             // 链式队列LinkNode *front,*rear;  // 队列的队头和队尾指针
}LinkQueue;

初始化(带头结点)

void InitQueue(LinkQueue &Q){// 初始化 front、rear 都指向头结点Q.front = Q.rear = (LinkNode *) malloc(sizeof(LinkNode));Q.front->next = NULL;
}

队列是否为空

bool IsEmpty(LinkQueue Q){if(Q.rear == Qfront)return true;elsereturn false;
}

新元素入队(带头结点)

void EnQueue(LinkNode &Q,ElemType x){LinkNode *s = (LinkNode *)malloc(sizeof(LinkNode));s->data = x;s->next = null;Q.rear->next = s;Q.rear = s;
}

在这里插入图片描述

入队(不带头结点)

void EnQueue(LinkQueue &Q,ElemType x){LinkNode *s = (LinkNode *)malloc(sizeof(LinkNode));s->data = x;s->next = NULL;if(Q.front == NULL){   // 在空队列中插入第一个元素Q.front = s;       // 修改队头队尾的指针Q.rear = s;} else{Q.rear->next = s;Q.rear = s;}
}

出队(带头结点)

bool DeQueue(LinkQueue &Q,ElemType &x){if(Q.front == Q.rear)return false;    // 空队LinkNode *p = Q.front->next;x = p.data;Q.front->next = p->next;if(Q.rear == p)   // 此次是最后一个结点出队Q.rear = Q.front;free(p);          // 释放结点空间return true;
}

出队(不带头结点)

bool DeQueue(LinkQueue &Q,ElemType &x){if(Q.front == NULL)return false;LinkNode *p = Q.front;x = p->data;Q.front = p->next;if(Q.rear = p)[Q.front = NULL;Q.rear = NULL;}free(p);return true;
}

队列的变种

双端队列:允许从两端插入、两端删除的队列

输入受限的双端队列:允许从两端删除、从一端插入的队列

输出受限的双端队列:允许从两端插入、从一端删除的队列

考点:对输出序列的合法性的判断

栈在括号匹配中的应用

括号匹配流程图

代码实现

#define MaxSize 10
typedef struct{char data[MaxSize];int top;
}SqStack;// 初始化栈
void InitStack(SqStack &S)// 判断栈是否为空
bool StackEmpty(SqStack S)// 新元素入栈
bool Push(SqStack &S,char x)// 栈顶元素出栈,用x返回
bool Pop(SqStack &S,char &x)bool bracketCheck(char str[],int length){SqStack S;InitStack(S);  // 初始化for(int i = 0; i < length; i++){if(str[i] == '(' || str[i] == '[' || str[i] == '{'){Push(S, str[i]);  // 扫描到左括号,入栈} else {if(StackEmpty(S))  // 扫描到右括号,并且当前栈空return false;  // 匹配失败char topElem;Pop(S, topElem);   // 栈顶元素出栈if(str[i] == ')' && topElem != '(')return false;if(str[i] == ']' && topElem != '[')return false;if(str[i] == '}' && topElem != '{')return false;}}return StackEmpty(S);   // 检索完全部括号后,栈空说明匹配成功
} 

栈在表达式求值中的应用

三种算术表达式:
1、中缀表达式:运算符在两个操作数中间 —— a+b
2、后缀表达式(逆波兰表达式):运算符在两个操作数后面 —— ab+
3、前缀表达式(波兰表达式):运算符在两个操作数前面 —— +ab

中缀表达式 ------>后缀表达式

手算

1、确定中缀表达式中各个运算符的运算顺序
2、选择下一个运算符,按照【 左操作符 右操作符 运算符 】的方式组合成一个新的操作数
3、如果还有运算符没被处理,就继续2
注意:为了保证手算和机算结果相同,采用“左优先”原则:只有左边的运算符能先运算,就优先算左边(可保证运算顺序唯一)

机算

初始化一个栈,用于保存暂时还不能确定运算顺序的运算符
从左到右处理各个元素,直到末尾,可能遇到三种情况:
1、遇到操作数:直接加入后缀表达式
2、遇到界限符:遇到 “ ( ” 直接入栈,遇到 “ ) ” 则依次弹出栈内运算符并加入后缀表达式,直到弹出 “ ( ” 为止。注意:“ ( ” 不加入后缀表达式
3、遇到运算符:依次弹出栈中优先级高于或者等于当前运算符的所有运算符,并加入后缀表达式,若碰到 “ ( ” 或栈空则停止。之后再把当前的运算符入栈
4、处理完所有字符后,将栈中剩余运算符依次弹出,并加入后缀表达式

后缀表达式的计算

1、从左往右扫描下一个元素,直到处理完所有的元素
2、若扫描到操作数则压入栈,并回到1;否则执行3
3、若扫描到运算符,则弹出两个栈顶元素,执行相应运算(先出栈的是右操作数),运算结果压回栈顶,回到1
4、若表达式合法。则最后栈中只会留下一个元素,就是最终结果

中缀表达式 ------>前缀表达式

1、确定中缀表达式中各个运算符的运算顺序
2、选择下一个运算符,按照【 运算符 左操作符 右操作符 】的方式组合成一个新的操作数
3、如果还有运算符没被处理,就继续2
注意:为了保证手算和机算结果相同,采用“右优先”原则:只有右边的运算符能先运算,就优先算右边(可保证运算顺序唯一)

前缀表达式的计算

1、从右往左扫描下一个元素,直到处理完所有的元素
2、若扫描到操作数则压入栈,并回到1;否则执行3
3、若扫描到运算符,则弹出两个栈顶元素,执行相应运算(先出栈的是左操作数),运算结果压回栈顶,回到1
4、若表达式合法。则最后栈中只会留下一个元素,就是最终结果

用栈实现中缀表达式的计算

中缀表达式 ------>后缀表达式后缀表达式的计算 的结合

*初始化两个栈:操作数栈 和 运算符栈
若扫描到操作数,压入操作数栈
若扫描到运算符或者界限符,则按照“中缀转后缀”相同的逻辑压入运算符栈
每当弹出一个运算符时,就需要在弹出两个操作数栈的栈顶元素并执行相应的运算,运算结果再压回操作数栈中

相关文章:

数据结构详细笔记——栈与队列

文章目录 栈的三要素逻辑结构&#xff08;定义&#xff09;数据的运算&#xff08;基本操作&#xff09;存储结构&#xff08;物理结构&#xff09;顺序栈&#xff08;顺序存储&#xff09;链栈&#xff08;链式存储&#xff09; 队列的三要素逻辑结构&#xff08;定义&#xf…...

JVM调试命令与调试工具

目录 一、JDK自带命令 1、jps 2、jstat&#xff08;FullGC频繁解决方案&#xff09; 3、jmap 4、jhat 5、jstack(cpu占用高解决方案) 6、jinfo 二、JDK的可视化工具JConsole 1、JConsole 2、VisualVM 一、JDK自带命令 Sun JDK监控和故障处理命令如&#xff1a; 1、jps JVM Proc…...

《软件方法》第1章2023版连载(07)UML的历史和现状

DDD领域驱动设计批评文集 做强化自测题获得“软件方法建模师”称号 《软件方法》各章合集 1.3 统一建模语言UML 1.3.1 UML的历史和现状 上一节阐述了A→B→C→D的推导是不可避免的&#xff0c;但具体如何推导&#xff0c;有各种不同的做法&#xff0c;这些做法可以称为“方…...

chromium 54 chrome 各个版本发布功能列表(109-119)

chromium Features 109-119 From https://chromestatus.com/features chromium109 Features:12 Auto range support for font descriptors inside font-face rule Auto range support for variable fonts in ‘font-weight’, ‘font-style’ and ‘font-stretch’ descrip…...

Linux实现原理 — I/O 处理流程与优化手段

Linux I/O 接口 Linux I/O 接口可以分为以下几种类型&#xff1a; 文件 I/O 接口&#xff1a;用于对文件进行读写操作的接口&#xff0c;包括 open()、read()、write()、close()、lseek() 等。 网络 I/O 接口&#xff1a;用于网络通信的接口&#xff0c;包括 socket()、conne…...

第 367 场 LeetCode 周赛题解

A 找出满足差值条件的下标 I 模拟 class Solution { public:vector<int> findIndices(vector<int> &nums, int indexDifference, int valueDifference) {int n nums.size();for (int i 0; i < n; i)for (int j 0; j < i; j)if (i - j > indexDiffe…...

最新百度统计配置图文教程,获取siteId、百度统计AccessToken、百度统计代码教程

一、前言 很多网友开发者都不知道百度统计siteId、百度统计token怎么获取&#xff0c;在网上找的教程都是几年前老的教程&#xff0c;因此给大家出一期详细百度统计siteId、百度统计token、百度统计代码获取详细步骤教程。 二、登录到百度统计 1.1 登录到百度统计官网 使用…...

【C++ 学习 ㉘】- 详解 C++11 的列表初始化

目录 一、C11 简介 二、列表初始化 2.1 - 统一初始化 2.2 - 列表初始化的使用细节 2.2.1 - 聚合类型的定义 2.2.2 - 注意事项 2.3 - initializer_list 2.3.1 - 基本使用 2.3.2 - 源码剖析 一、C11 简介 1998 年&#xff0c;C 标准委员会发布了第一版 C 标准&#xff0…...

OpenCV12-图像卷积

OpenCV12-图像卷积 图像卷积 图像卷积 OpenCV中提供了filt2D()函数用于实现图像和卷积模板之间的卷积运算&#xff1a; void filter2D(InputArray src, // 输入图像OutputArray dst, // 输出图像int ddepth, // 输出图像数据类型&#xff08;深度&#xff09;&#xff…...

MVCC与BufferPool缓存机制

MVCC多版本并发控制机制 Mysql在可重复读隔离级别下如何保证事务较高的隔离性&#xff0c;我们上节课给大家演示过&#xff0c;同样的sql查询语句在一个事务里多次执行查询结果相同&#xff0c;就算其它事务对数据有修改也不会影响当前事务sql语句的查询结果。 这个隔离性就是…...

POI、Easy Excel操作Excel

文章目录 1.常用的场景2.基本功能3.Excel在Java中是一个对象4. 简单的写&#xff08;07版本&#xff08;.xlsx&#xff09;Excel&#xff09;大文件写HSSF大文件写XSSF大文件写SXSSF 5. Excel读5.1 读取遇到类型转化问题该怎么解决5.2 遇到Excel公式怎么办 6. Easy Excel6.1简单…...

网络安全(黑客)自学方向

每年报考网络安全专业的人数很多&#xff0c;但不少同学听说千万别学网络安全&#xff0c;害怕网络安全专业很难就业。下面就带大家深入了解一下网络安全专业毕业后可以干什么&#xff0c;包括网络安全专业的就业前景和方向等。 随着信息化时代的到来&#xff0c;网络安全行业…...

react写一个简单的3d滚轮picker组件

1. TreeDPicker.tsx文件 原理就不想赘述了, 想了解的话, 网址在: 使用vue写一个picker插件,使用3d滚轮的原理_vue3中支持3d picker选择器插件-CSDN博客 import React, { useEffect, useRef, Ref, useState } from "react"; import Animate from "../utils/an…...

Compose竖向列表LazyColumn

基础列表一 LazyColumn组件中用items加载数据&#xff0c;rememberLazyListState()结合rememberCoroutineScope()实现返回顶部。 /*** 基础列表一*/ Composable fun Items() {Box(modifier Modifier.fillMaxSize()) {val context LocalContext.currentval dataList arrayLi…...

6.自定义相机控制器

愿你出走半生,归来仍是少年&#xff01; Cesium For Unity自带的Dynamic Camera,拥有优秀的动态展示效果&#xff0c;但是其对于场景的交互方式用起来不是很舒服。 通过模仿Cesium JS 的交互方式&#xff0c;实现在Unity中的交互&#xff1a; 通过鼠标左键拖拽实现场景平移通过…...

一文带你GO语言入门

什么是go语言? Go语言(又称Golang)是Google开发的一种静态强类型、编译型、并发型,并具有垃圾回收功能的编程语言。Go语言的主要特点包括:- 简洁和简单 - 语法简单明快,易于学习和使用 特点 高效 编译速度快,执行效率高 并发支持 原生支持并发,利用goroutine实现高效的并发…...

前后端小项目链接

1.vue的创建 vue的项目创建 1.1 vue create vue_name 1.2 Babel Router(路由) CSS Pre-processors 路由可通过&#xff1a;npm i vue-router3.5.2 -S 下载 1.3less 1.4 In dedicated config files 1.5 启动命令&#xff1a;npm run serve 端口号在vue.config。js中配置 devS…...

编辑器功能:用一个快捷键来【锁定】或【解开】Inspector面板

一、需求 我有一个脚本&#xff0c;上面暴露了许多参数&#xff0c;我要在场景中拖物体给它进行配置。 如果不锁定Inspector面板的话&#xff0c;每次点击物体后&#xff0c;Inspector的内容就是刚点击的物体的内容&#xff0c;而不是挂载脚本的参数面板。 二、 解决 &…...

Vue 网络处理 - axios 异步请求的使用,请求响应拦截器(最佳实践)

目录 一、axiox 1.1、axios 简介 1.2、axios 基本使用 1.2.1、下载核心 js 文件. 1.2.2、发送 GET 异步请求 1.2.3、发送 POST 异步请求 1.2.4、发送 GET、POST 请求最佳实践 1.3、请求响应拦截器 1.3.1、拦截器解释 1.3.2、请求拦截器的使用 1.3.3、响应拦截器的使…...

关于W5500网卡使用过程的部分问题记录

某个项目中用到了W5500这种自带网络协议栈的网卡芯片&#xff0c;由于该项目开发时间很紧&#xff0c;就临时网上买了一些模块拼凑到了一套系统&#xff0c;经过验证果真这种拼积木的方法只能用在学生实验开发中&#xff0c;真不能拿来做工程应用&#xff0c;硬件太不稳定很容易…...

论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(二)

HoST框架核心实现方法详解 - 论文深度解读(第二部分) 《Learning Humanoid Standing-up Control across Diverse Postures》 系列文章: 论文深度解读 + 算法与代码分析(二) 作者机构: 上海AI Lab, 上海交通大学, 香港大学, 浙江大学, 香港中文大学 论文主题: 人形机器人…...

vscode(仍待补充)

写于2025 6.9 主包将加入vscode这个更权威的圈子 vscode的基本使用 侧边栏 vscode还能连接ssh&#xff1f; debug时使用的launch文件 1.task.json {"tasks": [{"type": "cppbuild","label": "C/C: gcc.exe 生成活动文件"…...

(二)TensorRT-LLM | 模型导出(v0.20.0rc3)

0. 概述 上一节 对安装和使用有个基本介绍。根据这个 issue 的描述&#xff0c;后续 TensorRT-LLM 团队可能更专注于更新和维护 pytorch backend。但 tensorrt backend 作为先前一直开发的工作&#xff0c;其中包含了大量可以学习的地方。本文主要看看它导出模型的部分&#x…...

什么是EULA和DPA

文章目录 EULA&#xff08;End User License Agreement&#xff09;DPA&#xff08;Data Protection Agreement&#xff09;一、定义与背景二、核心内容三、法律效力与责任四、实际应用与意义 EULA&#xff08;End User License Agreement&#xff09; 定义&#xff1a; EULA即…...

鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个生活电费的缴纳和查询小程序

一、项目初始化与配置 1. 创建项目 ohpm init harmony/utility-payment-app 2. 配置权限 // module.json5 {"requestPermissions": [{"name": "ohos.permission.INTERNET"},{"name": "ohos.permission.GET_NETWORK_INFO"…...

select、poll、epoll 与 Reactor 模式

在高并发网络编程领域&#xff0c;高效处理大量连接和 I/O 事件是系统性能的关键。select、poll、epoll 作为 I/O 多路复用技术的代表&#xff0c;以及基于它们实现的 Reactor 模式&#xff0c;为开发者提供了强大的工具。本文将深入探讨这些技术的底层原理、优缺点。​ 一、I…...

均衡后的SNRSINR

本文主要摘自参考文献中的前两篇&#xff0c;相关文献中经常会出现MIMO检测后的SINR不过一直没有找到相关数学推到过程&#xff0c;其中文献[1]中给出了相关原理在此仅做记录。 1. 系统模型 复信道模型 n t n_t nt​ 根发送天线&#xff0c; n r n_r nr​ 根接收天线的 MIMO 系…...

第7篇:中间件全链路监控与 SQL 性能分析实践

7.1 章节导读 在构建数据库中间件的过程中&#xff0c;可观测性 和 性能分析 是保障系统稳定性与可维护性的核心能力。 特别是在复杂分布式场景中&#xff0c;必须做到&#xff1a; &#x1f50d; 追踪每一条 SQL 的生命周期&#xff08;从入口到数据库执行&#xff09;&#…...

【Linux系统】Linux环境变量:系统配置的隐形指挥官

。# Linux系列 文章目录 前言一、环境变量的概念二、常见的环境变量三、环境变量特点及其相关指令3.1 环境变量的全局性3.2、环境变量的生命周期 四、环境变量的组织方式五、C语言对环境变量的操作5.1 设置环境变量&#xff1a;setenv5.2 删除环境变量:unsetenv5.3 遍历所有环境…...

离线语音识别方案分析

随着人工智能技术的不断发展&#xff0c;语音识别技术也得到了广泛的应用&#xff0c;从智能家居到车载系统&#xff0c;语音识别正在改变我们与设备的交互方式。尤其是离线语音识别&#xff0c;由于其在没有网络连接的情况下仍然能提供稳定、准确的语音处理能力&#xff0c;广…...