《数据结构初阶》用队列实现栈&&用栈实现队列的细致解析

这篇具有很好参考价值的文章主要介绍了《数据结构初阶》用队列实现栈&&用栈实现队列的细致解析。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

纵有千古、横有八方

《数据结构初阶》用队列实现栈&&用栈实现队列的细致解析

目录

一、⏱️本章重点

二、⏱️队列实现栈

三、⏱️栈实现队列

四、⏱️解题思路总结


一、⏱️本章重点

  1. 用两个队列实现栈
  2. 用两个栈实现队列
  3. 解题思路总结

二、⏱️队列实现栈

《数据结构初阶》用队列实现栈&&用栈实现队列的细致解析

 我们有两个队列:

《数据结构初阶》用队列实现栈&&用栈实现队列的细致解析

 入栈数据1、 2、 3

可以将数据入队列至队列一或者队列二。

《数据结构初阶》用队列实现栈&&用栈实现队列的细致解析

如何出栈?

 但出栈要先出1,怎么办?

第一步

将队列一出队n-1个至队列二。

《数据结构初阶》用队列实现栈&&用栈实现队列的细致解析

 第二步

pop队列一的最后一个元素。

《数据结构初阶》用队列实现栈&&用栈实现队列的细致解析

 接下来怎么入栈呢?

将元素入队至不为空的队列。

怎么判断栈空?

队列一和队列二都为空的情况下,栈就是空的。

如何取栈顶元素?

取不为空的队列尾部元素。

总的来说就是,入栈时就将数据插入不为空的队列,出栈就将不为空的队列的前n-1个数据导入至另一个队列,然后pop最后一个元素。

代码实现:

 首先我们要构造一个栈。

这个栈要包含两个队列

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

在此之前我们要准备好队列的一般接口:

我这里的队列是用单链表来构建的,具体接口实现可以看我之前的文章。

typedef int QTypeData;
typedef struct QueueNode
{
	struct QueueNode* next;
	QTypeData val;
}QN;

void QueueInit(Queue* pq)//初始化队列
size_t QueueSize(Queue* pq)//求队列元素个数
int QueueBack(Queue* pq)//取队列尾部数据
void QueuePush(Queue* pq, QTypeData x)//将x入队
void QueuePop(Queue* pq)//出队
void QueueDestroy(Queue* pq)//结束队列

我们要用队列实现栈的接口:

💯第一个接口:创建并初始化栈

接口一:MyStack* myStackCreate()

这样做行吗?

MyStack* myStackCreate()
{

    MyStack ms;
    QueueInit(&ms.q1);
    QueueInit(&ms.q2);
    return ms;
}

很显然,返回局部变量的地址是不明智的,因为在函数返回时,ms开辟的空间会重新交给操作系统,再次访问就是非法操作。

因此我们需要将ms开辟在堆区。

参考代码:

💯第二个接口:入栈

接口二:void myStackPush(MyStack* obj, int x)

入栈简单:只要将数据插入到不为空的队列即可。

入栈之前我们需要判断队列满吗?

不需要,因为我的队列是用单链表实现的,可以无限链接下去。

如果两个队列都为空,该插入到哪个队列呢?

我们可以这样做,如果队列1为空,就插入到队列2,如果不为空,就插入到队列1.

参考代码:

💯第三个接口:出栈

接口三:int myStackPop(MyStack* obj) //出栈

再次回顾一下我们是如何出栈的。

首先我们有两个队列

初始状态它们都是空的

队列一:空

队列二:空

入栈1、2、3、4

执行后

队列一:空

队列二:1、2、3、4

出队列只能先出1,如何出4呢?

把1、2、3先出给队列一

执行后

队列一:1、2、3

队列二:4

然后将4用变量记录并出队,最后返回记录4的变量。

执行后

队列一:1、2、3

队列二:空。

出队三板斧

第一步:即将不为空的队列的前n-1个元素入至为空的队列。

第二步:将剩下的1个元素用变量记录,然后将最后一个元素出队。

第三步返回用变量记录的元素。

需要注意的是:如果栈为空,那么就返回false。

参考代码:

💯第四个接口:取栈顶元素

接口四:int myStackTop(MyStack* obj) //取栈顶元素

取栈顶元素之前我们需要保证栈不为空

如果栈为空,返回false。

取栈顶元素,即取不为空的队列的队尾元素。

参考代码:

💯第五个接口:判断栈是否为空

接口五:bool myStackEmpty(MyStack* obj) //判断栈是否为空

如果两个队列都是空的那么该栈就是空的。

这里多提一下,栈的元素个数怎么求?

栈的元素个数就是那个不为空队列的元素个数。

参考代码:

💯第六个接口:销毁栈

接口六:void myStackFree(MyStack* obj) //结束栈

参考代码:

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

最后需要注意的是:调用栈为空的接口时,要先声明!!

三、⏱️栈实现队列

《数据结构初阶》用队列实现栈&&用栈实现队列的细致解析

 第一次入队

《数据结构初阶》用队列实现栈&&用栈实现队列的细致解析

将数据1出队操作

将栈1的数据全导入栈2

《数据结构初阶》用队列实现栈&&用栈实现队列的细致解析

然后栈2进行出栈操作

《数据结构初阶》用队列实现栈&&用栈实现队列的细致解析

 再次入队5、6、7

直接将5、6、7入栈至栈1

《数据结构初阶》用队列实现栈&&用栈实现队列的细致解析

 实际我们的对头和队尾是这样的

《数据结构初阶》用队列实现栈&&用栈实现队列的细致解析文章来源地址https://www.toymoban.com/news/detail-424713.html

 总的来说:

用两个栈实现一个队列,就得把一个栈专门入队,另一个栈用作出队。这里实现的时候我们用栈1做入队栈,栈2做出队栈。

也就是说,只要将数据入队,直接放入栈1.

出队就直接出栈2的数据,如果栈2为空,这将栈1的数据全部导入栈2.

队列的结构体

typedef struct 
{
    ST st1;
    ST st2;
} MyQueue;

我们需要准备的栈

typedef int STDataType;
typedef struct Stack
{
	STDataType* data;
	int top;
	int capacity;
}ST;

这里我用的是动态数组实现的栈

需要提前准备栈的接口:

void STInit(ST* p)
void STDestroy(ST* p)
void STPush(ST* p,STDataType x)
void STPop(ST* p)
bool STEmpty(ST* p)
int STSize(ST* p)
STDataType STRear(ST* p)

💯第一个接口:创建并初始化队列

MyQueue* myQueueCreate() 

同样的,需要把队列开辟在堆区,同时对栈1和栈2进行初始化。

参考代码:

MyQueue* myQueueCreate() 
{
    MyQueue* mq=(MyQueue*)malloc(sizeof(MyQueue));
    assert(mq);
    STInit(&mq->st1);
    STInit(&mq->st2);
    return mq;
}

💯第二个接口:入队

void myQueuePush(MyQueue* obj, int x) 

我们把栈1做入队栈,栈2做出队栈。

也就是说,只要将数据入队,直接放入栈1.

出队就直接出栈2的数据,如果栈2为空,这将栈1的数据全部导入栈2.

参考代码:

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

💯第三个接口:出队

int myQueuePop(MyQueue* obj) 

先要判断队列是否为空,如果队列为空则返回false。

其次如果栈2为空,就将栈1的数据全导入栈2.

参考代码:

int myQueuePop(MyQueue* obj) 
{
    if(myQueueEmpty(obj))
    {
        return false;
    }
    if(STEmpty(&obj->st2))
    {
        int n=STSize(&obj->st1);
        while(n--)
        {
            STPush(&obj->st2,STRear(&obj->st1));
            STPop(&obj->st1);
        }
    }
    int ret=STRear(&obj->st2);
    STPop(&obj->st2);
    return ret;
}

💯第四个接口:取队头元素

int myQueuePeek(MyQueue* obj)

取队头元素之前,要判断队列是否为空,如果为空,则返回false

队头元素即栈2的尾部元素。

《数据结构初阶》用队列实现栈&&用栈实现队列的细致解析

但如果栈2为空呢?

那队列的队头元素就是栈1的头部元素。

参考代码:

int myQueuePeek(MyQueue* obj) 
{
    if(myQueueEmpty(obj))
    {
        return false;
    }
    if(STEmpty(&obj->st2))
    {
        return STFront(&obj->st1);
    }
    return STRear(&obj->st2);
}

💯第五个接口:判断队列是否为空

bool myQueueEmpty(MyQueue* obj)

队列为空,需要栈1和栈2都为空。

参考代码:

bool myQueueEmpty(MyQueue* obj) 
{
    return STEmpty(&obj->st1) && STEmpty(&obj->st2);
}

💯第六个接口:销毁队列

void myQueueFree(MyQueue* obj) 

参考代码:

void myQueueFree(MyQueue* obj) 
{
    STDestroy(&obj->st1);
    STDestroy(&obj->st2);
    free(obj);
}

注意:当使用判断队列是否为空的接口时,注意是否在之前声明过了。

四、⏱️解题思路总结

1.用队列实现栈:

我们需要用两个队列实现栈

栈类是于尾插尾删

队列是尾插头删

第一次入栈:两个队列都为空,随便插入一个队列都可

第一次出栈:出栈要出的是尾部数据,队列只能出头部数据,这是队列不能直接实现的。

那么需要将不为空的队列前n-1个数据导入至为空的队列,再将最后一个元素pop掉。

队列一:1、2、3、4

队列二:空

那么导入后

队列一:4

队列二:1、2、3

最后pop最后一个元素

队列一:空

队列二:1、2、3、4

再次尾插:尾插至不为空的队列即可。

2.用栈实现队列

我们有两个栈要求实现队列的一般接口

栈一:空

栈二:空

第一次入队:入栈至栈一或者栈二都可,这里选择栈一。

假设入队1、2、3、4

栈一:1、2、3、4

栈二:空

出队:要先出1

将栈一全部导入栈二

栈一:空

栈二:4、3、2、1

之后入队就插入至栈一

出队就pop栈二。

《数据结构初阶》用队列实现栈&&用栈实现队列的细致解析

到了这里,关于《数据结构初阶》用队列实现栈&&用栈实现队列的细致解析的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【LeetCode】数据结构题解(12)[用栈实现队列]

    所属专栏:玩转数据结构题型❤️ 🚀 博主首页:初阳785❤️ 🚀 代码托管:chuyang785❤️ 🚀 感谢大家的支持,您的点赞和关注是对我最大的支持!!!❤️ 🚀 博主也会更加的努力,创作出更优质的博文!!❤️ 🚀 关注我,关注我,关注我,重要的事情说三遍!!!!!

    2024年02月13日
    浏览(42)
  • 【算法与数据结构】232、LeetCode用栈实现队列

    所有的LeetCode题解索引,可以看这篇文章——【算法和数据结构】LeetCode题解。    思路分析 :这道题要求我们用栈模拟队列(工作上一定没人这么搞)。程序当中,push函数很好解决,直接将元素push进输入栈当中。pop函数需要实现队列先进先出的操作,而栈是先进后出。只

    2024年02月12日
    浏览(43)
  • 【数据结构】队列篇| 超清晰图解和详解:循环队列模拟、用栈实现队列、用队列实现栈

    博主简介: 努力学习的22级计算机科学与技术本科生一枚🌸 博主主页: @是瑶瑶子啦 每日一言🌼: 每一个不曾起舞的日子,都是对生命的辜负。——尼采 🔗622. 设计循环队列 👧🏻 思路: 🍊数据结构: 使用数组为数据结构,且采用牺牲一个空间的方法来包装判空和判满的

    2024年02月11日
    浏览(39)
  • 数据结构刷题训练:用栈实现队列(力扣OJ)

    目录 前言 1. 题目:用栈实现队列 2. 思路 3. 分析  3.1 定义 “ 队列 ”  3.2 创建队列 3.3 入队  3.4 队头数据  3.5 出队  3.6 判空和销毁 4.题解 总结         栈和队列是数据结构中的两个重要概念,它们在算法和程序设计中都有着广泛的应用。本文将带你深入了解如何使用

    2024年02月13日
    浏览(39)
  • 速学数据结构 | 我不允许还有人不会用栈实现队列!

    🎬 鸽芷咕 :个人主页  🔥个人专栏 :《Linux深造日志》《C++干货基地》 ⛺️生活的理想,就是为了理想的生活!    🌈 hello! 各位铁铁们大家好啊,不知道大家对栈和队列的学习都学过了吧?那么用栈来实现队列你会做嘛?    ⛳️ 栈和队列我们前面说了都是一种特殊

    2024年02月02日
    浏览(41)
  • 【数据结构】 队列详解!庖丁解牛般细致讲解!

    🎥 屿小夏 : 个人主页 🔥个人专栏 : 数据结构解析 🌄 莫道桑榆晚,为霞尚满天! 什么是队列?队列有什么样的特性?它的应用场景有哪些? 本文会对队列这种数据结构进行进行庖丁解牛般的讲解,让你彻底学会数据结构! 队列是一种常见的数据结构,它按照先进先出

    2024年02月06日
    浏览(46)
  • 初阶数据结构之队列的实现(六)

    👻作者简介:M malloc,致力于成为嵌入式大牛的男人 👻专栏简介:本文收录于 初阶数据结构 ,本专栏主要内容讲述了初阶的数据结构,如顺序表,链表,栈,队列等等,专为小白打造的文章专栏。 👻相关专栏推荐:LeetCode刷题集,C语言每日一题。 本章我将详细的讲解关于

    2024年02月08日
    浏览(44)
  • 初阶数据结构(六)队列的介绍与实现

    💓博主csdn个人主页:小小unicorn💓 ⏩专栏分类:C++ 🚚代码仓库:小小unicorn的学习足迹🚚 🌹🌹🌹关注我带你学习编程知识 队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表。队列遵守先进先出FIFO(First In First Out)的原则。 入队列:队列的

    2024年02月11日
    浏览(40)
  • 数据结构初阶(用C语言实现简单数据结构)--栈和队列

    ✨✨欢迎来到T_X_Parallel的博客!!       🛰️博客主页:T_X_Parallel       🛰️专栏 : 数据结构初阶       🛰️欢迎关注:👍点赞🙌收藏✍️留言 这小猫真好看 言归正传,通过上篇有关顺序表和链表的博客,可以了解到线性表的一些大致特征,这篇博

    2024年02月08日
    浏览(42)
  • 【数据结构初阶】六、线性表中的队列(C语言 -- 链式结构实现队列)

    ========================================================================= 相关代码gitee自取 : C语言学习日记: 加油努力 (gitee.com)  ========================================================================= 接上期 : 【数据结构初阶】五、线性表中的栈(C语言 -- 顺序表实现栈)_高高的胖子的博客-CSDN博客  

    2024年02月08日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包