栈和队列题目详解

news2024/9/20 7:54:57

前言:

在前面我们学习了栈和队列,栈的特性是后进先出,队列的特性是先进先出,当我们了解了这些之后,我们就可以用到栈和队列的特性来简单的做一些题目了。

1. 有效的括号

有效的括号:. - 力扣(LeetCode)

思路:这个题目我们就可以很好的利用栈的特性来进行解决,我们让左括号入栈,如果我们读取过程中,遇到了右括号,我们就将栈顶的左括号拿出来与它进行匹配,这里会出现两种情况:

情况1:我们在遇到右括号的时候,发现栈为空,此时说明配对失败了。

情况2:当我们遍历完字符串了之后,发现栈不为空,那么此时说明左右括号的数量不匹配,此时也说明失败了。

 代码:

typedef char STDataType;

typedef struct Stack
{
	STDataType* arr;
	int top;
	int capacity;
}st;

void STInit(st* pst);

void STDestroy(st* pst);

void STPush(st* pst, STDataType x);

void STPop(st* pst);

STDataType STTop(st* pst);

bool STEmpty(st* pst);

int STSize(st*pst);
void STInit(st* pst)
{
	assert(pst);
	pst->arr = NULL;
	pst->top = pst->capacity = 0;
}

void STDestroy(st* pst)
{
	assert(pst);
	free(pst->arr);
	pst->arr = NULL;
	pst->capacity = pst->top = 0;
}

void STPush(st* pst, STDataType x)
{
	assert(pst);
	if (pst->capacity == pst->top)
	{
		int newcapacity = pst->capacity == 0 ? 4 : 2 * pst->capacity;
		STDataType* tmp = (STDataType*)realloc(pst->arr, newcapacity * sizeof(STDataType));
		if (tmp == NULL)
		{
			perror("realloc");
			return;
		}
		pst->arr = tmp;
		pst->capacity = newcapacity;
	}
	pst->arr[pst->top++] = x;
}

void STPop(st* pst)
{
	assert(pst);
	assert(pst->top > 0);
	
	pst->top--;
}

STDataType STTop(st* pst)
{
	assert(pst);
	assert(pst->top > 0);
	return pst->arr[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 pst;
    STInit(&pst);
    while(*s)
    {
        //左扩号进栈
        if(*s == '('||*s == '[' || *s == '{')
        {
            STPush(&pst,*s);
        }
        else
        {
            //如果左括号没有入栈,那么栈是空的,就不能和之后的右括号进行匹配
            if(STEmpty(&pst))
            {
                return false;
            }
            //创建字符类型接收栈顶元素
            char tmp = STTop(&pst);
            //出栈
            STPop(&pst);
            //这里有一对匹配不合格直接返回false
            if(tmp == '(' && *s != ')' ||
               tmp == '[' && *s != ']' ||
               tmp == '{' && *s != '}')
               return false;
        }
        //让s往后走
        s++;
    }
    //如果s走完了,但是栈内还有元素,就说明匹配不成功
    if(!STEmpty(&pst))
    {
        return false;
    }
    else
    {
        return true;
    }
}

2. 用队列实现栈

用队列实现栈:. - 力扣(LeetCode)

思路:我们知道栈的特性是后进先出,队列是先进先出,我们如何使用两个队列来实现一个栈,其实,我们可以一个队列用来存数据,一个队列为空队列,我们在之后的入数据入到不为空的队列,如果要出数据,我们就可以将不为空的队列的前size-1个数据入到空队列里面,不为空的队列最后剩下的一个数据就栈的栈顶元素。

 代码:

typedef int QDataType;

typedef struct QueueNode
{
	QDataType data;
	struct QueueNode* next;
}QNode;

typedef struct Queue
{
	QNode* phead;
	QNode* ptail;
	int size;
}Queue;

//初始化队列
void QInit(Queue* qp);
//入队 出队
void QPush(Queue* qp, QDataType x);
void QPop(Queue* qp);
//获取队首,队尾数据
QDataType QFront(Queue* qp);
QDataType QBack(Queue* qp);

//获取对内有效数据个数
int QSize(Queue* qp);

//判断队列是否为空
bool QEmpty(Queue* qp);

//销毁队列
void QDestroy(Queue* qp);
void QInit(Queue* qp)
{
	assert(qp);
	qp->phead = NULL;
	qp->ptail = NULL;
	qp->size = 0;
}

void QDestroy(Queue* qp)
{
	assert(qp);
	QNode* cur = qp->phead;
	while (cur)
	{
		QNode* next = cur->next;
		free(cur);
		cur = next;
	}
	qp->phead = qp->ptail = NULL;
	qp->size = 0;	
}

void QPush(Queue* qp, QDataType x)
{
	assert(qp);
	QNode* newnode = (QNode*)malloc(sizeof(QNode));
	if (newnode == NULL)
	{
		perror("malloc");
		return;
	}
	newnode->data = x;
	newnode->next = NULL;
	if (qp->phead == NULL)
	{
		qp->phead = qp->ptail = newnode;
	}
	else
	{
		qp->ptail->next = newnode;
		qp->ptail = newnode;
	}
	qp->size++;
}

void QPop(Queue* qp)
{
	assert(qp);
	assert(qp->size > 0);
	if (qp->phead->next == NULL)
	{
		free(qp->phead);
		qp->phead = qp->ptail = NULL;
	}
	else
	{
		QNode* next = qp->phead->next;
		free(qp->phead);
		qp->phead = next;
	}
	qp->size--;
}

QDataType QFront(Queue* qp)
{
	assert(qp);
	assert(qp->phead);
	return qp->phead->data;
}

QDataType QBack(Queue* qp)
{
	assert(qp);
	assert(qp->ptail!=NULL);

	return qp->ptail->data;
}

int QSize(Queue* qp)
{
	assert(qp);
	return qp->size;
}

bool QEmpty(Queue* qp)
{
	assert(qp);

	return qp->size == 0;
}


typedef struct {
    Queue q1;
    Queue q2;
} MyStack;


MyStack* myStackCreate() {
    //初始化栈
    MyStack* pst = (MyStack*)malloc(sizeof(MyStack));
    if(pst == NULL)
    {
        perror("malloc");
        exit(1);
    }
    //初始化两个队列
   QInit(&pst->q1);
   QInit(&pst->q2);

   return pst;
}

void myStackPush(MyStack* obj, int x) {
    assert(obj);
    //如果q1队列为空,我们就把数据插入到q2
    if( QEmpty(&obj->q1))
    {
       
        QPush(&obj->q2,x);
    }
    else//反之插入到q1
    {
        QPush(&obj->q1,x);

    }
}

int myStackPop(MyStack* obj) {
    assert(obj);
    //假设法
    //这里我们们假设q1为空队列,q2为非空队列
    Queue* empty = &obj->q1;
    Queue* noempty = &obj->q2;
    if(QEmpty(&obj->q2))//如果q2为空队列
    {
        //交换一下
        empty = &obj->q2;
        noempty = &obj->q1;
    }
    //将非空队列里面前size-1个数据导入到空队列,此时剩下的数据就是栈顶元素
    while(QSize(noempty)>1)
    {
        QPush(empty,QFront(noempty));
        QPop(noempty);
    }
    //接收非空队列的最后一个数据即栈顶数据
    int ret = QFront(noempty);
    //删除栈顶数据
    QPop(noempty);
    return ret;
}

int myStackTop(MyStack* obj) {
    assert(obj);
    //这里如果q1是空队列,返回q2的队尾
    if(QEmpty(&obj->q1))
    {
        return QBack(&obj->q2);
    }
    else
    {
        //反之返回q1的队尾
        return QBack(&obj->q1);

    }
}

bool myStackEmpty(MyStack* obj) {
    assert(obj);
    //两个队列同时为空才是空
    return QEmpty(&obj->q1)&& QEmpty(&obj->q2);
}

void myStackFree(MyStack* obj) {
    assert(obj);
    //释放
    QDestroy(&obj->q1);
    QDestroy(&obj->q2);
    free(obj);
    obj = NULL;

}

3. 用栈实现队列

用栈实现队列:. - 力扣(LeetCode)

思路:这里我们如何用两个队列来是实现栈,我们还是可以用一个栈用来入数据,一个栈用来出数据,如果有数据,就都入到入数据的这个栈里面,如果需要出数据,我们先判断出数据的这个栈是否为空,如果为空,我们就把入数据的这个栈里面的数据全部导入到出数据的这个栈里面。

代码:

typedef int STDataType;

typedef struct Stack
{
	STDataType* arr;
	int top;
	int capacity;
}st;

void STInit(st* pst);

void STDestroy(st* pst);

void STPush(st* pst, STDataType x);

void STPop(st* pst);

STDataType STTop(st* pst);

bool STEmpty(st* pst);

int STSize(st*pst);

void STInit(st* pst)
{
	assert(pst);
	pst->arr = NULL;
	pst->top = pst->capacity = 0;
}

void STDestroy(st* pst)
{
	assert(pst);
	free(pst->arr);
	pst->arr = NULL;
	pst->capacity = pst->top = 0;
}

void STPush(st* pst, STDataType x)
{
	assert(pst);
	if (pst->capacity == pst->top)
	{
		int newcapacity = pst->capacity == 0 ? 4 : 2 * pst->capacity;
		STDataType* tmp = (STDataType*)realloc(pst->arr, newcapacity * sizeof(STDataType));
		if (tmp == NULL)
		{
			perror("realloc");
			return;
		}
		pst->arr = tmp;
		pst->capacity = newcapacity;
	}
	pst->arr[pst->top++] = x;
}

void STPop(st* pst)
{
	assert(pst);
	assert(pst->top > 0);
	
	pst->top--;
}

STDataType STTop(st* pst)
{
	assert(pst);
	assert(pst->top > 0);
	return pst->arr[pst->top - 1];
}

bool STEmpty(st* pst)
{
	assert(pst);
	return pst->top == 0;
}

int STSize(st*pst)
{
	assert(pst);
	return pst->top;
}

typedef struct {
    ///创建两个栈,一个栈用来入数据,一个栈用来出数据
    st pushst;
    st popst;
} MyQueue;


MyQueue* myQueueCreate() {
    MyQueue* tmp = (MyQueue*)malloc(sizeof(MyQueue));
    if(tmp == NULL)
    {
        perror("malloc");
        exit(1);
    }
    //初始化两个栈
    STInit(&tmp->pushst);
    STInit(&tmp->popst);
    return tmp;

}

void myQueuePush(MyQueue* obj, int x) {
     assert(obj);
     //我们直接将数据插入到入栈栈里面
     STPush(&obj->pushst,x);
}

int myQueuePop(MyQueue* obj) {
    //这里我们调用一下下面的函数,如果出栈栈为空则把入栈栈的数据都导入到出栈栈里面
    //然后接收队列开头元素
    int ret = myQueuePeek(obj);
    
    //直接删除出栈栈的栈顶元素
    STPop(&obj->popst);
    return ret;
}

int myQueuePeek(MyQueue* obj) {
    assert(obj);
    //如果出栈栈为空
    if(STEmpty(&obj->popst))
    {
        //那么我们把入栈栈的数据导入到出栈栈里面
        while(!STEmpty(&obj->pushst))
        {
            STPush(&obj->popst,STTop(&obj->pushst));
            STPop(&obj->pushst);
        }
    }
    //此时的栈顶元素就是队列的队头元素
    return STTop(&obj->popst);
}

bool myQueueEmpty(MyQueue* obj) {
    assert(obj);
   //两个栈都为空,队列才为空
    return STEmpty(&obj->pushst)&&STEmpty(&obj->popst);
}

void myQueueFree(MyQueue* obj) {
    assert(obj);
    //先释放动态申请的两个栈 
    STDestroy(&obj->pushst);
    STDestroy(&obj->popst);
    //在释放动态申请的队列
    free(obj);
    obj = NULL;


}

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

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

相关文章

ESP32驱动摄像头:1.驱动OV2640模块(待验证)

一、装ArduCam库和ESPAsyncWebServer库 二、参考代码 #include <Wire.h> #include <ArduCAM.h> #include <SPI.h> #include <WiFi.h> #include <ESPAsyncWebServer.h>#define CAM_CS 32 // modify according to your own wiring #define OV2640…

昇思25天训练营Day11 - 基于 MindSpore 实现 BERT 对话情绪识别

模型简介 BERT全称是来自变换器的双向编码器表征量&#xff08;Bidirectional Encoder Representations from Transformers&#xff09;&#xff0c;它是Google于2018年末开发并发布的一种新型语言模型。与BERT模型相似的预训练语言模型例如问答、命名实体识别、自然语言推理、…

电焰灶:烹饪性能的深度剖析

在如今众多的厨房炉灶选择中&#xff0c;华火电焰灶以其独特的技术和性能吸引了不少消费者的目光。那么&#xff0c;华火电焰灶的综合烹饪性能究竟如何呢&#xff1f;让我们一起来深入探究。 首先&#xff0c;从火力方面来看&#xff0c;华火电焰灶展现出了强大的优势。其火焰强…

5G/4G加密边缘计算电力网关,开启智慧电力新篇章

计讯物联TG452&#xff0c;一款面向电力行业应用的工业级物联网网关&#xff0c;持电力协议及规约标准&#xff0c;支持采集、存储、算力、通信组网 、协议转换、控制等多功能。    电力应用   计讯物联电力网关TG452支持电力IEC101、IEC104、IEC61850、DL/T645等协议标准…

uniapp 微信小程序,最简单的流式输出:Transfer-Encoding: chunked

在GPT项目中&#xff0c;流式输出是实现流畅对话体验的关键技术之一。今天&#xff0c;我们将探讨如何在uniapp开发的微信小程序中优雅地实现这一功能。虽然WebSocket是一种常见的解决方案&#xff0c;但在某些场景下&#xff0c;我们可能寻求更轻量级且易于集成的替代方案。本…

unity使用 MQTT复现plant simulate仿真

unity使用 MQTT复现plant simulate仿真 一、plant simulate端配置 1、plant simulate MQTT组件配置&#xff0c;该组件在类库的信息流类目下&#xff0c;端口不变&#xff0c;填写ip即可&#xff1b; 2、设备配置界面&#xff0c;在控件入口和出口处各挂一个脚本&#xff0c;…

新手教学系列——MongoDB聚合查询的进阶用法

引言 MongoDB的聚合查询是其最强大的功能之一。无论是汇总、平均值、计数等标准操作,还是处理复杂的数据集合,MongoDB的聚合框架都能提供高效且灵活的解决方案。本文将通过几个实例,详细讲解如何在实际项目中使用MongoDB进行聚合查询。 标准应用:汇总、平均值、计数等 在…

认识string(一)详解

目录 标准库中的string类了解如何看文档Construct string (构造string)string()空字符串构造函数&#xff08;默认构造函数&#xff09;string (const string& str) 拷贝构造函数string (const string& str, size_t pos, size_t len npos)string (const char* s)复制构…

FiddlerScript Rules修改-更改发包中的cookie

直接在fiddler script editor中增加如下处理代码即可 推荐文档oSession -- 参数说明 测试笔记 看云

SSRF漏洞深入利用与防御方案绕过技巧

文章目录 前言SSRF基础利用1.1 http://内网资源访问1.2 file:///读取内网文件1.3 dict://探测内网端口 SSRF进阶利用2.1 Gopher协议Post请求2.2 Gopher协议文件上传2.3 GopherRedis->RCE2.4 JavaWeb中的适用性&#xff1f; SSRF防御绕过3.1 Url黑名单检测的绕过3.2 Url白名单…

公共安全和应急管理系统:提升社区韧性与危机应对能力

引言 公共安全和应急管理是现代社会不可或缺的组成部分&#xff0c;其核心目标是确保社会的稳定和居民的福祉。随着全球化、城市化和技术进步&#xff0c;社会面临的风险和威胁日益复杂多样&#xff0c;从自然灾害到人为事故&#xff0c;从公共卫生危机到恐怖袭击&#xff0c;公…

机器学习(V)--无监督学习(三)EM算法

EM算法 极大似然估计 极大似然估计&#xff1a;(maximum likelihood estimate, MLE) 是一种常用的模型参数估计方法。它假设观测样本出现的概率最大&#xff0c;也即样本联合概率&#xff08;也称似然函数&#xff09;取得最大值。 为求解方便&#xff0c;对样本联合概率取对…

强烈推荐!!李沐老师《动手学深度学习》最新Pytorch版!

动手学深度学习(PyTorch版)》是由李沐、Aston Zhang和孔德威共同编写的教材&#xff0c;专为深度学习初学者和实践者设计。本书使用PyTorch作为主要的深度学习框架&#xff0c;全面系统地介绍了深度学习的基本理论、常见模型和实际应用技巧。 书中内容包括深度学习的基础知识、…

【YOLOv8】 用YOLOv8实现数字式工业仪表智能读数(一)

上一篇圆形表盘指针式仪表的项目受到很多人的关注&#xff0c;咱们一鼓作气&#xff0c;把数字式工业仪表的智能读数也研究一下。本篇主要讲如何用YOLOV8实现数字式工业仪表的自动读数&#xff0c;并将读数结果进行输出&#xff0c;若需要完整数据集和源代码可以私信。 目录 &…

Html5+Css3学习笔记

Html5 CSS3 一、概念 1.什么是html5 html: Hyper Text Markup Language ( 超文本标记语言) 文本&#xff1a;记事本 超文本&#xff1a; 文字、图片、音频、视频、动画等等&#xff08;网页&#xff09; html语言经过浏览器的编译显示成超文本 开发者使用5种浏览器&#xf…

element ui ts table重置排序

#日常# 今天带的实习生&#xff0c;在遇到开发过程中&#xff0c;遇到了element ui table 每次查询的时候都需要重置排序方式&#xff0c;而且多个排序是由前端排序。 <el-table :data"tableData" ref"restTable"> </<el-table> <script…

谷粒商城实战笔记-24-分布式组件-SpringCloud Alibaba-Nacos配置中心-命名空间与配置分组

文章目录 一&#xff0c;命名空间1&#xff0c;简介1.1&#xff0c;命名空间的主要功能和特点1.2&#xff0c;使用场景1.3&#xff0c;如何指定命名空间 2&#xff0c;命名空间实战2.1&#xff0c;环境隔离2.2&#xff0c;服务隔离 二&#xff0c;配置集三&#xff0c;配置集ID…

半月内笔者暂不写时评文

今晨&#xff0c;笔者在刚恢复的《新浪微博》发布消息表态如下&#xff1a;“要开会了&#xff01;今起&#xff0c;半月内笔者暂不写敏感时评文&#xff0c;不让自媒体网管感到压力&#xff0c;也是张驰有度、识时务者为俊杰之正常选择。野钓去也。” 截图&#xff1a;来源笔者…

apple watch程序出错 Cannot launch apps while in nightstand mode

开发的时候运行apple watch程序出错&#xff1a; ailure Reason: The request was denied by service delegate (IOSSHLMainWorkspace) for reason: Busy ("Cannot launch apps while in nightstand mode"). 这是因为&#xff1a; 将Apple Watch放在充电器上并直立…

4款免费国产开源软件,功能过于强大,常被认为是外国人开发

之前小编分享了一些良心的电脑软件&#xff0c;大部分都是国外的开源软件&#xff0c;就有部分同学在后台说小编有点极端了&#xff0c;国内也是有良心的电脑软件的。 本期就是国产软件专场&#xff0c;今天就给大家推荐几款良心的国产电脑软件&#xff0c;说真的&#xff0c;…