【leetcode】232. 用栈实现队列

news2025/1/20 14:58:36

1.使用两个栈结构构建队列

我们需要自定义栈及其相关操作

栈结构遵循后入先出的原则,队列结构遵循先入先出的原则

构建具有两个栈结构的队列,栈pushST用于数据的插入,栈popST用于数据的删除

为栈结构动态开辟空间并初始化栈结构

//定义一个具有两个栈的队列结构
typedef struct {
    ST pushST;//插入数据栈
    ST popST;//删除数据栈

} MyQueue;


MyQueue* myQueueCreate() {
    MyQueue* obj = (MyQueue*)malloc(sizeof(MyQueue));
		//内存开辟失败
		if(obj == NULL)
		{
			perror("malloc fail");
			exit(-1);
		}
		//开辟成功,初始化
		else
		{
			StackInit(&obj->pushST);
			StackInit(&obj->popST);
		}
			return obj;

}

2.入队操作

模拟入队操作,即将所有元素压栈即可,这里我们将数据压入栈pushST

void myQueuePush(MyQueue* obj, int x) {
		//把数据压入插入数据专用栈
		StackPush(&obj->pushST,x);

}
3.出队操作

模拟队列的出队操作:队列出队访问的是队头数据,即先进入结构的数据,在栈中即为栈底元素,要访问栈底元素,需要后入的元素先出栈才能访问

以上操作后,栈pushST和栈popST的结构如下:

此时栈pushST的栈顶元素即模拟队列的队头元素,存储并出栈即可

以上操作进行完之后需要将栈popST中的数据还原回pushST吗?

分析:不需要将栈popST中的数据还原回pushST,当进行下一次模拟出队操作时,只需要访问栈popST的栈顶元素即可,栈popST栈顶的元素为先进入栈pushST的元素;若popST为空,则重新进行上述步骤即可

📖Note:

栈结构遵循先进先出的原则,当我们把pushST栈中的元素依次出栈再入栈popST时,元素入栈popST顺序刚好与之前的入栈pushST的先后顺序相反,从而使这些元素出栈popST时栈顶刚好是先入栈pushST的元素

//将pushST中元素外依次倒入popST
void pushSTPopST(MyQueue* obj)
{
		if(StackEmpty(&obj->popST))
		{
			while(!StackEmpty(&obj->pushST))
			{
				StackPush(&obj->popST,StackTop(&obj->pushST));
				StackPop(&obj->pushST);
			}
		}
}

int myQueuePop(MyQueue* obj) {
		pushSTPopST(obj);

		int front = StackTop(&obj->popST);
		StackPop(&obj->popST);
		return front;
}

4.访问队列的开头元素

队列的开头元素即pushST栈中的栈底元素,将栈pushST中的所有元素入到栈popST中,再访问栈popST的栈顶元素即可

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

5.判断队列是否为空

队列结构为两个栈结构构成的,当两个栈都为空的时候,队列即为空

bool myQueueEmpty(MyQueue* obj) {

    return StackEmpty(&obj->pushST) && StackEmpty(&obj->popST);
}

6.空间释放

构建的队列结构动态开辟了空间,所有操作结束后,需要释放空间,否则会造成内存泄漏

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

参考代码如下:

//栈的相关定义
typedef int STDataType;
//动态内存开辟
typedef struct Stack
{
	STDataType* a;
	int top;
	int capacity;
}ST;

//初始化
void StackInit(ST* ps);
//销毁
void StackDestroy(ST* ps);
//插入数据
void StackPush(ST* ps, STDataType x);
//删除数据
void StackPop(ST* ps);
//访问栈顶数据
STDataType StackTop(ST* ps);
//判断是否为空栈
bool StackEmpty(ST* ps);
//访问栈中数据
void StackPopAll(ST* ps);
//计算栈的大小
int StackSize(ST* ps);

//初始化
void StackInit(ST* ps)
{
	assert(ps);
	ps->a = NULL;
	ps->top = ps->capacity = 0;
}
//销毁
void StackDestroy(ST* ps)
{
	assert(ps);
	free(ps->a);
	ps->a = NULL;
	ps->top = ps->capacity = 0;
}
//插入数据
void StackPush(ST* ps, STDataType x)
{
	assert(ps);
	//扩容
	if (ps->top == ps->capacity)
	{
		int newcapacity = ps->capacity == 0 ? 4 : (ps->capacity) * 2;
		STDataType* tmp = realloc(ps->a, newcapacity * sizeof(STDataType));
		//扩容失败
		if (tmp == NULL)
		{
			perror("realloc fail");
			exit(-1);
		}
		//扩容成功
		ps->a = tmp;
		ps->capacity = newcapacity;
	}
	//插入数据
	ps->a[ps->top] = x;
	ps->top++;
}
//删除数据
void StackPop(ST* ps)
{
	assert(ps);
	//栈不为空才能删除
	assert(!StackEmpty(ps));
	--ps->top;
}
//访问栈顶数据
STDataType StackTop(ST* ps)
{
	assert(ps);
	//栈不为空才能访问
	assert(!StackEmpty(ps));
	return ps->a[ps->top - 1];
}
//判断是否为空栈
bool StackEmpty(ST* ps)
{
	assert(ps);
	return ps->top == 0;
}
//计算栈的大小
int StackSize(ST* ps) 
{
	assert(ps);
	return ps->top;
}

//定义一个具有两个栈的队列结构
typedef struct {
    ST pushST;//插入数据栈
    ST popST;//删除数据栈

} MyQueue;


MyQueue* myQueueCreate() {
    MyQueue* obj = (MyQueue*)malloc(sizeof(MyQueue));
		//内存开辟失败
		if(obj == NULL)
		{
			perror("malloc fail");
			exit(-1);
		}
		//开辟成功,初始化
		else
		{
			StackInit(&obj->pushST);
			StackInit(&obj->popST);
		}
			return obj;

}

void myQueuePush(MyQueue* obj, int x) {
		//把数据压入插入数据专用栈
		StackPush(&obj->pushST,x);

}
//将pushST中元素外依次倒入popST
void pushSTPopST(MyQueue* obj)
{
		if(StackEmpty(&obj->popST))
		{
			while(!StackEmpty(&obj->pushST))
			{
				StackPush(&obj->popST,StackTop(&obj->pushST));
				StackPop(&obj->pushST);
			}
		}
}

int myQueuePop(MyQueue* obj) {
		pushSTPopST(obj);

		int front = StackTop(&obj->popST);
		StackPop(&obj->popST);
		return front;
}

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

bool myQueueEmpty(MyQueue* obj) {

    return StackEmpty(&obj->pushST) && StackEmpty(&obj->popST);
}

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

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

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

相关文章

object获取的两种方式/Object.keys使用/解构赋值

object获取的两种方式: data() {return {abj: {aa: {A: 1}}}},created() {console.log(this.abj.aa) //第一种console.log(this.abj["aa"]) //第二种}, Object.keys使用/解构赋值: return {footList: [],abj: {aa: {A: 12,AA:22},bb: {…

macOS系统安装python3

官网下载 官网:https://www.python.org/ 选择最新版本下载 双击安装包 点击继续 点击继续 点击同意 点击安装 终端执行 python3 --version

九、Linux下,如何在命令行进入文本编辑页面?

1、文本编辑基础 说到文本编辑页面,那就必须提到vi和vim,两者都是Linux系统中,常用的文本编辑器 2、三种工作模式 3、使用方法 (1)在进入Linux系统,在输入vim text.txt之后,会进入文本编辑中&…

【JS】for 与 forEach 分别如何跳出循环

for 循环 在 for 循环中&#xff0c;退出循环的两种方式&#xff1a; break; 退出整个循环continue; 退出当次循环 let array [1, 2, 3, 4, 5, 6, 7, 8, 9]; for (let i 0; i < array.length; i) {if (array[i] 6) {// break; // 退出整改循环&#xff0c;continue; /…

高并发内存池(centralcache)[2]

Central cache threadcache是每个线程独享&#xff0c;而centralcache是多线程共享&#xff0c;需要加锁&#xff08;桶锁&#xff09;一个桶一个锁 解决外碎片问题&#xff1a;内碎片&#xff1a;申请大小超过实际大小&#xff1b;外碎片&#xff1a;空间碎片不连续&#x…

能耗分析在医院节能中的管理

摘要&#xff1a;医院作为特殊的公共建筑&#xff0c;能耗较大且逐年攀升&#xff0c;具有较大的节能潜力。结合天津市某医院的用能概况、智慧管理平台的建设和使用&#xff0c;对大量能耗数据进行了研究和分析&#xff0c;通过将能源管理系统、数据分析与节能工作相结合&#…

在Visual Studio中使用 //TODO注释

在软件开发过程中&#xff0c;注释是非常重要的&#xff0c;它们可以帮助开发者理解代码的功能和逻辑。​有时候我们只需要标记出一些临时性的、需要后续处理的代码片段。这时候&#xff0c;我们可以使用一种特殊的注释&#xff1a;//TODO注释。 //TODO注释是一种轻量级的注释…

【项目实践】基于LSTM的一维数据扩展与预测

基于LSTM的一维数据拟合扩展 一、引(fei)言(hua) 我在做Sri Lanka生态系统服务价值计算时&#xff0c;中间遇到了一点小问题。从世界粮农组织(FAO)上获得Sri Lanka主要农作物产量和价格数据时&#xff0c;其中的主要作物Sorghum仅有2001-2006年的数据&#xff0c;而Millet只有…

2011年下半年 软件设计师 上午试卷2

博主介绍&#xff1a;✌全网粉丝3W&#xff0c;全栈开发工程师&#xff0c;从事多年软件开发&#xff0c;在大厂呆过。持有软件中级、六级等证书。可提供微服务项目搭建与毕业项目实战&#xff0c;博主也曾写过优秀论文&#xff0c;查重率极低&#xff0c;在这方面有丰富的经验…

新宝马M5谍照曝光,侵略感十足,将与奥迪、梅赛德斯-AMG正面竞争

报道称&#xff0c;宝马即将推出全新一代M5&#xff0c;该车的谍照最近再次曝光。早先&#xff0c;宝马 M5 Touring 旅行汽车的赛道测试图片已经在网络上流传开来&#xff0c;预计该车将与奥迪的RS6 Avant和梅赛德斯-AMG E63 Estate展开正面竞争。 从最新曝光的照片来看&#x…

区块链碎碎念

现在的区块链早已过了跑马圈地的时代&#xff0c;现在还按照以前承接项目的方式做区块链只能是越来越艰难。经过几年的技术沉淀&#xff0c;做区块链项目的公司都已经没落的七七八八了。 区块链不是一个能够快速显现盈利能力的行业&#xff0c;相反这个行业目前的模式还是处于…

【Datawhale暑期实践第三期】用户新增预测挑战赛

文章目录 赛题背景赛事任务赛题数据集评价指标赛题思路Baseline导入包并读取数据特征工程决策树模型训练和预测保存预测文件 赛题名称&#xff1a;用户新增预测挑战赛 赛题类型&#xff1a;数据挖掘、二分类 赛题链接&#x1f447;&#xff1a; https://challenge.xfyun.cn/top…

[Machine Learning] decision tree 决策树

&#xff08;为了节约时间&#xff0c;后面关于机器学习和有关内容哦就是用中文进行书写了&#xff0c;如果有需要的话&#xff0c;我在目前手头项目交工以后&#xff0c;用英文重写一遍&#xff09; &#xff08;祝&#xff0c;本文同时用于比赛学习笔记和机器学习基础课程&a…

【学习FreeRTOS】第12章——FreeRTOS时间管理

1.FreeRTOS系统时钟节拍 FreeRTOS的系统时钟节拍计数器是全局变量xTickCount&#xff0c;一般来源于系统的SysTick。在STM32F1中&#xff0c;SysTick的时钟源是72MHz/89MHz&#xff0c;如下代码&#xff0c;RELOAD 9MHz/1000-1 8999&#xff0c;所以时钟节拍是1ms。 portNV…

事物有哪些特性 ?MySQL 如何保证事物的四大特性 ?

目录 1.事物有哪些特性 2. MySQL 如何保证事物的四大特性 3. 事物的隔离级别 1.事物有哪些特性 1.1 何为事物 &#xff1f; 事物就是把一件事情的多个步骤&#xff0c;多个操作&#xff0c;打包成一个步骤&#xff0c;一个操作。其中任意一个步骤执行失败&#xff0c;都会进…

隧道广播平面波扬声器的应用

隧道广播平面波扬声器是一款高清晰定向扬声器&#xff0c;采用稀土永磁磁性材料与声波相控阵技术&#xff0c;有效的解决了声音定向问题。是远距离定向声波发射装置是一种革命性的技术&#xff0c;它具有大功、率高清晰、远距离传声特点&#xff0c;可以将声音信息清晰地传输到…

【数据结构】 链表简介与单链表的实现

文章目录 ArrayList的缺陷链表链表的概念及结构链表的分类单向或者双向带头或者不带头循环或者非循环 单链表的实现创建单链表遍历链表得到单链表的长度查找是否包含关键字头插法尾插法任意位置插入删除第一次出现关键字为key的节点删除所有值为key的节点回收链表 总结 ArrayLi…

Aurora 8B/10B

目录 1. Overview2. Feature List2. Block Diagram3. Ports Description3.1. User InterfaceFraming InterfaceStreaming InterfaceUser Flow Control&#xff08;UFC&#xff09;Native Flow Control&#xff08;NFC&#xff09; 3.2. Status and Control Ports3.3. Transceiv…

基于python+django+mysql的校园影院售票系统(可做计算机毕设)

开发柚子校园影院&#xff0c;不仅可以改善用户查看信息难的局面&#xff0c;还可以提高管理效率&#xff0c;同时也可以增强系统的竞争力。利用柚子校园影院的可以有效地提高系统的人事的效率和信息化水平&#xff0c;快速了解信息更新及服务的进度。这既可以确保系统服务的品…