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

数据结构例题代码及其讲解-栈与队列

栈与队列

栈Stack

后进先出

​ 栈的结构体定义及基本操作。

#define MaxSize 50
typedef struct {int data[MaxSize];//栈中存放数据类型为整型int top;//栈顶指针
}Stack;

初始化

​ 这里初始化时是将栈顶指针指向-1,有些则是指向0,因此后续入栈出栈的代码略微有点区别

void InitStack(Stack& S) {//初始化栈S.top = -1;
}

判断栈是否为空

int IsEmpty(Stack S) {//判断栈是否为空if (S.top == -1)return 1;elsereturn 0;
}

压栈操作

  1. 由于初始时栈顶指针指向-1,因此需要先变化栈顶指针,然后入栈操作;
  2. 且当MaxSize为50时候,数据域在data[0]~data[49],因此这里是S.top == MaxSize - 1表示栈满;
  3. 第4-5行可以合并为S.data[++S.top]=x。
int Push(Stack& S, int x) {//压栈操作if (S.top == MaxSize - 1)//若栈满则无法压栈return 0;S.top++;S.data[S.top] = x;return 1;
}

出栈操作

  1. 这里将出栈的元素用x接收,出栈时先接收,然后栈顶指针自减
  2. 第4-5行可以合并为x=S.data[++S.top]
int Pop(Stack& S, int& x) {//出栈操作if (S.top == -1)//若栈空则无法出栈return 0;x = S.data[S.top];S.top--;return 1;
}

读取栈顶元素

​ 这里将出栈的元素用x接收

int GetTop(Stack S, int& x) {//读取栈顶元素if (S.top == -1)//若栈空则无栈顶元素return 0;x = S.data[S.top];return 1;
}

​ 当然以上的是顺序栈,还有链栈,和单链表类似,带头结点处为栈头,另外一边为栈底,入栈出栈都在头结点处进行,方便操作。

01 有一个带头结点的单链表 L,结点结构由 data 和 next 两个域构成,其中data 域为字符型。试设计算法判断该链表的全部 n 个字符是否中心对称。例如xyx、xyyx 都是中心对称。
  1. 判断这类是否中心对称,一般都是用到栈;
  2. 本题中将其分为前后两部分,把前半部分依次入栈,到后半部分时,与出栈元素进行比较,比较完后栈顶指针移动。遍历指针移动;
  3. 易错for循环入栈结束后,i所在的位置在栈顶元素的后一个位置,需要i–将其返回到栈顶位置
  4. 结点个数为偶数时,正常处理,个数为奇数时,最中间元素不将其压栈处理,让遍历指针再走一步,绕过中间元素;
int central_symmetry(LinkList L, int n) {char S[n / 2];//定义字符型数组来作为一个栈int i;//定义栈顶指针LNode* p = L->next;//定义遍历指针//对称轴左边字符依次入栈for (i = 0; i < n / 2; i++) {S[i] = p->data;p = p->next;}i--;//变量 i 返回栈顶位置if (n % 2 == 1) {//若字符数为奇数则 p 向后遍历一步,因为最中间字符不需考虑p = p->next;}while (p != NULL) {//对称轴右边字符依次与栈顶元素比对if (p->data == S[i]) {//与栈顶元素相等则 p 继续遍历与下一出栈元素比较i--;//出栈p = p->next;//继续遍历}else//若不等,则说明 n 个字符不对称,直接返回 0return 0;//非中心对称}return 1;//若正常跳出循环,则证明 n 个字符对称,返回 1
}
02 假设一个算术表达式中包含小括号和中括号 2 种类型的括号,编写一个算法来判别表达式中的括号是否配对,假设算术表达式存放于字符数组中,以字符‘\0’作为算术表达式的结束符。
  1. 本题中对于数字和运算符不需要进行操作
  2. switch语句从上往下依次执行,因此需要break跳出;
  3. 遇到右括号时候,首先得判断栈是否为空,为空则说明不匹配了;
  4. 若数组遍历完成后栈为空,则证明所有左括号全部配对成功
int BracketsCheck(char a[]) {Stack S;InitStack(S);char x;for (int i = 0; a[i] != '\0'; i++) {switch (a[i]) {case'('://若数组元素为左括号,则压栈继续遍历push(S, a[i]);break;case'[':push(S, a[i]);break;case')'://若元素为右括号,则需考虑是否有左括号与之配对if (IsEmpty(S) {return 0;//若栈空,则说明无左括号与之配对}else {Pop(S, x);if (x != '(') {//若栈不为空,则判断栈顶元素与当前括号是否配对return 0;}//配对上了break;}case']':if (IsEmpty(S)) {return 0;}else {Pop(S, x);if (x != '[') {return 0;}break;}default://若数组元素不是括号则直接继续遍历break;}}if (IsEmpty(S)) {//若数组遍历完成后栈为空,则证明所有左括号全部配对成功return 1;}else {//若栈不为空,则证明有左括号未配对retun 0;}
}
03 两个栈 S1、S2 都采用顺序栈方式,并共享一个存储区[0,…,MaxSize-1],为了尽量利用空间,减少溢出的可能,可采用栈顶相向、迎面增长的存储方式。试设计写出此栈的定义和 S1、S2 有关入栈和出栈的操作算法。

​ 两个栈,需要两个栈顶指针,这里定义了top数组,一个top[0],一个top[1]

#define MaxSize 50
typedef struct{int data[MaxSize];int top[2];//一个top[0],一个top[1]指针
}DStack;

初始化

void InitDStack(DStack& S) {S.top[0] = -1;//初始化 S1 栈顶指针S.top[1] = MaxSize;//初始化 S2 栈顶指针
}

入栈

  1. 因为一个存储空间有两个栈,因此需要告诉是对哪个栈进行入栈操作,i就是用来区分哪个栈;
  2. 这里S[1]表示下面的栈,S[2]表示上面的栈
int push(int i, int x) {if (i < 0 || i>1) {return 0;//若 i 的输入不合法,则无法入栈}if (S.top[1] - S.top[0] == 1) {//若存储空间已满,则无法进行入栈操作return 0;}switch (i) {case 0:// S1 栈顶指针上移后入栈S.top[0]++;S.data[S.top[0]] = x;//S.data[++S.top[0]] = x;break;case 1:// S2 栈顶指针下移后入栈S.top[1]--;S.data[S.top[1]] = x;//S.data[--S.top[1]] = x;break;}return 1;
}

出栈

int pop(int i, int& x) {if (i < 0 || i>1) {return 0;}if (S.top[0] == -1 || S.top[1] == MaxSize) {//空栈return 0;}switch (i) {case 0:x = S.data[S.top[0]];S.top[0]--;//下面的栈往下移//x = S.data[S.top[0]--];break;case 1:x = S.data[S.top[1]];S.top[1]++;//上面的栈顶指针往上移//x = S.data[S.top[1]++];break;}return 1;
}

队列Queue

先进先出

​ 队列的结构体定义及其基本操作。

#define MaxSize 50
typedef struct {int data[MaxSize];//队列中存放数据类型为整型int front, rear;//队首指针和队尾指针
}Queue;
void InitQueue(Queue& Q) {//初始化队列Q.front = 0;Q.rear = 0;
}
int IsEmpty(Queue Q) {//判断队列是否为空if (Q.front == Q.rear)//若队首指针和队尾指针指向同一位置,则队列为空return 1;elsereturn 0;
}

队列的入队和出队

这里队尾指针指向元素的后一个位置,详见入队出队操作

入队争对的是队尾指针,需要判断队满Q.rear == MaxSize

//顺序队列的入队和出队:
//这里队尾指针指向元素的后一个位置
int EnQueue(Queue& Q, int x) {//入队操作if (Q.rear == MaxSize)//若队满,则无法入队return 0;Q.data[Q.rear] = x;//变量 x 入队Q.rear++;//队尾指针后移return 1;//入队成功
}

出队争对的是队头指针,需要判断队空Q.front == Q.rear

int DeQueue(Queue& Q, int& x) {//出队操作if (Q.front == Q.rear)//若队空,则无法出队return 0;x = Q.data[Q.front];//变量 x 接收出队元素Q.front++;//队首指针后移return 1;//出队成功
}

循环队列

​ 由于之前Q.front == Q.rear判断队空,若循环,则既有判空,又有存满的意思,因此可以牺牲一个空间,使得Q.front == Q.rear只能用来判空。

判空Q.front == Q.rear

判满(Q.rear + 1) % MaxSize == Q.front(rear向后移一个是front的话,说明满了)

​ 队尾指针和队首指针往后移动的时候都需要+1取余

//循环队列的入队和出队:(牺牲一个存储空间)
int EnQueue(Queue& Q, int x) {//入队操作if ((Q.rear + 1) % MaxSize == Q.front)//若队满,则无法入队return 0;Q.data[Q.rear] = x;//变量 x 入队Q.rear = (Q.rear + 1) % MaxSize;//队尾指针后移return 1;//入队成功
}
int DeQueue(Queue& Q, int& x) {//出队操作if (Q.front == Q.rear)//若队空,则无法出队return 0;x = Q.data[Q.front];//变量 x 接收出队元素Q.front = (Q.front + 1) % MaxSize;//队首指针后移return 1;//出队成功
}
04 若希望循环队列中的元素都能得到利用,则需设置一个标志域 tag,并以tag的值为0或1来区分队头指针front和队尾指针rear相同时的队列状态是“空”还是“满”。试编写与此结构相应的入队和出队算法。
  1. 循环队列中,Q.front == Q.rear在原先是能判断队空和队满,因此上面牺牲一个空间进行特别处理;
  2. 本题通过设置标志域来判断是队空还是队满;
  3. 这里需要判断队满的只有入队的时候,因此每次入队后将tag变成1;需要判断队空的只有出队的时候,因此每次出队后将tag变成0;由于队空队满判断都需要进行Q.front == Q.rear的判断,因此因此当队首队尾指针不在同一个地方时候,不会进入这个判断,初始时应该将tag置为0。
  4. Q.front == Q.rear && Q.tag == 1和Q.front == Q.rear && Q.tag == 0的条件下挺强的,都是需要两个条件同时满足
typedef struct {int data[MaxSize];int front, rear;int tag;
}Queue;
void InitQueue(Queue& Q) {//初始化队列Q.front = 0;Q.rear = 0;Q.tag = 0;
}
int EnQueue(Queue& Q, int x) {if (Q.front == Q.rear && Q.tag == 1) {//若队满,则无法进行入队操作return 0;}Q.data[Q.rear] = x;Q.rear = (Q.rear + 1) % MaxSize;//队尾指针后移Q.tag = 1;//入队后可能会出现队满的情况,所以将 tag 标志域置为 1return 1;
}
int DeQueue(Queue& Q, int& x) {if (Q.front == Q.rear && Q.tag == 0) {return 0;//队空}x = Q.data[Q.front];Q.front = (Q.front + 1) % MaxSize;Q.tag == 0;//出队后可能会出现队空的情况,所以将 tag 标志域置为 0return 1;
}
05 Q 是一个队列,S 是一个空栈,实现将队列中的元素逆置的算法。
  1. 队列先进先出,栈后进先出,要将队列中元素逆置,因此可以依次将队列的元素出队入栈,当队列为空时,然后出栈入队就实现了逆置。
//Q 是一个队列,S 是一个空栈,实现将队列中的元素逆置的算法。
void Reverse(Queue& Q, Stack& S) {int x;while (!IsEmpty(Q)) {//出队列入栈DeQueue(Q, x);Push(S, x);}while (!IsEmpty(S)) {//出栈入队列Pop(S, x);EnQueue(Q, x);}
}

相关文章:

数据结构例题代码及其讲解-栈与队列

栈与队列 栈Stack 后进先出 ​ 栈的结构体定义及基本操作。 #define MaxSize 50 typedef struct {int data[MaxSize];//栈中存放数据类型为整型int top;//栈顶指针 }Stack;初始化 ​ 这里初始化时是将栈顶指针指向-1&#xff0c;有些则是指向0&#xff0c;因此后续入栈出栈…...

【Spark】Pyspark RDD

1. RDD算子1.1 文件 <> rdd对象1.2 map、foreach、mapPartitions、foreach Partitions1.3 flatMap 先map再解除嵌套1.4 reduceByKey、reduce、fold 分组聚合1.5 mapValue 二元组value进行map操作1.6 groupBy、groupByKey1.7 filter、distinct 过滤筛选1.8 union 合并1.9 …...

数学建模:Logistic回归预测

&#x1f506; 文章首发于我的个人博客&#xff1a;欢迎大佬们来逛逛 数学建模&#xff1a;Logistic回归预测 Logistic回归预测 logistic方程的定义&#xff1a; x t 1 c a e b t x_{t}\frac{1}{cae^{bt}}\quad xt​caebt1​ d x d t − a b e b t ( c a e b t ) 2 >…...

一个面向MCU的小型前后台系统

JxOS简介 JxOS面向MCU的小型前后台系统&#xff0c;提供消息、事件等服务&#xff0c;以及软件定时器&#xff0c;低功耗管理&#xff0c;按键&#xff0c;led等常用功能模块。 gitee仓库地址为&#xff08;复制到浏览器打开&#xff09;&#xff1a; https://gitee.com/jer…...

软件外包开发人员分类

在软件开发中&#xff0c;通常会分为前端开发和后端开发&#xff0c;下面和大家分享软件开发中的前端开发和后端开发分类和各自的职责&#xff0c;希望对大家有所帮助。北京木奇移动技术有限公司&#xff0c;专业的软件外包开发公司&#xff0c;欢迎交流合作。 1. 前端开发&…...

HTML 元素被定义为块级元素或内联元素

大多数 HTML 元素被定义为块级元素或内联元素。 10. 块级元素 块级元素在浏览器显示时&#xff0c;通常会以新行来开始&#xff08;和结束&#xff09;。 我们已经学习过的块级元素有: <h1>, <p>, <ul>, <table> 等。 值得注意的是: <p> 标签…...

单调递增的数字【贪心算法】

单调递增的数字 当且仅当每个相邻位数上的数字 x 和 y 满足 x < y 时&#xff0c;我们称这个整数是单调递增的。 给定一个整数 n &#xff0c;返回 小于或等于 n 的最大数字&#xff0c;且数字呈 单调递增 。 public class Solution {public int monotoneIncreasingDigits…...

gnuradio-hackrf_info.exe -FM频率使用

97910000...

JVM学习(三)--生产环境的线程问题诊断

1.如何定位哪个进程对cpu占用过高 使用top命令 2.如何定位到某个进程的具体某个线程 使用ps H -eo pid,tid,%cpu | grep 进程id (可以具体定位到某个进程的某个线程的cpu占用情况) 3.如何查看有问题线程的具体信息&#xff0c;定位到代码的行数 使用jstack 进程id 可以找…...

PHP数组处理$arr1转换为$arr2

请编写一段程序将$arr1转换为$arr2 $arr1 array( 0>array (fid>1,tid>1,name>Name1), 1>array (fid>2,tid>2,name>Name2), 2>array (fid>3,tid>5,name>Name3), 3>array (fid>4,tid>7,name>Name4), 4>array (fid>5,tid…...

ATF(TF-A)安全通告 TFV-10 (CVE-2022-47630)

安全之安全(security)博客目录导读 ATF(TF-A)安全通告汇总 目录 一、ATF(TF-A)安全通告 TFV-10 (CVE-2022-47630) 二、CVE-2022-47630 2.1 Bug 1:证书校验不足 2.2 Bug 2:auth_nvctr()中缺少边界检查...

详解 SpringMVC 中获取请求参数

文章目录 1、通过ServletAPI获取2、通过控制器方法的形参获取请求参数3、[RequestParam ](/RequestParam )4、[RequestHeader ](/RequestHeader )5、[CookieValue ](/CookieValue )6、通过POJO获取请求参数7、解决获取请求参数的乱码问题总结 在Spring MVC中&#xff0c;获取请…...

Message: ‘chromedriver‘ executable may have wrong permissions.

今天运行项目遇到如下代码 driverwebdriver.Chrome(chrome_driver, chrome_optionsoptions)上述代码运行报错如下&#xff1a; Message: chromedriver executable may have wrong permissions. Please see https://sites.google.com/a/chromium.org/chromedriver/home出错的原…...

每日一题 1372二叉树中的最长交错路径

题目 给你一棵以 root 为根的二叉树&#xff0c;二叉树中的交错路径定义如下&#xff1a; 选择二叉树中 任意 节点和一个方向&#xff08;左或者右&#xff09;。如果前进方向为右&#xff0c;那么移动到当前节点的的右子节点&#xff0c;否则移动到它的左子节点。改变前进方…...

【力扣每日一题】2023.9.2 最多可以摧毁的敌人城堡数量

目录 题目&#xff1a; 示例&#xff1a; 分析&#xff1a; 代码&#xff1a; 题目&#xff1a; 示例&#xff1a; 分析&#xff1a; 这道题难在阅读理解&#xff0c;题目看得我匪夷所思&#xff0c;错了好多个测试用例才明白题目说的是什么。 我简单翻译一下就是寻找1和…...

kotlin实现java的单例模式

代码 package com.flannery.interviewdemo.singleinstance//https://blog.csdn.net/Jason_Lee155/article/details/128796742 Java实现 //public class SingletonDemo { // private static SingletonDemo instancenew SingletonDemo(); // private SingletonDemo() // …...

使用 KeyValueDiffers 检测Angular 对象的变化

使用 KeyValueDiffers 检测Angular 对象的变化 ngDoCheck钩子 ngDoCheck 是 Angular 生命周期钩子之一。它允许组件在 Angular 检测到变化时执行自定义的变化检测逻辑。 当任何组件或指令的输入属性发生变化、在组件内部发生了变更检测周期或者当主动触发变更检测策略&#…...

Macos 10.13.2安装eclipse

eclipse for php 安装2021-12最后版本4.22 2021-12 R | Eclipse Packages jdk17 x64 dmg安装包,要安装jdk这个才能运行 Java Downloads | Oracle...

Android逆向学习(一)vscode进行android逆向修改并重新打包

Android逆向学习&#xff08;一&#xff09;vscode进行android逆向修改并重新打包 写在前面 其实我不知道这个文章能不能写下去&#xff0c;其实我已经开了很多坑但是都没填上&#xff0c;现在专利也发出去了&#xff0c;就开始填坑了&#xff0c;本坑的主要内容是关于androi…...

【深入浅出设计模式--状态模式】

深入浅出设计模式--状态模式 一、背景二、问题三、解决方案四、 适用场景总结五、后记 一、背景 状态模式是一种行为设计模式&#xff0c;让你能在一个对象的内部状态变化时改变其行为&#xff0c;使其看上去就像改变了自身所属的类一样。其与有限状态机的概念紧密相关&#x…...

AI-调查研究-01-正念冥想有用吗?对健康的影响及科学指南

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; &#x1f680; AI篇持续更新中&#xff01;&#xff08;长期更新&#xff09; 目前2025年06月05日更新到&#xff1a; AI炼丹日志-28 - Aud…...

Unity3D中Gfx.WaitForPresent优化方案

前言 在Unity中&#xff0c;Gfx.WaitForPresent占用CPU过高通常表示主线程在等待GPU完成渲染&#xff08;即CPU被阻塞&#xff09;&#xff0c;这表明存在GPU瓶颈或垂直同步/帧率设置问题。以下是系统的优化方案&#xff1a; 对惹&#xff0c;这里有一个游戏开发交流小组&…...

黑马Mybatis

Mybatis 表现层&#xff1a;页面展示 业务层&#xff1a;逻辑处理 持久层&#xff1a;持久数据化保存 在这里插入图片描述 Mybatis快速入门 ![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/6501c2109c4442118ceb6014725e48e4.png //logback.xml <?xml ver…...

多模态商品数据接口:融合图像、语音与文字的下一代商品详情体验

一、多模态商品数据接口的技术架构 &#xff08;一&#xff09;多模态数据融合引擎 跨模态语义对齐 通过Transformer架构实现图像、语音、文字的语义关联。例如&#xff0c;当用户上传一张“蓝色连衣裙”的图片时&#xff0c;接口可自动提取图像中的颜色&#xff08;RGB值&…...

生成 Git SSH 证书

&#x1f511; 1. ​​生成 SSH 密钥对​​ 在终端&#xff08;Windows 使用 Git Bash&#xff0c;Mac/Linux 使用 Terminal&#xff09;执行命令&#xff1a; ssh-keygen -t rsa -b 4096 -C "your_emailexample.com" ​​参数说明​​&#xff1a; -t rsa&#x…...

论文浅尝 | 基于判别指令微调生成式大语言模型的知识图谱补全方法(ISWC2024)

笔记整理&#xff1a;刘治强&#xff0c;浙江大学硕士生&#xff0c;研究方向为知识图谱表示学习&#xff0c;大语言模型 论文链接&#xff1a;http://arxiv.org/abs/2407.16127 发表会议&#xff1a;ISWC 2024 1. 动机 传统的知识图谱补全&#xff08;KGC&#xff09;模型通过…...

Python 包管理器 uv 介绍

Python 包管理器 uv 全面介绍 uv 是由 Astral&#xff08;热门工具 Ruff 的开发者&#xff09;推出的下一代高性能 Python 包管理器和构建工具&#xff0c;用 Rust 编写。它旨在解决传统工具&#xff08;如 pip、virtualenv、pip-tools&#xff09;的性能瓶颈&#xff0c;同时…...

让回归模型不再被异常值“带跑偏“,MSE和Cauchy损失函数在噪声数据环境下的实战对比

在机器学习的回归分析中&#xff0c;损失函数的选择对模型性能具有决定性影响。均方误差&#xff08;MSE&#xff09;作为经典的损失函数&#xff0c;在处理干净数据时表现优异&#xff0c;但在面对包含异常值的噪声数据时&#xff0c;其对大误差的二次惩罚机制往往导致模型参数…...

AI+无人机如何守护濒危物种?YOLOv8实现95%精准识别

【导读】 野生动物监测在理解和保护生态系统中发挥着至关重要的作用。然而&#xff0c;传统的野生动物观察方法往往耗时耗力、成本高昂且范围有限。无人机的出现为野生动物监测提供了有前景的替代方案&#xff0c;能够实现大范围覆盖并远程采集数据。尽管具备这些优势&#xf…...

C++课设:简易日历程序(支持传统节假日 + 二十四节气 + 个人纪念日管理)

名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 专栏介绍:《编程项目实战》 目录 一、为什么要开发一个日历程序?1. 深入理解时间算法2. 练习面向对象设计3. 学习数据结构应用二、核心算法深度解析…...