栈和队列经典OJ题详解

news2024/11/25 10:53:39

目录

一、用栈实现队列

1.1 题目

1.2 思路

1.3 C语言题解

1.3.1 栈接口

1.3.2 代码实现

二、用队列实现栈

2.1 题目

2.2 思路

2.2.1 如何设计出栈

2.2.2 如何设计入栈

2.3 C语言题解

2.3.1 队列接口

2.3.2 代码实现

三、括号匹配问题

3.1 题目

3.2 思路

3.3 C语言题解

3.3.1 栈接口

3.3.2 主函数


一、用栈实现队列

1.1 题目

LeetCode原题链接:. - 力扣(LeetCode)

1.2 思路

        栈的特点是后进先出,要通过栈实现队列的先进先出。可以将所有数据压入一个栈中,再一个个出栈压入另一个空栈中,这样原先的栈底就变成了现在的栈顶。现在的栈的顺序就完美符合队列的顺序。

        综上,设计一个入栈,一个出栈即可完成此问题。

1.3 C语言题解

1.3.1 栈接口

  •  基于自己用C语言编写的接口进行题目的求解
  •  关于栈的知识详见博主的另一篇博客:http://t.csdnimg.cn/SHAxi
typedef int STDataType;

typedef struct Stack
{
	STDataType* a;    //数组
	int top;		//栈顶元素
	int capacity;	//数据个数
}ST;

void STInit(ST* pst)
{
	assert(pst);
	pst->a = NULL;
	pst->capacity = 0;
	//top指向栈顶元素的下一个位置
	pst->top = 0;
	top指向栈顶元素的位置
	//pst->top = -1;
}

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

void STPush(ST* pst, STDataType x)
{
	assert(pst);
	//扩容
	if (pst->top == pst->capacity)
	{
		int newcapacity = 0;
		if (pst->capacity == 0)
		{
			newcapacity = 4;
		}
		else
		{
			newcapacity = pst->capacity * 2;
		}
		STDataType* temp = (STDataType*)realloc(pst->a, newcapacity * sizeof(STDataType));
		if (temp == NULL)
		{
			perror("malloc");
			exit(1);
		}

		pst->a = temp;
		pst->capacity = newcapacity;
	}
	pst->a[pst->top] = x;
	pst->top++;
}

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

STDataType STTop(ST* pst)
{
	assert(pst);
	assert(pst > 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;
}

1.3.2 代码实现

typedef struct {
	ST pushstack;
	ST popstack;
} MyQueue;

//创建队列
MyQueue* myQueueCreate() {
	MyQueue* obj = (MyQueue*)malloc(sizeof(MyQueue));
	if (obj == NULL)
	{
		perror("malloc");
		exit(1);
	}
	STInit(&(obj->pushstack));
	STInit(&(obj->popstack));
	return obj;
}
//将元素 x 推到队列的末尾
void myQueuePush(MyQueue* obj, int x) {
	STPush(&(obj->pushstack), x);
}
//从队列的开头移除并返回元素
int myQueuePop(MyQueue* obj) {
	if (STEmpty(&(obj->popstack)))
	{
		while (!STEmpty(&(obj->pushstack)))
		{
			int front = STTop(&(obj->pushstack));
			STPush(&(obj->popstack), front);
			STPop(&(obj->pushstack));
		}
	}
	int temp = STTop(&(obj->popstack));
	STPop(&(obj->popstack));
	return temp;
}
//返回队列开头的元素
int myQueuePeek(MyQueue* obj) {
	if (STEmpty(&(obj->popstack)))
	{
		while (!STEmpty(&(obj->pushstack)))
		{
			int front = STTop(&(obj->pushstack));
			STPush(&(obj->popstack), front);
			STPop(&(obj->pushstack));
		}
	}
	return STTop(&(obj->popstack));
}
//如果队列为空,返回 true ;否则,返回 false
bool myQueueEmpty(MyQueue* obj) {
	if (STEmpty(&(obj->popstack)) == 1 && STEmpty(&(obj->pushstack)) == 1)
	{
		return true;
	}
	else
	{
		return false;
	}
}
//销毁队列
void myQueueFree(MyQueue* obj) {
	STDestroy(&(obj->pushstack));
	STDestroy(&(obj->pushstack));
	free(obj);
}

二、用队列实现栈

2.1 题目

LeetCode原题链接:. - 力扣(LeetCode)

2.2 思路

2.2.1 如何设计出栈

        队列的特点是先进先出,要想实现栈的后进先出。核心就是要实现后进的元素先出栈。使用两个队列。先将所有元素全部压入其中一个队列,将队列中最后一个元素之前的所有元素全部出队到另一个空的队列,那么剩下的元素便是最后的元素,从而实现了后进先出。

2.2.2 如何设计入栈

        出栈的问题解决了以后,我们再来看如何入栈。入栈的问题就在于在空的栈入栈还是在非空的栈入栈。理论上讲两种方式都可以实现。但是从代码的编写角度看,如果在空栈中继续压栈,那么就导致没有空栈的存在,意味着判断的困难,所以一律采取从非空栈入栈。

2.3 C语言题解

2.3.1 队列接口

  •  基于自己用C语言编写的接口进行题目的求解
  • 关于队列的知识详见博主的另一篇博客:http://t.csdnimg.cn/afeBF
typedef int QDataType;

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

typedef struct Queue
{
	QNode* phead;
	QNode* ptail;
	int size;
}Queue;
//队列初始化
void QueueInit(Queue* pq)
{
	assert(pq);
	pq->phead = pq->ptail = NULL;
	pq->size = 0;
}
//队列销毁
void QueueDestroy(Queue* pq)
{
	assert(pq);
	QNode* pcur = pq->phead;

	while (pcur)
	{
		QNode* temp = pcur->next;
		free(pcur);
		pcur = temp;
	}
	pq->phead = pq->ptail = NULL;
	pq->size = 0;
}
//创建节点封装
QNode* InitNewnode(QDataType x)
{
	QNode* newnode = (QNode*)malloc(sizeof(QNode));
	if (newnode == NULL)
	{
		perror("malloc");
		exit(1);
	}
	newnode->val = x;
	newnode->next = NULL;
	return newnode;
}
//入队
void QueuePush(Queue* pq, QDataType x)
{
	assert(pq);
	QNode* newnode = InitNewnode(x);
	if (pq->phead == NULL)
	{
		pq->phead = pq->ptail = newnode;
	}
	else
	{
		pq->ptail->next = newnode;
		pq->ptail = newnode;
	}

	pq->size++;
}
//出队
void QueuePop(Queue* pq)
{
	assert(pq);
	assert(pq->size != 0);
	assert(pq);
	assert(pq->size != 0);
	if (pq->phead->next == NULL)
	{
		free(pq->phead);
		pq->phead = pq->ptail = NULL;
	}
	else
	{
		QNode* temp = pq->phead->next;
		free(pq->phead);
		pq->phead = temp;
	}
	pq->size--;	
}
//队列大小
int QueueSize(Queue* pq)
{
	return pq->size;
}
//判空
bool QueueEmpty(Queue* pq)
{
	assert(pq);

	return pq->size == 0;
}
//返回队头元素
QDataType QueueFront(Queue* pq)
{
	assert(pq);
	assert(pq->phead);

	return pq->phead->val;
}
//返回队尾元素
QDataType QueueBack(Queue* pq)
{
	assert(pq);
	assert(pq->ptail);

	return pq->ptail->val;
}

2.3.2 代码实现

typedef struct {
	Queue queue1;
	Queue queue2;
} MyStack;

MyStack* myStackCreate() {
	MyStack* obj = (MyStack*)malloc(sizeof(MyStack));
	if (obj == NULL)
	{
		perror("malloc");
		exit(1);
	}
	QueueInit(&(obj->queue1));
	QueueInit(&(obj->queue2));
	return obj;
}
//将元素 x 压入栈顶。
void myStackPush(MyStack* obj, int x) {
	if (QueueEmpty(&(obj->queue1)))      //如果队1为空
	{
		QueuePush(&(obj->queue2), x);    //往队2插入
	}
	else
	{
		QueuePush(&(obj->queue1), x);
	}
}
//移除并返回栈顶元素。
int myStackPop(MyStack* obj) {
	Queue* full = &(obj->queue1);
	Queue* non = &(obj->queue2);
	if (QueueEmpty(&(obj->queue1)))
	{
		full = &(obj->queue2);
		non = &(obj->queue1);
	}
	while ((full->size) > 1)
	{
		QueuePush(non, QueueFront(full));
		QueuePop(full);
	}
	int front = QueueFront(full);
	QueuePop(full);
	
	return front;
}
//返回栈顶元素
int myStackTop(MyStack* obj) {
	if (QueueEmpty(&(obj->queue1)))
	{
		return QueueBack(&(obj->queue2));
	}
	else
	{
		return QueueBack(&(obj->queue1));
	}
}
//如果栈是空的,返回 true ;否则,返回 false 。
bool myStackEmpty(MyStack* obj) {
	return (QueueEmpty(&(obj->queue1)) == 1 && QueueEmpty(&(obj->queue2)) == 1);
}

void myStackFree(MyStack* obj) {
	QueueDestroy(&(obj->queue1));
	QueueDestroy(&(obj->queue2));
	free(obj);
}

三、括号匹配问题

3.1 题目

LeetCode原题链接:. - 力扣(LeetCode)

3.2 思路

        栈先入后出特点恰好与本题括号排序特点一致,即左括号入栈,遇到右括号时将最近的栈顶左括号出栈,进行比较。

        另外:遍历完所有括号后栈必须为空,也就是偶数个。

3.3 C语言题解

3.3.1 栈接口

typedef char STDataType;

typedef struct Stack
{
	STDataType* a;    //数组
	int top;		//栈顶元素
	int capacity;	//数据个数
}ST;
//栈初始化
void STInit(ST* pst)
{
	assert(pst);
	pst->a = NULL;
	pst->capacity = 0;
	//top指向栈顶元素的下一个位置
	pst->top = 0;
	top指向栈顶元素的位置
	//pst->top = -1;
}
//栈销毁
void STDestroy(ST* pst)
{
	assert(pst);
	free(pst->a);
	pst->a = NULL;
	pst->capacity = pst->top = 0;
}
//入栈
void STPush(ST* pst, STDataType x)
{
	assert(pst);
	//扩容
	if (pst->top == pst->capacity)
	{
		int newcapacity = 0;
		if (pst->capacity == 0)
		{
			newcapacity = 4;
		}
		else
		{
			newcapacity = pst->capacity * 2;
		}
		STDataType* temp = (STDataType*)realloc(pst->a, newcapacity * sizeof(STDataType));
		if (temp == NULL)
		{
			perror("malloc");
			exit(1);
		}

		pst->a = temp;
		pst->capacity = newcapacity;
	}
	pst->a[pst->top] = x;
	pst->top++;
}
//出栈
void STPop(ST* pst)
{
	assert(pst);
	assert(pst > 0);
	pst->top--;
}
//返回栈顶元素
STDataType STTop(ST* pst)
{
	assert(pst);
	assert(pst>0);
	return pst->a[pst->top-1];
}
//判空
bool STEmpty(ST* pst)
{
	assert(pst);
	if (pst->top == 0)
	{
		return true;
	}
	else
	{
		return false;
	}
}
//栈的元素个数
int STSize(ST* pst)
{
	assert(pst);
	return pst->top;
}

3.3.2 主函数

bool isValid(char* s) {
    ST st;
    STInit(&st);
    //遍历数组
    while(*s)
    {
        //左括号入栈
        if(*s == '[' || *s == '(' || *s == '{')
        {
            STPush(&st,*s);
        }
        //右括号比较
        else
        {
            //特殊情况判空
            if(STEmpty(&st))
            {
                return false;
            }
            //取出最近的左括号比较
            char top = STTop(&st);
            STPop(&st);
            if((top=='(' && *s != ')')
            || top=='[' && *s != ']'
            || top=='{' && *s != '}')
            {
                return false;
            }
        }
        s++;
    }
    //判空
    bool ret = STEmpty(&st);
    return ret;
    STDestroy(&st);
}

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

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

相关文章

【C++】继承与多态的一些练习题

学习完了继承与多态,当然要来点练习题啦~ 第一题: class Base1 { public: int _b1; }; class Base2 { public: int _b2; }; class Derive : public Base1, public Base2 { public: int _d; }; int main(){ Derive d; Base1* p1 &d; Base2* p2…

Ubuntu22.04怎么安装cuda11.3

环境: WSL2 Ubuntu22.04 问题描述: Ubuntu22.04怎么安装cuda11.3 之前是11.5 解决方案: 在Ubuntu 22.04上安装CUDA 11.3需要一些步骤,因为CUDA 11.3不是为Ubuntu 22.04官方支持的版本。但是,您仍然可以通过以下步…

Linux提权--定时任务--打包配合 SUID(本地)文件权限配置不当(WEB+本地)

免责声明:本文仅做技术交流与学习... 目录 定时任务 打包配合 SUID-本地 原理: 背景: 操作演示: 分析: 实战发现: 定时任务 文件权限配置不当-WEB&本地 操作演示: 定时任务 打包配合 SUID-本地 原理: 提权通过获取计划任务执行文件信息进行提权 . 1、相对路径和…

Spring框架核心:揭秘Java厨房的智能烹饪艺术

前情回顾:Spring框架深度解析:打造你的Java应用梦工厂 六. 实现控制反转 6.1 描述如何在Spring中实现IoC 在Spring Town的厨房里,实现控制反转就像是将食材的采购和准备过程外包给了一个智能系统。这个系统知道每种食材的特性,也…

【数据可视化01】matplotlib实例介绍1

目录 一、引言二、实例介绍1.柱状图1)简单柱状图2)堆叠柱状图 2.线条形式3.折线图(多子图)4.散点图5.水平和垂直线条6.饼状图1)饼状图2)“条形饼”图 一、引言 matplotlib是一个用于绘制数据可视化的Python库。它可以创建各种静态…

杠上Google I/O?OpenAI抢先一天直播,ChatGPT或将具备通话功能

本周的 AI 圈注定热闹非凡。 当地时间 5 月 13 日,OpenAI 将直播发布 ChatGPT 与 GPT-4 的更新。次日,Google I/O 如约而至。不同于 I/O 大会是谷歌的年度盛会,OpenAI 此次的临时发布颇有点抢热度的意思。这对纠缠已久的「老对头」此次又会如…

宝塔助手v1.4.1/手机操控云服务器的神器软件

宝塔助手是以宝塔Linux面板提供的API开发的一款可以随时随地管理服务器的APP。通过这款APP你可以随时随地的查看一台或多台服务器的运行情况,对服务器网站、FTP、数据库、文件进行管理。内置文件编辑器,可以对网站文件进行修改。 链接:https:…

Spring框架深度解析:打造你的Java应用梦工厂

想要在Java企业级应用开发中大展身手?Spring框架的核心容器是你不可或缺的伙伴! 文章目录 一. 引言1.1 介绍Spring框架的重要性1.2 阐述核心容器在Spring框架中的作用1.3 故事开端 二. 背景介绍2.1 描述Spring框架的发展历程2.2 概述Spring框架的主要特点…

计算机Java项目|Springboot房产销售系统

作者主页:编程指南针 作者简介:Java领域优质创作者、CSDN博客专家 、CSDN内容合伙人、掘金特邀作者、阿里云博客专家、51CTO特邀作者、多年架构师设计经验、腾讯课堂常驻讲师 主要内容:Java项目、Python项目、前端项目、人工智能与大数据、简…

数据结构——循环队列(数组)

一、循环队列的定义 二、循环队列图示 三、循环队列使用规则 为解决队满和队空的判断条件相同。 我们 采用 损失一个单元不用的方法 即当循环队列元素的个数是MAXSIZE-1时,就认为队列已满(front指向空的单元) 这样循环队列的队满条件就变…

提升文本到图像模型的空间一致性:SPRIGHT数据集与训练技术的新进展

当前的T2I模型,如Stable Diffusion和DALL-E,虽然在生成高分辨率、逼真图像方面取得了成功,但在空间一致性方面存在不足。这些模型往往无法精确地按照文本提示中描述的空间关系来生成图像。为了解决这一问题,研究人员进行了深入分析…

vivado Virtex UltraScale 配置存储器器件

Virtex UltraScale 配置存储器器件 下表所示闪存器件支持通过 Vivado 软件对 Virtex UltraScale ™ 器件执行擦除、空白检查、编程和验证等配置操作。 本附录中的表格所列赛灵思系列非易失性存储器将不断保持更新 , 并支持通过 Vivado 软件对其中所列非易失…

交易复盘-20240513

仅用于记录当天的市场情况,用于统计交易策略的适用情况,以便程序回测 短线核心:不参与任何级别的调整,采用龙空龙模式 一支股票 10%的时候可以操作, 90%的时间适合空仓等待 双成药业 (1)|[9:30]|[3566万]|0.34 中通客车 (1)|[9:43]|[7678万]|0.15 嘉华股份 (2)|[9:30]|[36…

分类预测 | Matlab实现DBO-CNN-SVM蜣螂算法优化卷积神经网络结合支持向量机多特征分类预测

分类预测 | Matlab实现DBO-CNN-SVM蜣螂算法优化卷积神经网络结合支持向量机多特征分类预测 目录 分类预测 | Matlab实现DBO-CNN-SVM蜣螂算法优化卷积神经网络结合支持向量机多特征分类预测分类效果基本描述程序设计参考资料 分类效果 基本描述 1.Matlab实现DBO-CNN-SVM蜣螂算法…

【软设】常见易错题汇总

目录 计算机系统基础 程序语言基础 数据结构 算法设计与分析 计算机网络与信息安全 软件工程基础 开发方法(结构化与面向对象) 数据库 操作系统 知识产权相关的法律法规 🤯🤯🤯🤯🤯&#x1f9…

2024最新软件测试【测试理论+ 数据库】面试题(内附答案)

一、测试理论 3.1 你们原来项目的测试流程是怎么样的? 我们的测试流程主要有三个阶段:需求了解分析、测试准备、测试执行。 1、需求了解分析阶段 我们的 SE 会把需求文档给我们自己先去了解一到两天这样,之后我们会有一个需求澄清会议, …

外卖系统微信小程序支付

微信小程序支付时序图 其中第9.步骤就是微信小程序前端调用wx.requestPayment

如何写好网评文章?写好了怎么去投稿呢,教程来了

如何写好网评文章,可谓仁者见仁、智者见智。俗话说:“冰冻三尺非一日之寒。”写好网评文章决不是一朝一夕能够练成的,是一个漫长的修炼的过程,需要我们耐得住寂寞、静得下心神。从事网评写作六年多,我有一些心得体会和…

Linux-磁盘管理类实训

一、Linux分区和磁盘操作命令 (1)将系统内所有的分区(文件系统)列出来) (2)将系统中所有特殊文件格式及名称都列出来 (3)将/bin下面的可以用的磁盘容量以易读的容量格式…

Dev-C++的下载和安装教程(超详细图文,小白入门)

Dev-C(或者叫做Dev-Cpp)是Windows环境下的一个轻量级C/C集成开发环境(IDE)。它是一款自由软件,遵守GPL许可协议分发源代码。 Dev-C集合了功能强大的源码编辑器、MingW64/TDM-GCC编译器、GDB调试器和AStyle格式整理器等…