用栈模拟实现队列(c语言版)

news2024/11/26 1:26:15

在这里插入图片描述

前言

用"栈实现队列",力扣中一道oj题,可以帮助刚接触"栈"和"队列"的新手更好的理解栈和队列这两种结构.

题目来源于力扣:
题目链接:https://leetcode.cn/problems/implement-queue-using-stacks/
难度:简单

目录

  • 前言
  • 一、队列的各接口:
    • 1.1 类型的声明(MyQueue):
    • 1.2 初始化(myQueueCreate):
    • 1.3 入队列(myQueuePush)
    • 1.4 出队列(myQueuePop)
    • 1.5 队列的判空(myQueueEmpty)
    • 1.6 返回队首元素(myQueuePeek):
    • 1.7 队列的销毁(myQueueFree):
  • 二、总代码:

一、队列的各接口:

1.1 类型的声明(MyQueue):

//模拟队列类型的声明
typedef struct {
    ST stackpush;		//用于模拟队列的 入队操作
    ST stackpop;		//用于模拟队列的 出队操作
} MyQueue;

这里是借助两个栈用于模拟队列.
①:stackpush 模拟队列的入队
②:stackpop 模拟队列的出队

在这里插入图片描述

1.2 初始化(myQueueCreate):

该队列是由两个栈实现的,所以重点关注两个栈的初始化即可.

步骤:

  1. 申请两个栈大小的空间.
    申请失败时判断一下.
  2. 对队列中的两个栈,一次调用他们的初始化函数.(这个千万别漏掉了,牛牛漏掉之后找了好久的问题)
//队列的初始化
MyQueue* myQueueCreate() {
	//给队列开辟空间
    MyQueue* obj=(MyQueue*)malloc(sizeof(MyQueue));
    if(obj==NULL)
    {
        perror("obj malloc fail");
    }
    //一定要记得这里要初始化(别漏掉了哦)
    InitST(&obj->stackpush);
    InitST(&obj->stackpop);
    return obj;
}

1.3 入队列(myQueuePush)

对于入队列的模拟实现很简单,只需要将数据压入栈(模拟入队列:stackpush)即可.

void myQueuePush(MyQueue* obj, int x) {
    assert(obj);
    STPush(&obj->stackpush,x);
}

1.4 出队列(myQueuePop)

函数要求:
将队首元素出队,并且返回刚刚出队的队首元素.

模拟出队相对复杂一些.

  1. 初始状态下或者stackpop(模拟出队的栈)数据出队列到空时,里面是没有数据的,所以先判断stackpop是否有数据.
    有数据:则直接获取stackpop栈顶元素作为队首元素.
    无数据:将数据从模拟入队列栈全部倒过来.(倒数据)
  2. 获取stackpop栈顶元素作为队首元素,使用top变量记录下来.(因为后面要执行出栈操作).
  3. 出栈(模拟出队列),并返回top变量.
int myQueuePop(MyQueue* obj) {
     assert(obj);
     if(STEmpty(&obj->stackpop))//如果栈(stackpop模拟出队列的栈)为空,则向栈(stackpush模拟入队列的栈)要数据
     {
     		//下面循环结束的条件是不为空
          while(!STEmpty(&obj->stackpush))//将数据从模拟入队列栈全部倒过来
        {
            //将栈(stackpush模拟入队)的栈顶元素依次压入栈(stackpop模拟出栈)
            STPush(&obj->stackpop,STTop(&obj->stackpush));
            STPop(&obj->stackpush);
        }
     }
    int top=STTop(&obj->stackpop);//记录用来模拟出队列的栈的栈顶元素;
    STPop(&obj->stackpop);
    return top;
}

1.5 队列的判空(myQueueEmpty)

当两个栈中都没有元素时,则队列为空.

//写法1

bool myQueueEmpty(MyQueue* obj) {
    if(STEmpty(&obj->stackpush)&&STEmpty(&obj->stackpop))//如果都为空,则为空栈
    {
        return true;
    }
    else 
    return false;
}

//写法2.

bool myQueueEmpty(MyQueue* obj) {
    return STEmpty(&obj->stackpush)	&&	STEmpty(&obj->stackpop);
}

1.6 返回队首元素(myQueuePeek):

  1. stackpop不为空时,则队首元素就是stackpop的栈元素.
  2. stackpop为空时,则队首元素就是stackpush的栈元素.
    所以这里也需要倒数据.
int myQueuePeek(MyQueue* obj) {
    assert(obj);
    if(STEmpty(&obj->stackpop))//如果栈(stackpop模拟出队列)为空,则向栈(stackpush模拟入队列)要数据
     {
        while(!STEmpty(&obj->stackpush))
        {
            //将栈(stackpush模拟入队)的栈顶元素依次压入栈(stackpop模拟出队列)
            STPush(&obj->stackpop,STTop(&obj->stackpush));
            STPop(&obj->stackpush);
        }
    }
    int top=STTop(&obj->stackpop);//记录用来模拟出队列的栈的栈顶元素;
    return top;
}

myQueuePop(出队列)函数比较,此函数只是将队首元素返回,并没有指向pop出队操作.
所以我们在实现myQueuePop函数时可以复用一下myQueuePeek函数.

int myQueuePop(MyQueue* obj) {
    int top=myQueuePeek(obj);
    STPop(&obj->stackpop);
    return top;
}

1.7 队列的销毁(myQueueFree):

  1. 释放两个栈初始化开辟的空间
  2. 释放队列申请的空间.
void myQueueFree(MyQueue* obj) {
    STDestory(&obj->stackpush);
    STDestory(&obj->stackpop);
    free(obj);
}

二、总代码:

前面的代码是栈的实现,由于c语言不能像c++那样直接调用库.

typedef  int stacktype;

typedef struct stack//定义栈的类型
{
	stacktype* data;
	int top;
	int capacaity;
}ST;
void InitST(ST* ps);//初始化栈
void STPush(ST* ps, stacktype x);//压栈
void STPop(ST* ps);//出栈
bool STEmpty(ST* ps);//判断是否为空栈
stacktype STTop(ST* ps);//返回栈顶元素
void STDestory(ST* ps);//栈的销毁

void InitST(ST* ps)//初始化栈
{
	assert(ps);
	ps->top = -1;
	ps->capacaity = 4;
	ps->data = (stacktype*)malloc(ps->capacaity * sizeof(stacktype));

}

void STPush(ST* ps, stacktype x)//压栈
{
	assert(ps);
	if (ps->top+1 == ps->capacaity)
	{
		ps->capacaity *= 2;
		ST* tmp = (stacktype*)realloc(ps->data, ps->capacaity * sizeof(stacktype));
		if(tmp == NULL)
		{
			printf("增容失败\n");
		}
		ps->data = tmp;
	}
	ps->top++;
	ps->data[ps->top] = x;
	
}


void STPop(ST* ps)//出栈
{
	assert(ps);
	assert(!STEmpty(ps));
	ps->top--;
}

bool STEmpty(ST* ps)//判断是否为空栈,是空返回真
{
	assert(ps);
	if (ps->top == -1)
	{
		return true;
	}
	return false;
}
stacktype STTop(ST* ps)//返回栈顶元素
{
	assert(ps);
	return ps->data[ps->top];
}
void STDestory(ST* ps)//销毁栈
{
	assert(ps);
	free(ps->data);
	ps->data = NULL;
	ps->top = -1;
	ps->capacaity = 0;
}


//模拟队列类型的声明
typedef struct {
    ST stackpush;
    ST stackpop;
} MyQueue;

//队列的初始化
MyQueue* myQueueCreate() {
    MyQueue* obj=(MyQueue*)malloc(sizeof(MyQueue));
    if(obj==NULL)
    {
        perror("obj malloc fail");
    }
    //一定要记得这里要初始化
    InitST(&obj->stackpush);
    InitST(&obj->stackpop);
    return obj;
}

void myQueuePush(MyQueue* obj, int x) {
    assert(obj);
    STPush(&obj->stackpush,x);
}

int myQueuePop(MyQueue* obj) {
     assert(obj);
     if(STEmpty(&obj->stackpop))//如果栈(stackpop模拟出栈)为空,则向栈(stackpush模拟入栈)要数据
     {
          while(!STEmpty(&obj->stackpush))
        {
            //将栈(stackpush模拟入队)的栈顶元素依次压入栈(stackpop模拟出栈)
            STPush(&obj->stackpop,STTop(&obj->stackpush));
            STPop(&obj->stackpush);
        }
     }
    int top=STTop(&obj->stackpop);//记录用来模拟出队列的栈的栈顶元素;
    STPop(&obj->stackpop);
    return top;
}


bool myQueueEmpty(MyQueue* obj) {
    if(STEmpty(&obj->stackpush)&&STEmpty(&obj->stackpop))//如果都为空,则为空栈
    {
        return true;
    }
    else 
    return false;
    //return STEmpty(&obj->stackpush)&&STEmpty(&obj->stackpop);
}

int myQueuePeek(MyQueue* obj) {
    if(STEmpty(&obj->stackpop))//如果栈(stackpop模拟出栈)为空,则向栈(stackpush模拟入栈)要数据
     {
        while(!STEmpty(&obj->stackpush))
        {
            //将栈(stackpush模拟入队)的栈顶元素依次压入栈(stackpop模拟出栈)
            STPush(&obj->stackpop,STTop(&obj->stackpush));
            STPop(&obj->stackpush);
        }
    }
    int top=STTop(&obj->stackpop);//记录用来模拟出队列的栈的栈顶元素;
    return top;
    //return STTop(&obj->stackpop);
}


void myQueueFree(MyQueue* obj) {
    STDestory(&obj->stackpush);
    STDestory(&obj->stackpop);
    free(obj);
}

运行结果:
在这里插入图片描述

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

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

相关文章

机器学习实战六步法之数据收集方法(四)

要落地一个机器学习的项目,是有章可循的,通过这六个步骤,小白也能搞定机器学习。 看我闪电六连鞭!🤣 数据收集 数据是机器学习的基础,没有数据一切都是空谈!数据集的数据量和数据的质量往往决…

潮牌搭配APP的设计与实现

摘 要:本文开发过程以android为中心,通过数据库进行的数据访问操作。软件以面向对象的思维进行开发和设计,针对于广大群众进行下载使用,对用户提供了时尚的搭配,带领用户形成自己的一套搭配系统,做自己搭配…

C++ std::thread 与Qt qthread多线程混合编程

C与Qt深度融合:高效设计多线程应用框架 1. C与Qt线程的混合使用1.1 C线程与Qt线程的基本概念1.2 线程间的相互依赖关系1.3 设计合理的代码框架 二、深入理解C和Qt线程模型2.1 C线程模型2.2 Qt线程模型2.3 C和Qt线程模型的比较 三、C和Qt线程间的互操作性3.1 std::th…

Web应用技术(第十六周/END)

本次练习基于how2j的教程完成对SpringBoot的初步学习。 初识Springboot 学习导入:1.第一个基于SpringBoot的项目:(1)application.java:该文件中的核心代码: (2)HelloController.java…

浅结代码混淆2

文章目录 SMC 自解码什么是SMC?原理示例动调 mov混淆 SMC 自解码 什么是SMC? 简而言之,就是程序中的部分代码在运行之前被加密成一段数据,不可反编译,通过程序运行后执行相关的解码功能,对加密…

Nginx搭建Https反向代理,使用阿里云免费SSL证书 - Docker

Docker安装Nginx - 需要有域名 没有docker需提前安装docker,不知怎么安装的请自行百度。 1、拉取镜像 docker pull nginx2、去阿里云或者其他云服务提供商申请免费证书,申请到之后下载下来,上传到服务器 # 创建nginx-proxy目录 mkdir ngi…

软考A计划-系统架构师-官方考试指定教程-(13/15)

点击跳转专栏>Unity3D特效百例点击跳转专栏>案例项目实战源码点击跳转专栏>游戏脚本-辅助自动化点击跳转专栏>Android控件全解手册点击跳转专栏>Scratch编程案例 👉关于作者 专注于Android/Unity和各种游戏开发技巧,以及各种资源分享&am…

IP签名档PHP开源版:轻松打造网站个性签名档

今天,我们将为大家介绍一个有趣的IP签名档项目。通过将源代码部署在服务器上,您可以轻松地为自己的社交媒体、论坛等地创建一个独特的签名档,使您的网站更加出彩! 接下来,我们将详细向大家展示如何搭建PHP开源版IP签名…

ASP.NET Core Web API入门之一:创建新项目

ASP.NET Core Web API入门之一:创建新项目 一、引言二、创建新项目三、加入Startup类,并替换Program.cs内容四、编辑Program.cs代码五、修改控制器的路由六、运行项目 一、引言 最近闲着,想着没真正从0-1开发过ASP.NET Core Web API的项目&a…

SpringMVC原理分析 | Hello程序

💗wei_shuo的个人主页 💫wei_shuo的学习社区 🌐Hello World ! SpringMVC Spring MVC 是 Spring 提供的一个基于 MVC 设计模式的轻量级 Web 开发框架,本质上相当于 Servlet; 拥有结构最清晰的 ServletJSPJav…

uni-app APP、html引入html2canvas截图以及截长图

下载安装html2canvas 方式一,https://www.bootcdn.cn/ CDN网站下载html2canvas插件 这里下载后放在测项目目录common下面 页面中引入 方式二、npm方式安装html2canvas 1、npm方式下载 npm i html2canvas2、引入html2canvas import html2canvas from html2can…

linux系统CAN驱动问题分析

在TI sam3354芯片上,使用3.13及4.19版内核,编译CAN驱动,加载启动后,查看有CAN设备,但无法直接使用ifconfig操作CAN设备,以下简单分析下问题。 加载驱动后,查看网络设备: 可以看到有…

分布式项目15 用户注册,单点登陆,用户退出dubbo来实现

用户注册 分析:当用户填写完成注册信息之后,将请求发送给前台服务器.之后前台消费者利用dubbo框架实现RPC调用。之后将用户信息传递给jt-sso服务提供者.之后完成数据的入库操作。 01.页面url分析 02.查看页面JS $.ajax({ type : "POST", url : "/…

煤矿安全防范,DTU为采矿过程提供实时数据支持

在当今快节奏的时代,采矿行业为我们提供了丰富的资源。然而,随着采矿作业的不断扩大和复杂化,我们也面临着一系列潜在的挑战。其中,数据传输和安全问题尤为突出。 想象一下,在一个繁忙的矿山中,海量的数据需…

让软件研发可视化可量化,华为云CodeArts持续加速企业研发转型

导读:软件开发工具从未像今天这样重要。 “没有度量,就没有管理。” (If you can’t measure it, you can’t manage it.) 管理学大师彼得德鲁克的话时刻提醒人们,度量是管理的必要条件。 在高科技领域,研发投入是企业核心竞争力的…

Linux常用命令——grep命令

在线Linux命令查询工具 grep 强大的文本搜索工具 补充说明 grep(global search regular expression(RE) and print out the line,全面搜索正则表达式并把行打印出来)是一种强大的文本搜索工具,它能使用正则表达式搜索文本&…

【MySQL数据库 | 第十二篇】:约束

约束: 在MySQL中,约束是一种限制数据表中列值的规定。保证数据库中的数据正确,有效性和完整性。MySQL中的约束有以下几种: 1. 主键约束(Primary Key Constraint):主键是用于唯一标识表中每行记…

国内强大的智能语言模型AI

​ Yan-英杰的主页 悟已往之不谏 知来者之可追 C程序员,2024届电子信息研究生 目录 前言 环境列表 视频教程 1.飞书设置 2.克隆feishu-chatgpt项目 3.配置config.yaml文件 4.运行feishu-chatgpt项目 5.安装cpolar内网穿透 6.固定公网地址 7.机器人权…

chatgpt赋能python:Python文件目录切换:简单易用的方法

Python文件目录切换:简单易用的方法 Python语言可以轻松地处理文件和目录。使用Python的os库可以方便地操作文件系统。Python在os库中提供了许多可以轻松完成文件和目录操作的函数,其中之一是os.chdir。os.chdir函数用于更改当前的工作目录。 为什么需…

使用阿里云OSS实现图片文件上传

说明&#xff1a;注册用户时&#xff0c;经常会用到上传头像。文件的上传/接收与一般文本数据不同。 一、创建Demo页面 先准备一个Demo页面 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>图片上传…