[LeetCode]栈,队列相关题目(C语言实现)

文章目录

  • LeetCode20. 有效的括号
  • LeetCode225. 用队列实现栈
  • LeetCode232. 用栈实现队列
  • LeetCode622. 设计循环队列

LeetCode20. 有效的括号

题目

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

要求

有效字符串需满足:

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

思路
用栈实现

  1. 如果是左括号, 直接将左括号入栈
  2. 如果是右括号, 如果此时栈为空, 返回 false; 将栈顶元素弹出栈, 如果栈顶元素不是对应的左括号, 返回 false; 如果栈顶元素是对应左括号, 出栈
  3. 遍历完字符串, 判断此时栈是否为空. 为空返回 true; 不为空返回 false

代码实现

#define N 10000
bool isValid(char * s)
{char stack[N] = {0,};   //创建栈数组int top = 0;            //top指向栈顶元素的后一个空间char topVal = 0;        //用来存放栈顶元素while (*s){//如果是左括号if (*s == '{' || *s == '(' || *s == '['){//入栈stack[top] = *s;top++;}//如果是右括号else{//如果此时栈为空, 直接返回falseif (top == 0){return false;}topVal = stack[top - 1];    //得到栈顶元素top--;  //栈顶元素出栈//如果右括号不是其对应的左括号, 直接返回falseif ((*s == ']' && topVal != '[')|| (*s == ')' && topVal != '(')|| (*s == '}' && topVal != '{')){return false;}}s++;}//如果遍历完字符串, 栈仍为空, 则返回trueif (top == 0)return true;elsereturn false;
}

LeetCode225. 用队列实现栈

题目

请你仅使用两个队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作(push、top、pop 和 empty)。

OJ链接

要求

实现 MyStack 类:

void push(int x) 将元素 x 压入栈顶。
int pop() 移除并返回栈顶元素。
int top() 返回栈顶元素。
boolean empty() 如果栈是空的,返回 true ;否则,返回 false

思路

  1. 使用两个队列,一个队列no_empty_que存放已经存放的元素,另一个队列empty_que常空
  2. 当要压栈的时候,将元素压入no_empty_que
  3. 当要出栈的时候,将no_empty_que中除队尾元素全部存入empty_que,将队尾元素移出

实例
在这里插入图片描述

代码实现

typedef int QDataType;// 链式结构表示队列
typedef struct QListNode
{struct QListNode* next;QDataType data;
}QNode;// 队列的结构
typedef struct Queue
{QNode* front;    //指向队列头QNode* rear;     //指向队列尾int size;        //记录队列的元素个数
}Queue;// 初始化队列
void QueueInit(Queue* q)
{assert(q);  //确保q合法q->front = q->rear = NULL;  //将头和为置为 NULL q->size = 0;
}// 判断队列是否为空, 如果为空返回非0, 非空返回0
int QueueEmpty(Queue* q)
{assert(q);  //确保q合法if (q->size == 0){return 1;}else {return 0;}
}// 队尾入队列
void QueuePush(Queue* q, QDataType x)
{assert(q);  //确保q合法//创建新结点QNode* newNode = (QNode*)malloc(sizeof(QNode));newNode->data = x;newNode->next = NULL;//入队列if (QueueEmpty(q)){//如果队列为空,直接赋值q->front = q->rear = newNode;}else {//如果队列不为空,直接尾插q->rear->next = newNode;q->rear = newNode;}q->size++;
}// 队头出队列
void QueuePop(Queue* q)
{assert(q);  //确保q合法assert(!QueueEmpty(q)); //确保队列不为空if (q->size == 1){//如果只有一个元素,头删的同时还要将尾指针置空free(q->front);q->front = q->rear = NULL;}else {//如果不止一个元素,则只头删QNode* nextNode = q->front->next;free(q->front);q->front = nextNode;}q->size--;
}// 获取头部元素
QDataType QueueFront(Queue* q)
{assert(q);  //确保q合法assert(!QueueEmpty(q)); //确保队列不为空return q->front->data;
}// 获取尾部元素
QDataType QueueBack(Queue* q)
{assert(q);  //确保q合法assert(!QueueEmpty(q)); //确保队列不为空return q->rear->data;
}// 获取队列元素个数
int QueueSize(Queue* q)
{assert(q);  //确保q合法return q->size;
}// 销毁队列
void QueueDestroy(Queue* q)
{assert(q);while(!QueueEmpty(q)){QNode* nextNode = q->front->next;free(q->front);q->front = nextNode;}q->front = q->rear = NULL;q->size = 0;
}//用两个队列构成一个栈
typedef struct 
{Queue queue1;Queue queue2;
} MyStack;MyStack* myStackCreate() 
{MyStack* pst = (MyStack*)malloc(sizeof(MyStack));QueueInit(&pst->queue1);QueueInit(&pst->queue2);return pst;
}void myStackPush(MyStack* obj, int x) 
{if (!QueueEmpty(&obj->queue1)){QueuePush(&obj->queue1, x);}else{QueuePush(&obj->queue2, x);}
}int myStackPop(MyStack* obj) 
{Queue* no_empty_que = &obj->queue1;Queue* empty_que = &obj->queue2;if (!QueueEmpty(&obj->queue2)){no_empty_que = &obj->queue2;empty_que = &obj->queue1;}//弹出有元素的队列直至只剩一个元素while (QueueSize(no_empty_que) > 1){QueuePush(empty_que, QueueFront(no_empty_que));QueuePop(no_empty_que);}int pop = QueueFront(no_empty_que);QueuePop(no_empty_que);return pop;
}int myStackTop(MyStack* obj) 
{if (!QueueEmpty(&obj->queue1)){return QueueBack(&obj->queue1);}else{return QueueBack(&obj->queue2);}
}bool myStackEmpty(MyStack* obj) 
{return QueueEmpty(&obj->queue1) && QueueEmpty(&obj->queue2);
}void myStackFree(MyStack* obj) 
{QueueInit(&obj->queue1);QueueInit(&obj->queue2);free(obj);
}

LeetCode232. 用栈实现队列

题目

你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(push、pop、peek、empty):OJ链接

要求

实现 MyQueue 类:

void push(int x) 将元素 x 推到队列的末尾
int pop() 从队列的开头移除并返回元素
int peek() 返回队列开头的元素
boolean empty() 如果队列为空,返回 true ;否则,返回 false

思路

  1. 使用两个栈,一个专门负责压入数据push_stack,另一个专门负责弹出数据pop_stack
  2. 当push数据,直接将数据压入push_stack
  3. 当pop数据,如果pop_stack为空,先将push_stack中的数据压入,pop_stack,再接将pop_stack的栈顶弹出

实例
在这里插入图片描述

代码实现

typedef int STDataType;typedef struct Stack
{STDataType* a;  //指向栈空间int top;        //栈顶int capacity;   //容量
}Stack;// 初始化栈
void StackInit(Stack* ps)
{assert(ps);ps->a = NULL;     ps->top = 0;ps->capacity = 0;
}//入栈
void StackPush(Stack* ps, STDataType data)
{assert(ps);       //确保ps合法//如果容量不够则扩容if (ps->capacity == ps->top){int newCapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;   //定义新的容量STDataType* tmp = (STDataType*)realloc(ps->a, sizeof(STDataType) * newCapacity);  //开辟新的空间if (tmp == NULL){perror("malloc error");exit(-1);}else {ps->a = tmp;ps->capacity = newCapacity;}}//将数据入栈ps->a[ps->top] = data;ps->top++;
}// 出栈
void StackPop(Stack* ps)
{assert(ps); //确保ps合法assert(!StackEmpty(ps));  //确保栈不为空ps->top--;}// 检测栈是否为空, 如果为空返回非零结果, 如果不为空返回 0
int StackEmpty(Stack* ps)
{assert(ps); //确保ps合法if (ps->top > 0){return 0;}else {return 1;}
}// 获取栈顶元素
STDataType StackTop(Stack* ps)
{assert(ps);   //确保ps合法assert(!StackEmpty(ps));  //确保栈不为空return ps->a[ps->top - 1];
}// 获取栈中有效元素个数
int StackSize(Stack* ps)
{assert(ps);   //确保ps合法return ps->top;
}// 销毁栈
void StackDestroy(Stack* ps)
{assert(ps); //确保ps合法free(ps->a);ps->a = NULL;ps->capacity = 0;ps->top = 0;
}typedef struct 
{Stack push_stack;Stack pop_stack;
} MyQueue;MyQueue* myQueueCreate() 
{MyQueue* que = (MyQueue*)malloc(sizeof(MyQueue));StackInit(&que->push_stack);StackInit(&que->pop_stack);return que;
}void myQueuePush(MyQueue* obj, int x) 
{StackPush(&obj->push_stack, x);
}int myQueuePop(MyQueue* obj) 
{int pop = myQueuePeek(obj);StackPop(&obj->pop_stack);return pop;
}int myQueuePeek(MyQueue* obj) 
{//如果pop_stack是空的话,将push_stack的所有元素入pop_stackif (StackEmpty(&obj->pop_stack)){while (!StackEmpty(&obj->push_stack)){StackPush(&obj->pop_stack, StackTop(&obj->push_stack));StackPop(&obj->push_stack);}}//如果pop_stack不是空,直接取栈顶元素int peek = StackTop(&obj->pop_stack);return peek;
}bool myQueueEmpty(MyQueue* obj) 
{return StackEmpty(&obj->push_stack) && StackEmpty(&obj->pop_stack);
}void myQueueFree(MyQueue* obj) 
{StackDestroy(&obj->push_stack);StackDestroy(&obj->pop_stack);free(obj);
}

LeetCode622. 设计循环队列

题目

设计你的循环队列实现。 循环队列是一种线性数据结构,其操作表现基于 FIFO(先进先出)原则并且队尾被连接在队首之后以形成一个循环。它也被称为“环形缓冲器”。

循环队列的一个好处是我们可以利用这个队列之前用过的空间。在一个普通队列里,一旦一个队列满了,我们就不能插入下一个元素,即使在队列前面仍有空间。但是使用循环队列,我们能使用这些空间去存储新的值。OJ链接

要求

你的实现应该支持如下操作:

MyCircularQueue(k): 构造器,设置队列长度为 k 。
Front: 从队首获取元素。如果队列为空,返回 -1 。
Rear: 获取队尾元素。如果队列为空,返回 -1 。
enQueue(value): 向循环队列插入一个元素。如果成功插入则返回真。
deQueue(): 从循环队列中删除一个元素。如果成功删除则返回真。
isEmpty(): 检查循环队列是否为空。
isFull(): 检查循环队列是否已满。

思路

  1. 为了确保方便判断空和满情况,将循环队列的空间比设定长度加1
  2. 入队列和出队列相关frontrear不是简单的加一或减一
  3. rear指向队尾下一个空间,front指向队头元素

代码实现

typedef struct 
{int* a;     //存放队列元素int front;  //指向队头元素int rear;   //指向队尾下一个元素int k;      //循环队列的大小
} MyCircularQueue;MyCircularQueue* myCircularQueueCreate(int k) 
{MyCircularQueue* cq = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));cq->a = (int*)malloc(sizeof(int) * (k + 1));cq->front = cq->rear = 0;cq->k = k;return cq;
}bool myCircularQueueIsEmpty(MyCircularQueue* obj) 
{return obj->front == obj->rear;
}bool myCircularQueueIsFull(MyCircularQueue* obj) 
{return (obj->rear + 1) % (obj->k + 1) == obj->front;
}bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) 
{//如果满了,插入失败if (myCircularQueueIsFull(obj)){return false;}//如果不满,进行插入,注意rear的大小obj->a[obj->rear] = value;obj->rear = (obj->rear + 1) % (obj->k + 1);return true;
}bool myCircularQueueDeQueue(MyCircularQueue* obj) 
{//如果没有元素,删除失败if (myCircularQueueIsEmpty(obj)){return false;}//直接修改front的值即可obj->front = (obj->front + 1) % (obj->k + 1);return true;
}int myCircularQueueFront(MyCircularQueue* obj) 
{if (myCircularQueueIsEmpty(obj)){return -1;}return obj->a[obj->front];
}int myCircularQueueRear(MyCircularQueue* obj) 
{if (myCircularQueueIsEmpty(obj)){return -1;}return obj->a[(obj->rear + obj->k) % (obj->k + 1)];
}void myCircularQueueFree(MyCircularQueue* obj) 
{free(obj->a);free(obj);
}

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

合宙Air724UG LuatOS-Air LVGL API控件-键盘 (Keyboard)

键盘 (Keyboard) LVGL 可以添加触摸键盘,但是很明显,使用触摸键盘的话必须要使用触摸的输入方式,否则无法驱动键盘。 示例代码 function keyCb(obj, e)-- 默认处理事件lvgl.keyboard_def_event_cb(keyBoard, e)if(e lvgl.EVENT_CANCEL)the…

一百七十二、Flume——Flume采集Kafka数据写入HDFS中(亲测有效、附截图)

一、目的 作为日志采集工具Flume,它在项目中最常见的就是采集Kafka中的数据然后写入HDFS或者HBase中,这里就是用flume采集Kafka的数据导入HDFS中 二、各工具版本 (一)Kafka kafka_2.13-3.0.0.tgz (二)…

QT—基于http协议的网络文件下载

1.常用到的类 QNetworkAccessManager类用于协调网络操作,负责发送网络请求,创建网络响应 QNetworkReply类表示网络请求的响应。在QNetworkAccessManager发送一个网络请求后创建一个网络响应。它提供了以下信号: finished():完成…

Net跨平台UI框架Avalonia入门-安装和使用(v11版本)

介绍Avalonia v11版本 avalonia v11版本发布了,增加了很多新的功能,Avalonia的扩展也同步升级了。 主要更新内容: 辅助功能:增加了对各种辅助工具的支持,提高了Avalonia应用程序的可用性。输入法编辑器(I…

video标签自动播放音视频并绘制波形图

html中的<video>标签可以用来播放常见的音视频格式&#xff0c;支持的格式包括:MP3、Ogg、WAV、AAC、MP4、WebM、AVI等&#xff0c;当然支持的格式也和浏览器和操作系统有关。这里以一个可以自动播放音视频并绘制波形图的页面为例说明一下<video>标签的用法。 vid…

LAMP搭建WordPress

L linux A apache hhtpd M mysql/maridb P PHP1、 安装php yum -y install php php-fpm php-server php-mysql1.1、 启动php-fpm并自启 systemctl enable php-fpm --now[rootecs-1cee ~]# systemctl status php-fpm ● php-fpm.service - The PHP FastCGI Process ManagerLoa…

达梦控制台还原报错“管道失败”

达梦数据库控制台还原报错“管道失败” 环境 主机操作系统&#xff1a;windows10 profession 达梦数据库版本&#xff1a;达梦7 问题背景 全新安装达梦7数据库后&#xff0c;创建数据库实例&#xff0c;需要恢复往期bat备份。在控制台配置指定搜索目录后&#xff0c;获取备份时…

警告:Provides transitive vulnerable dependency maven:org.yaml:snakeyaml:1.30

1. 警告 SpringBoot 的 validation 依赖包含有易受攻击的依赖 snakeyaml。 警告信息如下&#xff1a; Provides transitive vulnerable dependency maven:org.yaml:snakeyaml:1.30 意思是&#xff1a;提供了可传递的易受攻击依赖 maven:org.yaml:snakeyaml:1.30 2. 警告示例 …

【MySQL】MySQL的安装,登录,配置和相关命令

文章目录 前言一. 卸载不需要的环境二. 获取MySQL的yum源三. 安装MySQL和启动四. 尝试登录MySQL方法1&#xff1a;获取临时root密码方法2&#xff1a;没有密码方法3&#xff1a;配置文件 五. 简单配置结束语 前言 本篇文章是基于云服务器&#xff1b;Linux&#xff1a;Centos7…

【图文并茂】C++介绍之串

1.1串 引子—— ​ 字符串简称为串&#xff0c;串是由字符元素构成的&#xff0c;其中元素的逻辑关系也是一种线性关系。串的处理在计算机非数值处理中占用重要的地位&#xff0c;如信息检索系统&#xff0c;文字编辑等都是以串数据作为处理对象 串是由零个或多个字符组成的…

NATAPP内网穿透之接口测试

下载 工具下载 下载对应系统版本的软件&#xff1a; NATAPP-内网穿透 基于ngrok的国内高速内网映射工具 认证文件下载 使用本地配置文件config.ini - NATAPP-内网穿透 基于ngrok的国内高速内网映射工具 解压完之后&#xff0c;将配置文件放到解压后的文件夹中 申请免费隧…

编程中的信号处理和系统 - 初学者指南

信号处理是工程和编程的一个重要领域。 基本上,它允许工程师和程序员改进数据,以便人们可以更有效地使用它。 例如,由于信号处理,电话中的大部分背景噪音都被消除了。这样,通话的另一端就只能听到您的声音。 其他例子有: 音频和音乐软件图像视频处理软件医学影像软件语…