【栈和队列OJ题】

news2024/11/17 6:48:36

栈和队列OJ题

文章目录

  • 栈和队列OJ题
    • 1. 用队列实现栈
    • 2. 用栈实现队列
    • 3. 括号匹配问题
    • 4. 循环队列

1. 用队列实现栈

OJ链接:225. 用队列实现栈 - 力扣(LeetCode)

好的,我们一起来看一下题目,题目是这样说的

在这里插入图片描述

思路:使用两个队列,始终保持一个队列为空。当我们需要进行进栈操作时,将数据进入不为空的队列中(若两个都为空,则随便压入一个队列)。当需要进行出栈操作时,将不为空的队列中的数据导入空队列,仅留下一个数据,这时将这个数据返回并且删除即可。判断栈是否为空,即判断两个队列是否同时为空

举个例子,我们将 1,2,3,4 进栈,实际上就是进入其中一个队列 q1

在这里插入图片描述

如果我们要出栈是不是就是按照 4,3,2,1 的顺序,我们将 1,2,3 push 到第二个队列 q2 中,然后在 q1pop 4 就完成出栈的一步操作

在这里插入图片描述

然后我们就可以 push q2 中的 1,2q1 ,这样就可以留一个 3q2 然后 pop q2 就可以完成 3 的出栈操作

在这里插入图片描述

以此循环就可以完成出栈的全部操作

在这里插入图片描述

下面就是代码实现:

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

typedef struct Queue
{
	QNode* head;
	QNode* tail;
	int size;
}Queue;

void QueueInit(Queue* pq);
void QueueDestory(Queue* pq);
void QueuePush(Queue* pq, QDataType x);
void QueuePop(Queue* pq);

QDataType QueueFront(Queue* pq);
QDataType QueueBack(Queue* pq);

bool QueueEmpty(Queue* pq);
int QueueSize(Queue* pq);

void QueueInit(Queue* pq)
{
	assert(pq);
	pq->size = 0;
	pq->head = pq->tail = NULL;
}

void QueueDestory(Queue* pq)
{
	assert(pq);
	QNode* cur = pq->head;
	while (cur)
	{
		QNode* del = cur;
		cur = cur->next;
		free(del);
	}
	pq->size = 0;
	pq->head = pq->tail = NULL;
}

void QueuePush(Queue* pq, QDataType x)
{
	assert(pq);
	QNode* newnode = (QNode*)malloc(sizeof(QNode));
	if (newnode == NULL)
	{
		perror("malloc fail\n");
		exit(-1);
	}
	else
	{
		newnode->data = x;
		newnode->next = NULL;
	}

	if (pq->tail == NULL)
	{
		pq->head = pq->tail = newnode;
	}
	else
	{
		pq->tail->next = newnode;
		pq->tail = newnode;
	}
	pq->size++;
}

bool QueueEmpty(Queue* pq)
{
	return pq->tail == NULL && pq->head == NULL;
}

void QueuePop(Queue* pq)
{
	assert(pq);
	assert(!(QueueEmpty(pq)));

	if (pq->head->next == NULL)
	{
		free(pq->head);
		pq->head = pq->tail = NULL;
	}
	else
	{
		QNode* del = pq->head;
		pq->head = pq->head->next;
		free(del);
		del = NULL;
	}
	pq->size--;
}


QDataType QueueFront(Queue* pq)
{
	assert(pq);
	assert(!(QueueEmpty(pq)));

	return pq->head->data;
}

QDataType QueueBack(Queue* pq)
{
	assert(pq);
	assert(!(QueueEmpty(pq)));

	return pq->tail->data;
}

int QueueSize(Queue* pq)
{
	assert(pq);

	return pq->size;
}


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


MyStack* myStackCreate() {
	MyStack* obj = (MyStack*)malloc(sizeof(MyStack));
	QueueInit(&obj->q1);
	QueueInit(&obj->q2);


	return obj;

}

void myStackPush(MyStack* obj, int x) {
	if (!QueueEmpty(&obj->q1))
	{
		QueuePush(&obj->q1, x);
	}
	else
	{
		QueuePush(&obj->q2, x);
	}

}

int myStackPop(MyStack* obj) {
	Queue* empty = &obj->q1;
	Queue* noEmpty = &obj->q2;
	if (!QueueEmpty(&obj->q1))
	{
		empty = &obj->q2;
		noEmpty = &obj->q1;
	}

	while (QueueSize(noEmpty) > 1)
	{
		QueuePush(empty, QueueFront(noEmpty));
		QueuePop(noEmpty);
	}
	int top = QueueFront(noEmpty);
	QueuePop(noEmpty);

	return top;
}

int myStackTop(MyStack* obj) {
	if (!QueueEmpty(&obj->q1))
	{
		return QueueBack(&obj->q1);
	}
	else
	{
		return QueueBack(&obj->q2);
	}
}

bool myStackEmpty(MyStack* obj) {
	return QueueEmpty(&obj->q1) && QueueEmpty(&obj->q2);

}

void myStackFree(MyStack* obj) {
	QueueDestory(&obj->q1);
	QueueDestory(&obj->q2);
	free(obj);
}

2. 用栈实现队列

OJ链接:232. 用栈实现队列 - 力扣(LeetCode)

好的,我们一起来看一下题目,题目是这样说的

在这里插入图片描述

思路:使用两个栈,第一个栈只用于数据的输入,第二个栈只用于数据的输出。当需要输出数据,但第二个栈为空时,先将第一个栈中的数据一个一个导入到第二个栈,然后第二个栈再输出数据即可

举个例子 ,我想要按照 1,2,3,4 的顺序入队列,那就是要按照 1,2,3,4 的顺序出队列,我们可以先入一个栈,然后将第一个栈中的数据一个一个导入到第二个栈,输入即可

在这里插入图片描述

下面就是代码实现:

typedef int STDataType;
typedef struct Stack
{
	STDataType* _a;
	int _top; // 栈顶
	int _capacity; // 容量
}Stack;

// 初始化栈
void StackInit(Stack* ps);

// 入栈
void StackPush(Stack* ps, STDataType data);

// 出栈
void StackPop(Stack* ps);

// 获取栈顶元素
STDataType StackTop(Stack* ps);

// 获取栈中有效元素个数
int StackSize(Stack* ps);

// 检测栈是否为空,如果为空返回非零结果,如果不为空返回0 
bool StackEmpty(Stack* ps);

// 销毁栈
void StackDestroy(Stack* ps);

bool StackEmpty(Stack* ps)
{
	assert(ps);
	return ps->_top == 0;
}

int StackSize(Stack* ps)
{
	assert(ps);
	return ps->_top;
}

STDataType StackTop(Stack* ps)
{
	assert(ps);
	assert(!StackEmpty(ps));
	return ps->_a[ps->_top - 1];
}

void StackInit(Stack* ps)
{
	assert(ps);

	ps->_a = NULL;
	ps->_capacity = ps->_top = 0;
}

void StackPush(Stack* ps, STDataType data)
{
	assert(ps);
	if (ps->_top == ps->_capacity)
	{
		int newCapacity = ps->_capacity == 0 ? 4 : ps->_capacity * 2;
		STDataType* tmp = (STDataType*)realloc(ps->_a, newCapacity * sizeof(STDataType));
		if (NULL == tmp)
		{
			perror("malloc fail");
			exit(-1);
		}
		ps->_a = tmp;
		ps->_capacity = newCapacity;
	}
	ps->_a[ps->_top] = data;
	ps->_top++;
}

void StackPop(Stack* ps)
{
	assert(ps);
	ps->_top--;
}

void StackDestroy(Stack* ps)
{
	assert(ps);
	free(ps->_a);
	ps->_a = NULL;
	ps->_capacity = ps->_top = 0;
}

typedef struct {
	Stack pushST;
	Stack popST;
} MyQueue;


MyQueue* myQueueCreate() {
	MyQueue* obj = (MyQueue*)malloc(sizeof(MyQueue));
	StackInit(&obj->pushST);
	StackInit(&obj->popST);

	return obj;
}

void myQueuePush(MyQueue* obj, int x) {
	StackPush(&obj->pushST, x);
}

void PushSTToPopST(MyQueue* obj)
{
	if (StackEmpty(&obj->popST))
	{
		while (!StackEmpty(&obj->pushST))
		{
			StackPush(&obj->popST, StackTop(&obj->pushST));
			StackPop(&obj->pushST);
		}
	}
}

int myQueuePop(MyQueue* obj) {
	PushSTToPopST(obj);
	int front = StackTop(&obj->popST);
	StackPop(&obj->popST);
	return front;
}



int myQueuePeek(MyQueue* obj) {
	PushSTToPopST(obj);
	int front = StackTop(&obj->popST);
	return front;
}

bool myQueueEmpty(MyQueue* obj) {
	return StackEmpty(&obj->popST) && StackEmpty(&obj->pushST);

}

void myQueueFree(MyQueue* obj) {
	StackDestroy(&obj->pushST);
	StackDestroy(&obj->popST);
	free(obj);
}

3. 括号匹配问题

OJ链接:20. 有效的括号 - 力扣(LeetCode)

好的,我们一起来看一下题目,题目是这样说的

在这里插入图片描述

思路:该题是栈的典型应用,满足后进先出的规则(后入栈的前括号将优先与先出现的后括号相匹配)。遍历字符串,遇到前括号直接入栈。遇到后括号,判断该后括号与栈顶的前括号是否匹配(若此时栈为空,则字符串无效),若不匹配则字符串无效;若匹配则删除栈顶元素,继续遍历字符串,直到字符串遍历完毕。当字符串遍历完后,检测栈是否为空,若为空,则字符串有效,若不为空,说明有前括号未匹配,字符串无效

typedef char STDataType;
typedef struct Stack
{
	STDataType* _a;
	int _top; // 栈顶
	int _capacity; // 容量
}Stack;

// 初始化栈
void StackInit(Stack* ps);

// 入栈
void StackPush(Stack* ps, STDataType data);

// 出栈
void StackPop(Stack* ps);

// 获取栈顶元素
STDataType StackTop(Stack* ps);

// 获取栈中有效元素个数
int StackSize(Stack* ps);

// 检测栈是否为空,如果为空返回非零结果,如果不为空返回0 
bool StackEmpty(Stack* ps);

// 销毁栈
void StackDestroy(Stack* ps);

bool StackEmpty(Stack* ps)
{
	assert(ps);
	return ps->_top == 0;
}

int StackSize(Stack* ps)
{
	assert(ps);
	return ps->_top;
}

STDataType StackTop(Stack* ps)
{
	assert(ps);
	assert(!StackEmpty(ps));
	return ps->_a[ps->_top - 1];
}

void StackInit(Stack* ps)
{
	assert(ps);

	ps->_a = NULL;
	ps->_capacity = ps->_top = 0;
}

void StackPush(Stack* ps, STDataType data)
{
	assert(ps);
	if (ps->_top == ps->_capacity)
	{
		int newCapacity = ps->_capacity == 0 ? 4 : ps->_capacity * 2;
		STDataType* tmp = (STDataType*)realloc(ps->_a, newCapacity * sizeof(STDataType));
		if (NULL == tmp)
		{
			perror("malloc fail");
			exit(-1);
		}
		ps->_a = tmp;
		ps->_capacity = newCapacity;
	}
	ps->_a[ps->_top] = data;
	ps->_top++;
}

void StackPop(Stack* ps)
{
	assert(ps);
	ps->_top--;
}

void StackDestroy(Stack* ps)
{
	assert(ps);
	free(ps->_a);
	ps->_a = NULL;
	ps->_capacity = ps->_top = 0;
}

bool isValid(char * s){
    Stack st;
    StackInit(&st);

    while(*s)
    {
        if(*s == '(' || *s == '[' || *s == '{')
        {
            StackPush(&st, *s);
        }
        else
        {
            if(StackEmpty(&st))
            {
                StackDestroy(&st);
                return false;
            }
            else
            {
                if((*s == ')' && StackTop(&st) != '(')
                || (*s == ']' && StackTop(&st) != '[')
                || (*s == '}' && StackTop(&st) != '{'))
                {
                    StackDestroy(&st);
                    return false;
                }
                StackPop(&st);
            }
            
        }
        ++s;
    }
    if(!StackEmpty(&st))
    {
        StackDestroy(&st);
        return false;
    }
    return true;
}

4. 循环队列

OJ链接:622. 设计循环队列 - 力扣(LeetCode)

好的,我们一起来看一下题目,题目是这样说的

在这里插入图片描述

思路:在环形队列中,队列为空时,队头队尾指向同一个位置。当队列不为空时,队头指向插入的第一个数据,队尾指向最后一个数据的下一个位置。当tail+1等于front时,说明环形队列已满。
注意:环形队列的队尾不能像常规队列中队尾一样指向最后一个数据,如果这样的话,我们将不能区别环形队列的状态是空还是满,因为此时队头和队尾都指向同一个位置。这就意味着,我们必须留出一个空间,这个空间不能存放数据,这样我们才能很好的区别环形队列的状态是空还是满。
在这里插入图片描述

实现代码如下:

typedef struct {
    int* a;
    int head;
    int tail;
    int size;
} MyCircularQueue;

bool myCircularQueueIsEmpty(MyCircularQueue* obj) {
    return obj->head == obj->tail;
}

bool myCircularQueueIsFull(MyCircularQueue* obj) {
    return (obj->tail + 1) % obj->size == obj->head;
}

MyCircularQueue* myCircularQueueCreate(int k) {
    MyCircularQueue* obj = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));
    obj->a = (int*)malloc(sizeof(int) * (k+1));
    obj->head = obj->tail = 0;
    obj->size = k + 1;
    return obj;
}

bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {
    if(myCircularQueueIsFull(obj))
    {
        return false;
    }
    else
    {
        obj->a[obj->tail] = value;
        obj->tail++;
        obj->tail %= obj->size;
        return true;
    }
}

bool myCircularQueueDeQueue(MyCircularQueue* obj) {
    if(myCircularQueueIsEmpty(obj))
    {
        return false;
    }
    else
    {
        obj->head++;
        obj->head %= obj->size;
        return true;
    }
}

int myCircularQueueFront(MyCircularQueue* obj) {
    if(myCircularQueueIsEmpty(obj))
    {
        return -1;
    }
    else
    {
        return obj->a[obj->head];
    }
}

int myCircularQueueRear(MyCircularQueue* obj) {
    if(myCircularQueueIsEmpty(obj))
    {
        return -1;
    }
    else
    {
        return obj->a[(obj->tail - 1 + obj->size) % obj->size];
    }
}



void myCircularQueueFree(MyCircularQueue* obj) {
    free(obj->a);
    free(obj);
}

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

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

相关文章

IDEA实现热部署

什么是热部署? 热部署(Hot Deployment)是指在应用程序运行过程中,无需停止整个应用程序或重新启动服务器,就能够部署新的代码、资源或配置文件,使其立即生效。这种部署方式有助于提高开发效率和系统的可用性…

这些免费看电视的直播软件,还能免费追剧的app,需要的收藏!

想看中央台和地方卫视的电视直播app有什么呢?支持手机和智能电视的电视直播软件有哪些?今天要跟大家聊聊那些让人眼前一亮的电视直播软件,特别是2024年还能免费看电视直播的神器,让家里的老人也能享受到精彩的电视节目&#xff0c…

无线领夹麦克风哪个牌子好,热门无线麦克风十大排名推荐

​在这个信息爆炸的时代,声音的传递变得愈发重要。无论是直播中的激情解说,还是视频创作中的精彩对白,亦或是远程会议中的清晰发言,一款出色的无线领夹麦克风都能成为你的得力助手。今天,就让我们一同探索多款备受瞩目…

【测开能力提升-fastapi框架】fastapi模版引擎简单使用

1.6 通过模版引擎返回HTM页面 import uvicorn from fastapi import FastAPI, Request from fastapi.templating import Jinja2Templatesapp FastAPI()# 初始化模版引擎存放位置 templates Jinja2Templates(directory"templates")app.get("/") async def…

在Office里面无缝使用任何一家AI大模型,免费的!

昨天一个朋友说他在Word里面,用了一个插件,可以在右侧和AI对话,然后把AI生成的内容载入到左边的文档中。 我当时心理的想法:我这是穿越了吗?这不是我去年2月就实现,然后又扔掉的功能吗? 是的&a…

国漫推荐09

剧场版 1.龙之谷 《龙之谷:破晓奇兵》2014年7月31日 《龙之谷2精灵王座》2016年8月19日 2.星游记 《星游记之风暴法米拉》2017年8月11日 《星游记之风暴法米拉2》2020年3月28日 《星游记之冲出地球》2022-08-14 3.《大鱼海棠》2016年7月8日 4.《哪吒之魔童降世》2…

大数据如何推动工业数字化发展?

随着工业领域的深刻变革,数字化成为了驱动行业前行的核心力量。在这一转变中,大数据扮演着不可或缺的角色。它不仅为企业提供了洞察市场趋势、消费者行为等关键信息的窗口,还为企业优化生产流程、提升产品质量以及推动创新提供了强有力的支持…

前端-Cookie篇

文章目录 一、由来什么是Cookie?特点Cookie的类型 二、原理三、Cookie生成机制客户端设置案例 四、属性五、缺陷最后分享一段自己工作中封装的一些关于cookie的公众方法✒️总结 前端Cookie是Web开发中非常重要的一部分,它是服务器发送到用户浏览器并保存…

分享一款嵌入式开源LED指示灯控制代码框架cotLed

一、工程简介 cotLed是一款轻量级的LED控制软件框架,可以十分方便地控制及自定义LED的各种状态,移植方便,无需修改,只需要在初始化时实现单片机硬件GPIO初始化,同时为框架接口提供GPIO写函数即可。 框架代码工程地址&a…

C++:重定义

派生类和基类的同名成员问题 派生类中再实现一个基类中的方法会怎样 (1)代码实验:派生类和基类中各自实现一个内容不同但函数原型完全相同的方法,会怎么样 (2)结论:基类对象调用的是基类的方法,派生类对象调用执行的是派生类中重…

Vue3 + Echarts堆叠折线图的tooltip不显示问题

问题介绍 使用Echarts在Vue3Vite项目中绘制堆叠折线图的的时候,tooltip总是不显示,经过很长时间的排查和修改,最后发现是在使用上有错误导致的。 错误图片展示 问题原因 由于Vue3底层使用proxy代理创建示例,使用其创建出来的实…

甘蔗基因组--文献精读30

A chromosomal-scale genome assembly of modern cultivated hybrid sugarcane provides insights into origination and evolution 现代栽培杂交甘蔗的染色体级基因组组装提供了起源和进化的洞见,确实甘蔗好几个基因组了~ 摘要 甘蔗是一种具有重要经济和工业价值…

提升论文质量和说服力的高阶技巧:数据驱动

学境思源,一键生成论文初稿: AcademicIdeas - 学境思源AI论文写作 今天分享的内容是“如何利用数据驱动的高阶技巧提升学术论文的深度与说服力”。从高级统计分析到机器学习,再到数据可视化和模型验证,我们将提供了一整套策略&am…

在Linux上搭建服务器之综合实验(web,dns,防火墙,SELinux)

其实验简图如下: 解读: 本实验需要完成4部分内容,web服务器的搭建,主从dns服务器的搭建,防火墙的开启,以及SELinux设置为强制模式。 首先dns主服务器上配置web服务(其中我本机的IP为192.168.5.…

基于Android平台开发,仿头条新闻app

相关视频教程在某站上面(🔍浩宇软件开发) 1. 项目模块功能思维导图 2. 项目涉及到的技术点 数据来源:聚合数据API使用okhttp网络请求框架获取api数据使用gson库解析json数据使用RecyclerViewadapter实现新闻列表使用SQLite数据库实现用户登录&#xff0…

数学建模·Topsis优劣解距离法

Topsis优劣解 一种新的评价方法,特点就是利用原有数据,客观性强。相较于模糊评价和层次评价 更加客观,充分利用原有数据,精确反映方案差距基本原理 离最优解最近,离最劣解越远具体步骤 正向化 代码与原理与熵权法…

防火墙第一次综合实验

DMZ区内的服务器,办公区仅能在办公时间内(9:00-18:00)可以访问,生产区的设备全天可以访问。 办公区设备10.8.2.1不允许访问DMZ区的FTP服务器和HTTP服务器,仅能ping通10.0.3.10 1.先建立拒绝BG到DMZ区的安全策略 2.建立BG到DMZ区的icmp允许 3…

探索 Electron:窗口菜单以及生命周期和对话框讲解

Electron是一个开源的桌面应用程序开发框架,它允许开发者使用Web技术(如 HTML、CSS 和 JavaScript)构建跨平台的桌面应用程序,它的出现极大地简化了桌面应用程序的开发流程,让更多的开发者能够利用已有的 Web 开发技能…

Linux文件编程(标准C库)

目录 一、标准C库打开/创建文件,读写文件,光标移动 二、标准C库写入结构体到文件 三、其他函数补充 1.fputc函数 2.feof函数和fgetc函数 前面讲到的open函数都是基于linux内核的,也就是说在Windows系统上无法运行,移植性比较…

shein测试开发会问些啥?

🏆本文收录于《CSDN问答解惑-》专栏,主要记录项目实战过程中的Bug之前因后果及提供真实有效的解决方案,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&…