速学数据结构 | 用队列实现栈你都被难住了?那是你没掌握好技巧

news2024/11/27 12:48:16

在这里插入图片描述

🎬 鸽芷咕:个人主页

 🔥个人专栏:《Linux深造日志》《C++干货基地》

⛺️生活的理想,就是为了理想的生活!

📋 前言

  🌈hello! 各位铁铁们大家好啊,栈和队列我们都学过了那么试试用队列实现栈你会嘛?。
  ⛳️本篇文章就来给大家来篇如何用队列来实现栈的全部解析让你彻底拿捏队列。
  📚本期文章收录在《数据结构&算法》,大家有兴趣可以看看呐
  ⛺️ 欢迎铁汁们 ✔️ 点赞 👍 收藏 ⭐留言 📝!

文章目录

  • 📋 前言
  • 一、队列实现栈的具体功能
  • 二、队列实现栈的具体思路
    • 2.1 实现栈区的具体方法
    • 2.1 栈区的插入思路
    • 2.1 栈区的删除思路
  • 三、队列实现栈(具体代码)
    • 3.1 队列的准备
    • 3.2 栈区的初始化
    • 3.3 栈区的插入
    • 3.4 栈区的删除
    • 3.5 栈区的判空
    • 3.6 获取栈区的头元素
    • 3.7 栈区的销毁
  • 三、全部实现代码
  • 📝全篇总结

一、队列实现栈的具体功能

在这里插入图片描述

二、队列实现栈的具体思路

我们先来总结一下队列的特点 先进先出 ,队列的特点 是 后进先出

  • 具体我们可以看一下下图来快速了解

在这里插入图片描述

  • 队列的特点是先进先出
  • 我们要实现栈的功能是后进先出

2.1 实现栈区的具体方法

我们是不是可以具体这样想,队列既然是先进先出,栈是后进先出,的意识就是我们需要每次获取的栈区数据是队列的最后一个:

  • ⁉️那可以不可以这样呢?
  • 开辟俩个队列空间,每次让其中一个为空
  • 另外一个不为空,这样就可以解决删除的问题了。

在这里插入图片描述

2.1 栈区的插入思路

这思路就很简单如果使用俩个指针来管理队列,那么插入就非常简单了,只需要考虑俩种情况:

  • 第一种当然是俩个栈区都为空的情况,还没开始插数据
  • 第二种就是已经插入数据了,那么插入的时候直接往不为空的栈区插入就好了。

2.1 栈区的删除思路

大家看如何我们使用俩个指针来管理队列,来实现栈的话那么来删除就非常简单了为什么这样说呢?

  • 既然一个队列永远为空,一个不为空
  • 那么删除的时候直接把不为空的队列插入到为空的队列
  • 留下最后一个元素用来删除就好了

在这里插入图片描述

三、队列实现栈(具体代码)

好了以上就是队列实现栈的核心思想了,只要核心思想掌握了,那么其他就是小菜了。下面我们就来快速实现一下吧:

3.1 队列的准备

这里是队列的实现代码,由于C语言库里面并没有队列这个数据结构我们就只能手动实现了:

  • 如果有想了解队列的可以看这篇文章:
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>

typedef int QueDataType;

typedef struct QueueType {
	QueDataType data;
	struct QueueType* next;
}QueueNode;

typedef struct Queue {
	struct QueueType* head;
	struct QueueType* tail;
	int size;
}Que;

//初始化队列
void QueueInit(Que* ps);
//销毁队列
void QueueDestroy(Que* ps);
//插入数据
void QueuePush(Que* ps, QueDataType x);
//删除数据
void QueuePop(Que* ps);
//获取头数据
QueDataType QueueFront(Que* ps);
//获取尾数据
QueDataType QueueBack(Que* ps);
//获取队列长度
int QueueSize(Que* ps);
//判断是否为空
bool QueueEmpty(Que* ps);


//初始化队列
void QueueInit(Que* ps)
{
	assert(ps);

	ps->head = NULL;
	ps->tail = NULL;
	ps->size = 0;
}

//销毁队列
void QueueDestroy(Que* ps)
{
	assert(ps);
	QueueNode* cur = ps->head;
	while (cur)
	{
		QueueNode* next = cur->next;
		free(cur);
		cur = next;
	}

	ps->head = ps->tail = NULL;
	ps->size = 0;
}

//插入数据
void QueuePush(Que* ps, QueDataType x)
{
	assert(ps);
	QueueNode* newnode = (QueueNode*)malloc(sizeof(QueueNode));
	if (newnode == NULL)
	{
		perror("malloc fail");
		exit(-1);
	}

	newnode->data = x;
	newnode->next = NULL;

	if (ps->head == NULL)
	{
		ps->head = ps->tail = newnode;
	}
	else
	{
		ps->tail->next = newnode;
		ps->tail = newnode;
	}

	ps->size++;
}


//删除数据
void QueuePop(Que* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));

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

	pq->size--;
}

//获取头数据
QueDataType QueueFront(Que* ps)
{
	assert(ps);
	assert(!QueueEmpty(ps));

	return ps->head->data;
}

//获取尾数据
QueDataType QueueBack(Que* ps)
{
	assert(ps);
	assert(!QueueEmpty(ps));


	return ps->tail->data;
}

//获取队列长度
int QueueSize(Que* ps)
{
	assert(ps);
	
	return ps->size;
}

//判断是否为空
bool QueueEmpty(Que* ps)
{
	assert(ps);

	return ps->head == NULL;
}

3.2 栈区的初始化

好了思路我们理清楚了接下来就是看看具体队列实现栈的代码到底如何实现:

  • 前面我们说过了使用俩个指针来管理队列就好了
  • 然后进行 malloc 申请空间就好了

📚 代码演示:

typedef struct {
    Que q1;
    Que q2;

} MyStack;


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

    return obj;
}

3.3 栈区的插入

插入的话我们思想已经都知道,下面就是考验你的代码能力了:

  • 如果俩个队列为空随便插入一个就好了
  • 否则就插入另一个队列

📚 代码演示:

void myStackPush(MyStack* obj, int x) {
    assert(obj);

    if(!QueueEmpty(&obj->q1))
    {
        QueuePush(&obj->q1,x);
    }
    else
    {
        QueuePush(&obj->q2,x);
    }

}

3.4 栈区的删除

删除的思想很简单,每次搬运一下队列就好了:

  • 这里使用了一个非常实用的判定方法大家可以去看看
  • 先假设一个为空一个不为空
  • 然后如果错了就换过来

📚 代码演示:

int myStackPop(MyStack* obj) {
    assert(obj);

    Que* empty = &obj->q1;
    Que* noempty = &obj->q2;
    if(!QueueEmpty(empty))
    {
        empty = &obj->q2;
        noempty = &obj->q1;
    }

    while(QueueSize(noempty) > 1)
    {
        QueuePush(empty, QueueFront(noempty));
        QueuePop(noempty);
    }

    int top = QueueFront(noempty);
    QueuePop(noempty);
    
    return top;
}

3.5 栈区的判空

这个就简单了只要栈中管理俩个队列的的都为空那当然都没有数据了:

  • QueueEmpty(&obj->q1) && QueueEmpty(&obj->q2)

📚 代码演示:

bool myStackEmpty(MyStack* obj) {

    return QueueEmpty(&obj->q1) && QueueEmpty(&obj->q2);
}

3.6 获取栈区的头元素

既然我们使用了俩个队列来实现栈,并且只有一个队列存放数据。

  • 那么只需要看哪个队列不为取出队尾数据就好了。

📚 代码演示:

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

3.7 栈区的销毁

老样子了,先把栈区里面的 malloc 里面的空间释放了,然后再释放栈就好了。

📚 代码演示:

void myStackFree(MyStack* obj) {  
    QueueDestroy(&obj->q1);
    QueueDestroy(&obj->q2);
    

    free(obj);

}

三、全部实现代码

📚 代码演示:

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>

typedef int QueDataType;

typedef struct QueueType {
	QueDataType data;
	struct QueueType* next;
}QueueNode;

typedef struct Queue {
	struct QueueType* head;
	struct QueueType* tail;
	int size;
}Que;

//初始化队列
void QueueInit(Que* ps);
//销毁队列
void QueueDestroy(Que* ps);
//插入数据
void QueuePush(Que* ps, QueDataType x);
//删除数据
void QueuePop(Que* ps);
//获取头数据
QueDataType QueueFront(Que* ps);
//获取尾数据
QueDataType QueueBack(Que* ps);
//获取队列长度
int QueueSize(Que* ps);
//判断是否为空
bool QueueEmpty(Que* ps);


//初始化队列
void QueueInit(Que* ps)
{
	assert(ps);

	ps->head = NULL;
	ps->tail = NULL;
	ps->size = 0;
}

//销毁队列
void QueueDestroy(Que* ps)
{
	assert(ps);
	QueueNode* cur = ps->head;
	while (cur)
	{
		QueueNode* next = cur->next;
		free(cur);
		cur = next;
	}

	ps->head = ps->tail = NULL;
	ps->size = 0;
}

//插入数据
void QueuePush(Que* ps, QueDataType x)
{
	assert(ps);
	QueueNode* newnode = (QueueNode*)malloc(sizeof(QueueNode));
	if (newnode == NULL)
	{
		perror("malloc fail");
		exit(-1);
	}

	newnode->data = x;
	newnode->next = NULL;

	if (ps->head == NULL)
	{
		ps->head = ps->tail = newnode;
	}
	else
	{
		ps->tail->next = newnode;
		ps->tail = newnode;
	}

	ps->size++;
}


//删除数据
void QueuePop(Que* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));

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

	pq->size--;
}

//获取头数据
QueDataType QueueFront(Que* ps)
{
	assert(ps);
	assert(!QueueEmpty(ps));

	return ps->head->data;
}

//获取尾数据
QueDataType QueueBack(Que* ps)
{
	assert(ps);
	assert(!QueueEmpty(ps));


	return ps->tail->data;
}

//获取队列长度
int QueueSize(Que* ps)
{
	assert(ps);
	
	return ps->size;
}

//判断是否为空
bool QueueEmpty(Que* ps)
{
	assert(ps);

	return ps->head == NULL;
}

typedef struct {
    Que q1;
    Que q2;

} MyStack;


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

    return obj;
}

void myStackPush(MyStack* obj, int x) {
    assert(obj);

    if(!QueueEmpty(&obj->q1))
    {
        QueuePush(&obj->q1,x);
    }
    else
    {
        QueuePush(&obj->q2,x);
    }

}

int myStackPop(MyStack* obj) {
    assert(obj);

    Que* empty = &obj->q1;
    Que* noempty = &obj->q2;
    if(!QueueEmpty(empty))
    {
        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) {  
    QueueDestroy(&obj->q1);
    QueueDestroy(&obj->q2);
    

    free(obj);

}

/**
 * Your MyStack struct will be instantiated and called as such:
 * MyStack* obj = myStackCreate();
 * myStackPush(obj, x);
 
 * int param_2 = myStackPop(obj);
 
 * int param_3 = myStackTop(obj);
 
 * bool param_4 = myStackEmpty(obj);
 
 * myStackFree(obj);
*/

📝全篇总结

☁️ 好了以上就是队列实现栈的全部细节与过程来,大家不要忘记练习哦!
看到这里了还不给博主扣个:
⛳️ 点赞☀️收藏 ⭐️ 关注

💛 💙 💜 ❤️ 💚💓 💗 💕 💞 💘 💖
拜托拜托这个真的很重要!
你们的点赞就是博主更新最大的动力!
有问题可以评论或者私信呢秒回哦。
在这里插入图片描述

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

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

相关文章

CleanMyMac X4.15试用版许可证

如果你拥有苹果电脑&#xff0c;那么就非常有必要在Mac上安装CleanMyMac&#xff0c;不是只有Windows才会产生垃圾&#xff0c;Mac同样的也会&#xff0c;定期清理Mac垃圾&#xff0c;可以释放磁盘空间。 CleanMyMac X 是一款流行的 Mac 清理工具&#xff0c;具有许多功能&…

【PyTorch实战演练】AlexNet网络模型构建并使用Cifar10数据集进行批量训练(附代码)

目录 0. 前言 1. Cifar10数据集 2. AlexNet网络模型 2.1 AlexNet的网络结构 2.2 激活函数ReLu 2.3 Dropout方法 2.4 数据增强 3. 使用GPU加速进行批量训练 4. 网络模型构建 5. 训练过程 6. 完整代码 0. 前言 按照国际惯例&#xff0c;首先声明&#xff1a;本文只是我…

点云学习记录

(50 封私信 / 79 条消息) 三维点云数据的语义分割方法除了pointnet还有哪些呢&#xff1f; - 知乎 (zhihu.com) (50 封私信 / 80 条消息) 点云特征提取 - 搜索结果 - 知乎 (zhihu.com) (50 封私信 / 80 条消息) 点云提取特征如何进行关键点匹配? - 知乎 (zhihu.com) 1、图像…

ZZ308 物联网应用与服务赛题第A套

2023年全国职业院校技能大赛 中职组 物联网应用与服务 任 务 书 &#xff08;A卷&#xff09; 赛位号&#xff1a;______________ 竞赛须知 一、注意事项 1.检查硬件设备、电脑设备是否正常。检查竞赛所需的各项设备、软件和竞赛材料等&#xff1b; 2.竞赛任务中所使用的…

SwiftUI 代码调试之都是“变心”惹的祸

0. 概览 这是一段非常简单的 SwiftUI 代码&#xff0c;我们将 Item 数组传递到子视图并在子视图中对其进行修改&#xff0c;修改的结果会立即在主视图中反映出来。 不幸的是&#xff0c;当我们修改 Item 名称时却发现不能连续输入&#xff1a;每次敲一个字符键盘都会立即收起并…

2023-11-05 LeetCode每日一题(重复的DNA序列)

2023-11-05每日一题 一、题目编号 187. 重复的DNA序列二、题目链接 点击跳转到题目位置 三、题目描述 DNA序列 由一系列核苷酸组成&#xff0c;缩写为 ‘A’, ‘C’, ‘G’ 和 ‘T’.。 例如&#xff0c;“ACGAATTCCG” 是一个 **DNA序列 **。 在研究 DNA 时&#xff0c…

网络运维Day04

文章目录 实验环境grep命令使用vim文本编辑器命令模式基本操作光标跳转复制、粘贴、删除 末行模式基本操作存盘、退出、文件操作开关设置 Linux命令补充man帮助历史命令du命令date指令 归档及压缩制作压缩包释放压缩包zip压缩包制作zip格式压缩包(打包)释放zip格式压缩包(解包)…

从Spring说起

一. Spring是什么 在前面的博文中,我们学会了SpringMVC的使用,可以完成一些基本功能的开发了,但是铁子们肯定有很多问题,下面来从Spring开始介绍,第一个问题,什么是Spring? Spring是包含了众多工具方法的IOC容器. Spring有两个核心思想--IOC和AOP,本章先来讲解IOC...... 1.1…

高中信息技术学业水平考试模拟题库

单选 水仙花数的定义&#xff1a;指一个 3 位数&#xff0c;它的每个位上的数字的 3次幂之和等于它本身 ①数据&#xff1a;数据是信息和知识的来源。 ②信息&#xff1a;信息是经过加工的数据。 ③知识&#xff1a;知识是人们在改造世界的实践活动中所获得的可用于指导实践的…

docker---dockerfile相关知识

第 3 章 Docker 高级实践 在这一部分我们主要来介绍一些Docker的高级内容&#xff1a; Dockerfile 和 Docker compose 3.1 Dockerfile Dockerfile我们从下面的几个方面来介绍&#xff1a; Dockerfile简介 Dockerfile快速入门 Dockerfile详解 Dockerfile简单 实践 3.1.1 Docke…

利用Path工具在Plant Simulation快速进行agv路径规划

之前小伙伴在问B站上有个AGV遇到障碍动态调整路线的视频是如何实现的。波哥花了点时间实现了一下&#xff0c;说一下思路&#xff1a; 1. 在Plant Simulation里面实现任意一个路径规划算法(A*、D*、Dijkstra)。 2. 监控agv移动过程中道路情况的变化 3. 判断是否需要重新规划路线…

【Python语言】序列(列表,元组,字符串)切片操作

目录 序列切片操作 1.1 对list进行切片&#xff0c;从1开始&#xff0c;到5结束&#xff0c;步长为1 [ 1 : 5 ] 1.2 对tuple进行切片&#xff0c;从头开始&#xff0c;到最后结束&#xff0c;步长为1 [ : ] 1.3 对str进行切片&#xff0c;从头开始&#xff0c;到最…

什么是DITA?从百度的回答说起

▲ 搜索“大龙谈智能内容”关注GongZongHao▲ 什么是DITA? 把这个问题输入百度&#xff0c;获得以下回答&#xff1a; DITA 是“Darwin Information Typing Architecture”&#xff08;达尔文信息类型化体系结构&#xff09;的缩写&#xff0c;它是IBM 公司为OASIS 所支持…

一看就懂,把“百度”搬回家

引言 生活中&#xff0c;我们经常使用“百度”查询资料&#xff0c;访问“购物网站”购买商品&#xff0c;下面&#xff0c;我们搭建实验环境&#xff0c;将“百度”和“京东”搬回家。 前提 了解什么是计算机网络&#xff0c;参考&#xff1a;一看就懂&#xff0c;原来这就…

新版onenet平台安全鉴权的确定与使用

根据onenet官方更新的文档&#xff1a;平台提供开放的API接口&#xff0c;用户可以通过HTTP/HTTPS调用&#xff0c;进行设备管理&#xff0c;数据查询&#xff0c;设备命令交互等操作&#xff0c;在API的基础上&#xff0c;根据自己的个性化需求搭建上层应用。 为提高API访问安…

vue3后台管理系统之数据大屏适配解决方案

1&#xff1a;scale 方式 我们整个大屏的尺寸设置和设计图一样&#xff0c;只是通过css的scale放大缩小属性&#xff0c;来控制实际展示的大小。 通过监听浏览器窗口的大小&#xff0c;来改变scale的比例&#xff0c;从而实现数据大屏适配。&#xff08;百度、网易等大数据适配…

运维知识点-MySQL从小白到入土

MySQL从小白到入土 mysql 服务器安装windows mysql 服务漏洞复现-mysql jdbc反序列化-权限绕过 mysql 服务器安装 https://dev.mysql.com/downloads/mysql/https://www.cnblogs.com/xiaostudy/p/12262804.html 点餐小程序腾讯云服务器安装mysql8 windows mysql 服务 net sta…

YOLOv8改进:IOU创新篇 | 引入MPDIou、WIoU、SIoU、EIoU、α-IoU,在不同场景实现涨点

🚀🚀🚀本文改进:引入MPDIou、WIoU、SIoU、EIoU、α-IoU,适配各个YOLO 🚀🚀🚀MPDIou、WIoU、SIoU、EIoU、α-IoU在各个场景都能够有效涨点 🚀🚀🚀YOLOv8改进专栏:http://t.csdnimg.cn/hGhVK 学姐带你学习YOLOv8,从入门到创新,轻轻松松搞定科研; 1. …

(附源码)基于SSM 车险事故自助理赔小程序-计算机毕设 84607

车险事故自助理赔小程序 摘要 随着我国经济迅速发展&#xff0c;人们对手机的需求越来越大&#xff0c;各种手机软件也都在被广泛应用&#xff0c;但是对于手机进行数据信息管理&#xff0c;对于手机的各种软件也是备受用户的喜爱&#xff0c;车险事故自助理赔小程序被用户普遍…

基于YOLOv8的烟雾检测:自研模块 BSAM注意力 PK CBAM注意力,提升一个多点

&#x1f4a1;&#x1f4a1;&#x1f4a1;本文全网首发独家改进&#xff1a;提出新颖的注意力BSAM&#xff08;BiLevel Spatial Attention Module&#xff09;&#xff0c;创新度极佳&#xff0c;适合科研创新&#xff0c;效果秒杀CBAM&#xff0c;Channel AttentionSpartial …