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

栈和队列题目练习

本节小编选了两道题来加深对栈和队列的认识理解!

有效的括号

方法1:直接用栈的结构(动态数组)

本题可以用栈这个结构来解答,将'(','{','['  左括号压入栈中,然后取出栈顶元素与右括号')','}',']'匹配。不匹配的话,返回false,我们同时也要考虑空集的情况,即栈中元素为空,则返回false。

因为本题使用c语言写的,所以需要手撕栈的结构,可以运用上篇博客所写的栈的代码。

typedef  char  datatype;
typedef struct stack {datatype* a;int top;//栈顶int capacity;
}ST;
void STInit(ST* pst){assert(pst);pst->a = NULL;//top指向栈顶数据的下一个位置,可以理解为下标pst->top = 0;pst->capacity = 0;
}
void STDestory(ST* pst) {assert(pst);free(pst->a);pst->a = NULL;pst->top = pst->capacity = 0;
}
//容量检查
void Checkcapacity(ST* pst) {assert(pst);if (pst->top == pst->capacity) {int newcapacity = pst->capacity==0?4:pst->capacity * 2;datatype* temp = (datatype*)realloc(pst->a, newcapacity * sizeof(datatype));if (temp == NULL) {perror("relloc fail");return;}pst->a = temp;pst->capacity = newcapacity;}
}
//入栈和出栈
void STPush(ST* pst, datatype x) {assert(pst);Checkcapacity(pst);pst->a[pst->top] = x;pst->top++;
}
void STPop(ST* pst) {assert(pst);assert(pst->top>0);pst->top--;
}
//获取栈顶数据
datatype STTop(ST* pst) {assert(pst);assert(pst->top > 0);return pst->a[pst->top-1];
}
//判空
bool STEmpty(ST* pst) {assert(pst);return pst->top == 0;//表达式判断
}
//栈的数据个数
int STSize(ST* pst) {assert(pst);return pst->top;
}
bool isValid(char* s) {ST st;STInit(&st);while(*s){//左括号入栈if(*s=='('||*s=='{'||*s=='['){STPush(&st,*s);}else{//空集的情况,入栈结束后检查是否为空,if(STEmpty(&st)){STDestory(&st);return false;}char top=STTop(&st);STPop(&st);//通过括号不匹配的情况判断if((top=='('&& *s!=')') ||(top=='['&& *s!=']')||(top=='{'&& *s!='}')){STDestory(&st);return false;//STPop(&st);}}s++;}
//看最后是否栈为空,探讨左右括号数量不匹配的情况。bool ret=(STEmpty(&st));STDestory(&st);return ret;
}

方法2:通过数组模拟栈来实现

使用一个字符数组作为栈,通过使用top标记栈顶的位置来实现栈的操作。在遍历字符串的过程中,遇到左括号就将其压入栈中,遇到右括号就与栈顶元素进行匹配。如果匹配成功,则将栈顶元素出栈,否则返回false。最后,如果栈为空,则说明所有的括号都匹配成功,返回true;否则,返回false。

bool isValid(char* s) {char stack[10000];int top = -1;int len = strlen(s);for (int i = 0; i < len; i++) {if (s[i] == '(' || s[i] == '{' || s[i] == '[') {stack[++top] = s[i];} else {if (top == -1) {return false;}if ((s[i] == ')' && stack[top] == '(') || (s[i] == '}' && stack[top] == '{') || (s[i] == ']' && stack[top] == '[')) {top--;} else {return false;}}}return top == -1;
}

设计循环队列

方法1:使用动态数组

通过画图发现,当head==tail时,既是队列为空的条件,也是队列满的条件,所以我们可以通过增加一个空间来辅助判满,当tail+1=head时。还有另外一个方法,通过定义size变量,当size大小等于k时,也是队列满的时候。

在后续解决回绕的问题时,我们多次采用取模的方法,因为一个数除以比他大的数,取模后大小不变,当相等时,模为0,刚好回到起点处,完美的解决了回绕问题。

//循环队列先进先出
typedef struct {int *arr;int head;int tail;//指向尾下一个int k;
} MyCircularQueue;//创建循环队列
MyCircularQueue* myCircularQueueCreate(int k) {MyCircularQueue*obj=(MyCircularQueue*)malloc(sizeof(MyCircularQueue));//多开辟一个空间obj->arr=(int*)malloc(sizeof(int)*(k+1));obj->head=0;obj->tail=0;obj->k=k;return obj;
}
bool myCircularQueueIsEmpty(MyCircularQueue* obj) {//头尾相等时队列为空return (obj->head)==obj->tail;
}bool myCircularQueueIsFull(MyCircularQueue* obj) {//当tail+1=head时,为满,通过取模解决回绕问题return((obj->tail+1)%(obj->k+1))==obj->head;
}
bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {//队列满的时候,返回falseif(myCircularQueueIsFull(obj))return false;//插入一个数据,tail后移obj->arr[obj->tail]=value;obj->tail++;//解决回绕,重头再来obj->tail %=(obj->k+1);return true;
}bool myCircularQueueDeQueue(MyCircularQueue* obj) {if(myCircularQueueIsEmpty(obj))return false;//head前进,删除数据obj->head++;//解决回绕问题obj->head %=(obj->k+1);return true;
}int myCircularQueueFront(MyCircularQueue* obj) {if(myCircularQueueIsEmpty(obj))return -1;return obj->arr[obj->head];
}int myCircularQueueRear(MyCircularQueue* obj) {if(myCircularQueueIsEmpty(obj))return -1;else//分类讨论取尾元素return obj->tail==0?obj->arr[obj->k]:obj->arr[obj->tail-1];//return obj->arr[(obj->tail-1+obj->k+1)%(obj->k+1)];//取模的方法很巧妙
}void myCircularQueueFree(MyCircularQueue* obj) {free(obj->arr);free(obj);
}

方法2:双向链表实现

使用双向链表实现,其中每个节点(Node)包含一个整数值(val),以及指向前一个节点和后一个节点的指针(prev和next)。循环队列(MyCircularQueue)包含一个指向队列头部和尾部的指针(head和tail),以及队列的大小(size)和容量(capacity)。

//节点建立
typedef struct Node {int val;struct Node* prev;struct Node* next;
} Node;
//双向链表实现队列
typedef struct {Node* head;Node* tail;int size;int capacity;
} MyCircularQueue;MyCircularQueue* myCircularQueueCreate(int k) {MyCircularQueue* obj = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));obj->head = NULL;obj->tail = NULL;obj->size = 0;obj->capacity = k;return obj;
}
//判空
bool myCircularQueueIsEmpty(MyCircularQueue* obj) {return obj->size == 0;
}
//判满
bool myCircularQueueIsFull(MyCircularQueue* obj) {return obj->size == obj->capacity;
}
//插入数据
bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {if (myCircularQueueIsFull(obj)) {return false;}Node* newNode = (Node*)malloc(sizeof(Node));newNode->val = value;newNode->prev = NULL;newNode->next = NULL;//队列为空时if (myCircularQueueIsEmpty(obj)) {obj->head = newNode;obj->tail = newNode;newNode->next = newNode;newNode->prev = newNode;} // 不为空时else {newNode->prev = obj->tail;newNode->next = obj->head;obj->tail->next = newNode;obj->head->prev = newNode;obj->tail = newNode;}obj->size++;return true;
}
//数据的删除
bool myCircularQueueDeQueue(MyCircularQueue* obj) {if (myCircularQueueIsEmpty(obj)) {return false;}Node* del = obj->head;if (obj->size == 1) {obj->head = NULL;obj->tail = NULL;} else {obj->head = obj->head->next;obj->head->prev = obj->tail;obj->tail->next = obj->head;}obj->size--;free(del);return true;
}
//头数据
int myCircularQueueFront(MyCircularQueue* obj) {if (myCircularQueueIsEmpty(obj)) {return -1;}return obj->head->val;
}
//尾数据
int myCircularQueueRear(MyCircularQueue* obj) {if (myCircularQueueIsEmpty(obj)) {return -1;}return obj->tail->val;
}
//队列销毁
void myCircularQueueFree(MyCircularQueue* obj) {Node* curr = obj->head;while (curr != obj->tail) {Node* next = curr->next;free(curr);curr = next;}obj->tail=NULL;free(obj);
}

补充方法3:

使用链表(单链表)-投机取巧哈哈哈

不过这种方法没有关系到循环队列,也能通过该题目。

可以用链表实现队列,用链表实现队列则较为简单,因为链表可以在 O(1)时间复杂度完成插入与删除。入队列时,将新的元素插入到链表的尾部;出队列时,将链表的头节点返回,并将头节点指向下一个节点。

循环队列的属性如下:

head:链表的头节点,队列的头节点。
tail:链表的尾节点,队列的尾节点。
capacity:队列的容量,即队列可以存储的最大元素数量。
size:队列当前的元素的数量。

相比较与数组,我们使用了size的方法来判断队列为空为满的状态,

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
//中间节点创建和函数主体
typedef struct node {int val;struct node* next;
} node;
//循环队列先进先出
typedef struct {node* head;node* tail;int size;int capacity;
} MyCircularQueue;//创建循环队列
MyCircularQueue* myCircularQueueCreate(int k) {MyCircularQueue* obj = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));obj->head=obj->tail=NULL;obj->size=0;obj->capacity=k;return obj;
}
bool myCircularQueueIsEmpty(MyCircularQueue* obj) {if(obj->size==0)return true;elsereturn false;
//return obj->size==0;
}bool myCircularQueueIsFull(MyCircularQueue* obj) {return obj->size==obj->capacity;
}
bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {if(myCircularQueueIsFull(obj))return false;node* newnode=(struct node*)malloc(sizeof(node));newnode->val=value;newnode->next=NULL;if(obj->size==0){obj->head=newnode;obj->tail=newnode;}else{obj->tail->next=newnode;obj->tail=newnode;}obj->size++;return true;
}bool myCircularQueueDeQueue(MyCircularQueue* obj) {if(myCircularQueueIsEmpty(obj))return false;node*del=obj->head;obj->head=obj->head->next;free(del);obj->size--;return true;}int myCircularQueueFront(MyCircularQueue* obj) {if(myCircularQueueIsEmpty(obj))return -1;return obj->head->val;
}int myCircularQueueRear(MyCircularQueue* obj) {if(myCircularQueueIsEmpty(obj))return -1;return obj->tail->val;
}void myCircularQueueFree(MyCircularQueue* obj) {node* curr = obj->head;while (curr != NULL) {node* next = curr->next;free(curr);curr = next;}obj->size = obj->capacity = 0;obj->head = obj->tail = NULL;free(obj);
}//手动测试部分
int main() {MyCircularQueue* obj = myCircularQueueCreate(5);myCircularQueueEnQueue(obj, 1);myCircularQueueEnQueue(obj, 2);myCircularQueueEnQueue(obj, 3);myCircularQueueEnQueue(obj, 4);myCircularQueueEnQueue(obj, 5);printf("%d\n", myCircularQueueRear(obj));printf("%d\n", myCircularQueueFront(obj));myCircularQueueDeQueue(obj);printf("%d\n", myCircularQueueFront(obj));myCircularQueueFree(obj);return 0;
}

OK,本节内容到此结束,各位友友留下三连和评论吧,有更好的方法希望各位佬私信交流!!!

相关文章:

栈和队列题目练习

本节小编选了两道题来加深对栈和队列的认识理解&#xff01; 有效的括号 方法1&#xff1a;直接用栈的结构&#xff08;动态数组&#xff09; 本题可以用栈这个结构来解答&#xff0c;将(,{,[ 左括号压入栈中&#xff0c;然后取出栈顶元素与右括号),},]匹配。不匹配的话&…...

【排列问题】

问题&#xff1a; 已知某序列有n个元素&#xff0c;请编写程序打印出包含该序列所有元素的所有排列。 输入要求&#xff1a; 输入第1行为整数n&#xff0c;表示该序列元素的个数&#xff1b;第2行为n个整数&#xff0c;表示需要排列的序列元素。 输出要求&#xff1a;输出若…...

token 无感刷新

什么是 token 无感刷新&#xff1f;为什么需要 token 无感刷新&#xff1f;让我们想象一下有这么个场景&#xff1a;你登录一个系统成功后&#xff0c;玩了 10 分钟&#xff0c;发现登录失效了&#xff0c;又要你重新登录&#xff0c;然后又过 10 分钟&#xff0c;又失效了&…...

Netty SSL双向验证

Netty SSL双向验证 1. 环境说明2. 生成证书2.1. 创建根证书 密钥证书2.2. 生成请求证书密钥2.3. 生成csr请求证书2.4. ca证书对server.csr、client.csr签发生成x509证书2.5. 请求证书PKCS#8编码2.6. 输出文件 3. Java代码3.1. Server端3.2. Client端3.3. 证书存放 4. 运行效果4…...

4.nginx反向代理、负载均衡

nginx反向代理、负载均衡 一、反向代理1、语法2、注意事项3、后端服务器记录客户端真实IP3.1 在nginx反向代理时添加x-real-ip字段3.2 后端httpd修改combined日志格式3.3 后端是nginx的情况 二、负载均衡 upstream模块1、负载均衡作用2、调度算法3、配置应用 一、反向代理 隐藏…...

浅谈申请小程序地理位置权限的正确打开方式

小程序地理位置接口有什么功能&#xff1f; 这篇内容会教大家如何快速申请“获取当前的地理位置&#xff08;onLocationChange&#xff09;”接口&#xff0c;以便帮助大家顺利开通接口。以下内容是本人经历了多次的申请经历得出来的经验&#xff0c;来之不易&#xff0c;望大家…...

make modules 和 make modules_install

1. make modules 如&#xff1a;make ARCHarm64 CROSS_COMPILEaarch64-linux-gnu- modules 直接make&#xff0c;不加任何参数&#xff0c;就是make all&#xff0c;包含make modules。 make modules是单独编译模块&#xff0c;驱动被配置成M的都是modules&#xff0c;modul…...

docker 安装mysql,redis,rabbitmq

文章目录 docker 安装ngnix&#xff0c;mysql,redis,rabbitmq安装docker1.安装下载docker-ce源命令2.安装docker3.查看版本4.查看docker状态5.启动docker6.测试安装ngnix 安装mysql8.0.361.拉取mysql镜像2.安装mysql8 安装redis1.拉取redis7.0.11镜像2.安装redis3.进入容器内部…...

Windows配置java环境JDK

配置jdk环境非常简单&#xff0c;大概有以下几步&#xff1a; 下载jdk安装&#xff0c;然后双击进行安装配置环境变量(也不是一定非要配置环境变量&#xff0c;配置环境变量的好处就是&#xff0c;在任何位置&#xff0c;系统都可以找到安装路径&#xff0c;非常实用且方便) …...

英伟达驱动重装教程

离线安装NVIDIA驱动程序通常涉及下载驱动程序安装包并手动执行安装步骤。以下是详细步骤: 1. 下载NVIDIA驱动程序 首先,你需要在有网络连接的计算机上下载适合你系统的NVIDIA驱动程序安装包。可以从NVIDIA官方驱动下载页面下载。 选择你的GPU型号和操作系统,然后下载相应…...

【蓝桥杯嵌入式】 第六届国赛

目录 题目 配置 注意事项 代码 - 默写大师 EEPROM读写函数 LED驱动函数 ADC采集 上电初始化 LCD 按键 PWM互补输出 全部代码 hardware.c hardware.h control.c control.h main.c 题目 配置 注意事项 复制LCD的工程&#xff0c;先配置资源 --- 勾选完选项一…...

图片裁剪与上传处理方案 —— 基于阿里云 OSS 处理用户资料

目录 01: 通用组件&#xff1a;input 构建方案分析 02: 通用组件&#xff1a;input 构建方案 03: 构建用户资料基础样式 04: 用户基本资料修改方案 05: 处理不保存时的同步问题 06: 头像修改方案流程分析 07: 通用组件&#xff1a;Dialog 构建方案分析 08: 通用组件&…...

迷你主机Esxi 6.7挂载新硬盘

背景 硬件&#xff1a;零刻SER Pro 6 系统&#xff1a;vmware Exsi 6.7.0 Update 3 现有的硬盘槽位占满了&#xff0c;但空间不够用&#xff0c;想要通过USB外接移动硬盘来进行扩容。使用了一块250G的硬盘做测试。 步骤 TL;DR # 停止usbarbitrator服务 /etc/init.d/usbarbi…...

解决VSCode右键没有Open In Default Browser问题

在VSCode进行Web小程序测试时&#xff0c;我们在新建的HTML文件中输入 !会自动生成页面代码骨架&#xff0c;写入内容后&#xff0c;我们想要右键在浏览器中预览。发现右键没有“Open In Default Browser”选项。原因是没有安装插件。 下面是解决方案&#xff1a;首先在VSCode找…...

httpsok-v1.12.0支持LB证书自动部署

&#x1f525;httpsok-v1.12.0支持LB证书自动部署 介绍 httpsok 是一个便捷的 HTTPS 证书自动续签工具&#xff0c;基于全新的设计理念&#xff0c;专为 Nginx 、OpenResty 服务器设计。已服务众多中小企业&#xff0c;稳定、安全、可靠。 一行命令&#xff0c;一分钟轻松搞…...

基于Pytorch框架的深度学习EfficientNetV2神经网络中草药识别分类系统源码

第一步&#xff1a;准备数据 5种中草药数据&#xff1a;self.class_indict ["百合", "党参", "山魈", "枸杞", "槐花", "金银花"] &#xff0c;总共有900张图片&#xff0c;每个文件夹单独放一种数据 第二步&a…...

网络协议。

一、流程案例 接下来揭秘我要说的大事情&#xff0c;“双十一”。这和我们要讲的网络协议有什么关系呢&#xff1f; 在经济学领域&#xff0c;有个伦纳德里德&#xff08;Leonard E. Read&#xff09;创作的《铅笔的故事》。这个故事通过一个铅笔的诞生过程&#xff0c;来讲述…...

Excel单元格格式无法修改的原因与解决方法

Excel单元格格式无法更改可能由多种原因造成。以下是一些可能的原因及相应的解决方法&#xff1a; 单元格或工作表被保护&#xff1a; 如果单元格或工作表被设置为只读或保护状态&#xff0c;您将无法更改其中的格式。解决方法&#xff1a;取消单元格或工作表的保护。在Excel中…...

CasaOS玩客云安装全平台高速下载器Gopeed并实现远程访问

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…...

JAVA学习-练习试用Java实现“最长回文子串”

问题&#xff1a; 给定一个字符串 s&#xff0c;找到 s 中最长的回文子串。 示例 1&#xff1a; 输入&#xff1a;s "babad" 输出&#xff1a;"bab" 解释&#xff1a;"aba" 同样是符合题意的答案。 示例 2&#xff1a; 输入&#xff1a;s …...

国防科技大学计算机基础课程笔记02信息编码

1.机内码和国标码 国标码就是我们非常熟悉的这个GB2312,但是因为都是16进制&#xff0c;因此这个了16进制的数据既可以翻译成为这个机器码&#xff0c;也可以翻译成为这个国标码&#xff0c;所以这个时候很容易会出现这个歧义的情况&#xff1b; 因此&#xff0c;我们的这个国…...

深入剖析AI大模型:大模型时代的 Prompt 工程全解析

今天聊的内容&#xff0c;我认为是AI开发里面非常重要的内容。它在AI开发里无处不在&#xff0c;当你对 AI 助手说 "用李白的风格写一首关于人工智能的诗"&#xff0c;或者让翻译模型 "将这段合同翻译成商务日语" 时&#xff0c;输入的这句话就是 Prompt。…...

Java 语言特性(面试系列1)

一、面向对象编程 1. 封装&#xff08;Encapsulation&#xff09; 定义&#xff1a;将数据&#xff08;属性&#xff09;和操作数据的方法绑定在一起&#xff0c;通过访问控制符&#xff08;private、protected、public&#xff09;隐藏内部实现细节。示例&#xff1a; public …...

Spring Boot 实现流式响应(兼容 2.7.x)

在实际开发中&#xff0c;我们可能会遇到一些流式数据处理的场景&#xff0c;比如接收来自上游接口的 Server-Sent Events&#xff08;SSE&#xff09; 或 流式 JSON 内容&#xff0c;并将其原样中转给前端页面或客户端。这种情况下&#xff0c;传统的 RestTemplate 缓存机制会…...

FastAPI 教程:从入门到实践

FastAPI 是一个现代、快速&#xff08;高性能&#xff09;的 Web 框架&#xff0c;用于构建 API&#xff0c;支持 Python 3.6。它基于标准 Python 类型提示&#xff0c;易于学习且功能强大。以下是一个完整的 FastAPI 入门教程&#xff0c;涵盖从环境搭建到创建并运行一个简单的…...

django filter 统计数量 按属性去重

在Django中&#xff0c;如果你想要根据某个属性对查询集进行去重并统计数量&#xff0c;你可以使用values()方法配合annotate()方法来实现。这里有两种常见的方法来完成这个需求&#xff1a; 方法1&#xff1a;使用annotate()和Count 假设你有一个模型Item&#xff0c;并且你想…...

MVC 数据库

MVC 数据库 引言 在软件开发领域,Model-View-Controller(MVC)是一种流行的软件架构模式,它将应用程序分为三个核心组件:模型(Model)、视图(View)和控制器(Controller)。这种模式有助于提高代码的可维护性和可扩展性。本文将深入探讨MVC架构与数据库之间的关系,以…...

06 Deep learning神经网络编程基础 激活函数 --吴恩达

深度学习激活函数详解 一、核心作用 引入非线性:使神经网络可学习复杂模式控制输出范围:如Sigmoid将输出限制在(0,1)梯度传递:影响反向传播的稳定性二、常见类型及数学表达 Sigmoid σ ( x ) = 1 1 +...

2025季度云服务器排行榜

在全球云服务器市场&#xff0c;各厂商的排名和地位并非一成不变&#xff0c;而是由其独特的优势、战略布局和市场适应性共同决定的。以下是根据2025年市场趋势&#xff0c;对主要云服务器厂商在排行榜中占据重要位置的原因和优势进行深度分析&#xff1a; 一、全球“三巨头”…...

sipsak:SIP瑞士军刀!全参数详细教程!Kali Linux教程!

简介 sipsak 是一个面向会话初始协议 (SIP) 应用程序开发人员和管理员的小型命令行工具。它可以用于对 SIP 应用程序和设备进行一些简单的测试。 sipsak 是一款 SIP 压力和诊断实用程序。它通过 sip-uri 向服务器发送 SIP 请求&#xff0c;并检查收到的响应。它以以下模式之一…...