栈和队列——用栈实现队列

news2024/9/23 21:23:24

栈的特点是先进后出,队列的特点是先进先出。根据题中要求,我们应用两个栈实现一个队列。我们可以类比用队列实现栈,我们可以先将元素都插入到栈1中,当我们想要取出元素时,我们可以将栈1中的所有数据依次插入到栈2中,这样我们就可以实现顺序的调转。但是,此时若我们只取出一个数据后我们还想要插入数据,是应该先将栈2中的数据依次挪回栈1再进行插入,还是直接在 栈1中进行插入,直接将栈1设置为专门插入的栈,将栈2设置为专门取出数据的栈。非常明显,我们应该选择第二种方法,这种方法插入取出更加的清晰方便。

1.创建结构体的结构

我们可以将两个栈封存在一个结构体中,这样方便我们去访问两个栈。

MyQueue* myQueueCreate() 
{
    MyQueue*obj=(MyQueue*)malloc(sizeof(MyQueue));
    STInit(&(obj->pushst));
    STInit(&(obj->popst));
    return obj;
}

2.myQueuePush()插入数据

在这个函数中我们可以直接调用栈部分的STPush()函数,直接将数据插入到pushst中。

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

3.myQueuePeek()返回队列的头数据

首先我们需要调用栈部分的STEmpty()函数,判断popst栈中是否有数据,如果没有数据,我们需要再次调用STEmpty()函数用来遍历pushst栈,将pushst栈中的所有数据都依次挪到popst中。如果popst中有数据,我们就可以调用STTop函数得出popst栈中的头数据,并返回他。

int myQueuePeek(MyQueue* obj) 
{
    if(STEmpty(&(obj->popst)))
    {
        while(!STEmpty(&(obj->pushst)))
        {
            int top=STTop(&(obj->pushst));
            STPush(&(obj->popst),top);
            STPop(&(obj->pushst));
        }
    }
    return STTop(&(obj->popst));
}

4.myQueuePop()从队列的开头移除并返回元素

myQueuePop()函数对比myQueuePeek()函数只多了一个移除元素,所以我们可以直接调用myQueuePeek()函数,先将获得的头元素存储,再调用STPop()函数将头元素移除,最后再返回。

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

5.myQueueEmpty()判断队列是否为空

队列为空的条件是pushst栈与popst栈均为空。

bool myQueueEmpty(MyQueue* obj) 
{
    return STEmpty(&(obj->pushst))&&STEmpty(&(obj->popst));
}

6.myQueueFree()销毁队列

想要销毁整体首先需要销毁pushst栈和popst栈,再将结构体释放。

void myQueueFree(MyQueue* obj) 
{
    STDestory(&(obj->pushst));
    STDestory(&(obj->popst));
    free(obj);
}

总结

完整代码如下

#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<assert.h>
//
静态的栈
//#define N 10
//struct Stack
//{
//	int a[N];
//};


//动态的栈
typedef  int STDataType;
typedef struct Stack
{
	STDataType* a;
	int top;
	int capacity;
}ST;

//栈的初始化
void STInit(ST* pst);
//栈的销毁
void STDestory(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->a = NULL;
	//top指向栈顶的下一个节点
	pst->top = 0;
	//top指向栈顶
	//pst->top = -1;
	pst->capacity = 0;
}
//栈的销毁
void STDestory(ST* pst)
{
	assert(pst);
	free(pst->a);
	pst->a = NULL;
	pst->top = 0;
	pst->capacity = 0;
}
//栈的进栈
void STPush(ST* pst, STDataType x)
{
	assert(pst);
	//扩容
	if (pst->top == pst->capacity)
	{
		int newcapacity = pst->capacity == 0 ? 4 : 2 * pst->capacity;
		STDataType* tmp = (STDataType*)realloc(pst->a, newcapacity * sizeof(STDataType));
		if (tmp == NULL)
		{
			perror("realloc fail!");
			exit(1);
		}
		pst->a = tmp;
		pst->capacity = newcapacity;
	}
	pst->a[pst->top] = x;
	pst->top++;
}
//栈的出栈
void STPop(ST* pst)
{
	assert(pst);
	assert(pst->top > 0);
	pst->top--;
}
//栈的取栈顶数据
STDataType STTop(ST* pst)
{
	assert(pst);
	assert(pst->top > 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;
}


typedef struct 
{
    ST pushst;
    ST popst;
} MyQueue;


MyQueue* myQueueCreate() 
{
    MyQueue*obj=(MyQueue*)malloc(sizeof(MyQueue));
    STInit(&(obj->pushst));
    STInit(&(obj->popst));
    return obj;
}

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

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

int myQueuePeek(MyQueue* obj) 
{
    if(STEmpty(&(obj->popst)))
    {
        while(!STEmpty(&(obj->pushst)))
        {
            int top=STTop(&(obj->pushst));
            STPush(&(obj->popst),top);
            STPop(&(obj->pushst));
        }
    }
    return STTop(&(obj->popst));
}

bool myQueueEmpty(MyQueue* obj) 
{
    return STEmpty(&(obj->pushst))&&STEmpty(&(obj->popst));
}

void myQueueFree(MyQueue* obj) 
{
    STDestory(&(obj->pushst));
    STDestory(&(obj->popst));
    free(obj);
}

大家感兴趣的可以自行尝试哦~

. - 力扣(LeetCode)

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

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

相关文章

污点、容忍、不可调度、排水、数据卷

目录 污点taint 污点的格式 1. key:effect 键名&#xff1a;污点类型 2. keyvalue:effect 键名数值&#xff1a;污点类型 污点的类型 1. NoSchedule 2. PreferNoSchedule 3. NoExecute&#xff08;驱逐&#xff09; 设置污点&#xff08;主节点操作&#xff09…

STM32:通过旋转计数器的计数控制舵机旋转的角度

声明&#xff1a;本博客为各模块之间结合的自主研究学习。 目录 一、按键操控舵机旋转&#xff08;单向&#xff09; 1.1、实物图讲解 1.2、代码讲解 1.2.1、PWM.c 具体步骤&#xff1a; 完整代码&#xff1a; 1.2.2、PWM.h 1.2.3、Servo.c && Servo.h 1.2.4、…

ts 类型分类

目录 01 ts 相关指令 02 类型声明空间与变量声明空间 03 类型注解和类型推断 04 类型分类 , 联合类型与交叉类型 05 never类型 any类型 和unknown类型 01 ts 相关指令 全局安装 typescript 模块 npm i -g typescript 安装完成之后 可以将ts文件转换成js文件 tsc xxx.ts…

为什么越来越多的人选择开放式耳机?平价高品质蓝牙耳机推荐

越来越多的人选择开放式耳机&#xff0c;主要是因为其具有多方面的优势&#xff0c;具体如下&#xff1a; 佩戴舒适度高&#xff1a;开放式耳机不入耳&#xff0c;不堵塞耳道&#xff0c;避免了对耳道的压迫和摩擦&#xff0c;长时间佩戴也不易产生闷热感和不适感。例如&#x…

windows安装git

windows安装git 1.通过git官网下载 官网&#xff1a;https://git-scm.com/downloads 2.安装git &#xff08;1&#xff09;找到下载到的文件&#xff0c;进行双击进行安装 &#xff08;2&#xff09;安装使用说明点击Next &#xff08;3&#xff09;选择自己的安装地址&a…

大屏可视化:阿里 DataV 大屏怎么做自适应的?

你好&#xff0c;我是沐爸&#xff0c;欢迎点赞、收藏、评论和关注。 阿里 DataV 大屏是一款功能强大的数据可视化应用搭建工具&#xff0c;由阿里云提供&#xff0c;旨在帮助用户通过图形化的界面轻松搭建专业水准的可视化应用。 下面我们一起看下 DataV 大屏 是如何做自适应…

【嵌入式】uint32值写入到二进制文件中的存储详情

背景 项目预留100字节用于存储参数文件。现在有些数值一个字节表示不够&#xff0c;需要用4个字节。比如数值1144201745&#xff0c;对应的十六进制0x44332211,那么在二进制中存储是怎么样的呢&#xff1f;做个总结 分析 写了一个sample&#xff0c;把uint32_t u32Value1{0x…

【ThreadLocal源码】深入浅出ThreadLocal

【ThreadLocal源码】深入浅出ThreadLocal-CSDN博客

Linux之Prometheus

认识普罗米修斯 1、prometheus介绍 Prometheus(普罗米修斯)是一套开源的监控&报警&时间序列数据库的组合, 由go语言开发。 适合监控容器平台, 因为kubernetes(俗称k8s)的流行带动了prometheus的发展。 PS&#xff1a;文档使用prometheus监控物理服务器。 prometheus的…

数组程序基础知识

为了处理方便&#xff0c;把具有相同类型的变量按有序的形式组织起来。这些同类数据元素的集合称之为数组。数组可分为数值数组、字符数组、指针数组、结构数组等。 01--一维数组 在使用数组前需要先定义&#xff1a; 类型说明符 数组名[常量表达式]&#xff1b; 类型说明符…

因 Mysql root 密码过于简单导致 Mysql 连接失败的解决方法

问题&#xff1a; Access denied for user ‘root’‘192.168.xx.xx’ (using password: YES) 用户“root”“192.168.xx.xx”的访问被拒绝&#xff08;使用密码&#xff1a;YES&#xff09; 解决方法&#xff1a; 1、使用root用户登录mysql&#xff0c;通过下面的命令给ro…

数据管理能力成熟度评估模型DCMM

一、引言 DCMM&#xff08;Data Management Capability Maturity Assessment Model&#xff0c;数据管理能力成熟度评估模型&#xff09;是我国首个数据管理领域国家标准&#xff08;GB/T 36073-2018&#xff09;&#xff0c;由中国国家标准化管理委员会于2018年3月15日发布&am…

FreeRTOS基础入门——FreeRTOS信号量及二值信号量(十三)

个人名片&#xff1a; &#x1f393;作者简介&#xff1a;嵌入式领域优质创作者&#x1f310;个人主页&#xff1a;妄北y &#x1f4de;个人QQ&#xff1a;2061314755 &#x1f48c;个人邮箱&#xff1a;[mailto:2061314755qq.com] &#x1f4f1;个人微信&#xff1a;Vir2025WB…

智联云采 SRM2.0 autologin 身份认证绕过漏洞复现

0x01 产品简介 智联云采是一款针对企业供应链管理难题及智能化转型升级需求而设计的解决方案,针对企业供应链管理难题,及智能化转型升级需求,智联云采依托人工智能、物联网、大数据、云等技术,通过软硬件系统化方案,帮助企业实现供应商关系管理和采购线上化、移动化、智能…

【王树森】RNN模型与NLP应用(4/9):LSTM模型(个人向笔记)

前言 LSTM是对Simple RNN的改进&#xff0c;可以避免梯度消失的问题&#xff0c;能够有更长的记忆力。 LSTM 1. LSTM:Conveyor Belt 过去的信息 C t − 1 C_{t-1} Ct−1​ 通过一个传输带直接输送到下一个状态 C t C_t Ct​&#xff0c;不会发生太大的变化&#xff0c;由此…

激活函数 Sigmod 及其导数

文章目录 1. Sigmod 函数2. 取值3. 图像4. 导数 1. Sigmod 函数 Sigmod 函数是神经网络中最常用的激活函数之一&#xff0c;其形式如下&#xff1a; sigmod ( x ) f ( x ) 1 1 e − x . \text{sigmod}(x) f(x) \frac{1}{1 e^{-x}}. sigmod(x)f(x)1e−x1​. 2. 取值 分…

大模型理论基础

大模型理论基础与学习路径 1.大模型的理论基础&#xff0c;包括深度学习、预训练语言模型和大语言模型。 2.学习大模型开发的路径&#xff0c;包括理论学习、实践操作和项目应用。 3.如何通过理论学习提升上限&#xff0c;为深入学习大模型奠定基础。 GPT模型家族技术发展 1.GP…

数据结构——堆排序

目录 引言 堆排序 1.算法思想 2.算法步骤 3.代码实现 3.1 构建堆 (1)小堆 (2)大堆 3.2 交换与调整 3.3 重复上述过程 4.复杂度分析 5.完整代码 5.1算法实现代码 5.2 示例 6.堆排序的优势 结束语 引言 本篇博客&#xff0c;我们将利用堆结构实现的高效排序算法…

版本控制的核心:Git中的哈希与默克尔树解析

Git是最常用的代码版本控制工具。它帮助我们跟踪代码的更改、管理代码版本&#xff0c;同时保证代码库的完整性和安全性。我们知道 Git 中有一些基本的操作&#xff0c;比如commit、merge、rebase等&#xff0c;但这些操作的底层机制是如何实现的呢&#xff1f;哈希函数和默克尔…

深度学习|模型推理:端到端任务处理

文章目录 引言端到端的能力任务与模型简介手写数字识别数据准备训练集与测试集模型介绍 推理过程前向传播权重参数推理与评估 结语 引言 通过前文「深度学习&#xff5c;感知机&#xff1a;神经网络之始」中 XOR Gate 的示例&#xff0c;我们知道叠加层可以增强感知机的表达能…