题集-栈和队列的相互转化

news2024/12/27 9:41:13

 这里,队列的性质是先入先出,但是栈的性质是后入先出。两个队列就可以通过相互捯实现数据的后入先出。

typedef int QDataType;

//这是一个队列结点的结构

typedef struct QueueNode

{

    struct QueueNode* next;

    QDataType data;

}QNode;

//这是一个队列结构

typedef struct Queue

{

    QNode* phead;

    QNode* ptail;

    int size;

}Queue;

//这是通过两个队列搭建的栈结构

typedef struct {

    Queue q1;

    Queue q2;

} MyStack;

//栈的初始化

void QueueInit(Queue* pq)

{

    assert(pq);

    pq->phead = NULL;

    pq->ptail = NULL;

    pq->size = 0;

}

//队列判空

bool QueueEmpty(Queue* pq)

{

    assert(pq);

    return pq->size == 0 ;

}

//栈数据个数

int QueueSize(Queue* pq)

{

    assert(pq);

    return pq->size;

}

//入队

void QueuePush(Queue* pq, QDataType x)

{

    assert(pq);

    QNode* newnode = malloc(sizeof(QNode));

    if (newnode == NULL)

    {

        perror("malloc fail::");

        return;

    }

    newnode->data = x;

    newnode->next = NULL;

    if (pq->ptail == NULL)

    {

        assert(pq->phead == NULL);

        pq->phead = pq->ptail = newnode;

    }

    else

    {

        pq->ptail->next = newnode;

        pq->ptail = newnode;

    }

    pq->size++;

}

//出队列

void QueuePop(Queue* pq)

{

    assert(pq);

    //队列为空

    if(QueueEmpty(pq))

    {

        return NULL;

    }

    //当队列只有一个结点时,ptail会成为野指针,所以要分情况处理

    if (QueueSize(pq)==1)

    {

        free(pq->phead);

        pq->phead = pq->ptail = NULL;

        pq->size = 0;

    }

    else

    {

        QNode* cur = pq->phead;

        pq->phead = pq->phead->next;

        free(cur);

        cur = NULL;

        pq->size--;

    }

}

//获取队首元素

QDataType QueueFront(Queue* pq)

{

    assert(pq);

    if(pq->phead == NULL)

    {

        return NULL;

    }

    return pq->phead->data;

}

//队列的销毁

void QueueDestroy(Queue* pq)

{

    assert(pq);

    if(pq->size == 0) return;

    if(pq->size == 1)

    {

        QueuePop(pq);

    }

    else

    {

    QNode* cur = pq->phead;

    QNode* after = cur->next;

    while (cur)

    {

        free(cur);

        cur = after;

        if (cur)

        {

            after = after->next;

        }

    }

    pq->phead = pq->ptail = NULL;

    pq->size = 0;   

    }

}

//队尾底元素的获取

QDataType QueueBack(Queue* pq)

{

    assert(pq);

    if (QueueEmpty(pq))

    {

        return NULL;

    }

    return pq->ptail->data;

}

//创建栈

MyStack* myStackCreate() {

     MyStack *obj = (MyStack*)malloc(sizeof(MyStack));

     if(obj == NULL)

     {

         perror("malloc fail::");

         return;

     }

        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);

    Queue* pEmptyQ = &obj->q1;

    Queue* pNonEmptyQ = &obj->q2;

    if(!QueueEmpty(&obj->q1))

    {

        pEmptyQ = &obj->q2;

        pNonEmptyQ = &obj->q1;

    }

    while(QueueSize(pNonEmptyQ)>1)

    {

        QueuePush(pEmptyQ,QueueFront(pNonEmptyQ));

        QueuePop(pNonEmptyQ);

    }

    int ret = QueueFront(pNonEmptyQ);

    QueuePop(pNonEmptyQ);

    return ret;

}

//获取栈顶元素

int myStackTop(MyStack* obj) {

    assert(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);

     obj = NULL;

}

用栈实现队列就不能通过相互捯实现了,因为栈换到另一个栈中时,顺序就是相反的顺序,所以此时压栈顺序和出栈顺序就无法判断。

所以此时,我们将两个栈区分清楚,一个叫做“入”栈,专门用来进数据的,一个叫做“出”栈,专门用来出数据的。

 

 此时要求出数据,若“出”栈内没有数据,则从“入”栈中捯过来,然后再出。若出栈中本来就有数据,则直接出栈即可。

要求入数据时,直接放在“入”栈中即可。

typedef int STDataType;

//栈的结点结构

typedef struct Stack

{

    STDataType* a;

    int top;

    int capacity;

}ST;

//初始化栈

void STInit(ST* pst)

{

    assert(pst);//如果指针为空,无法通过动态申请进行初始化,因为参数为一级指针。

    pst->a = NULL;

    pst->top = 0;

    pst->capacity = 0;

}

//栈判空

bool STEmpty(ST* pst)

{

    assert(pst);

    /*if (pst->top == 0)

        return true;

    else return false;

    */

    return pst->top == 0;

}

//销毁栈

void STDestroy(ST* pst)

{

    assert(pst);

    free(pst->a);

    pst->a = NULL;

    pst->capacity = 0;

    pst->top = 0;

}

//压栈

void STPush(ST* pst,STDataType a)

{

    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::");

            return;

        }

        pst->a = tmp;

        pst->capacity = newCapacity;

    } 

    pst->a[pst->top] = a;

    pst->top += 1;

}

//出栈

void STPop(ST* pst)

{

    assert(pst);

    assert(!STEmpty(pst));

    pst->top--;

}

//获取栈顶元素

STDataType STTop(ST* pst)

{

    assert(pst);

    assert(!STEmpty(pst));

    return pst->a[pst->top - 1];

}

//栈元素个数统计

int STSize(ST* pst)

{

    assert(pst);

    return pst->top;

}

//由两个栈构建的队列结构

typedef struct {

    ST pushst;

    ST popst;

} MyQueue;

//队列的创建

MyQueue* myQueueCreate() {

    MyQueue * obj = (MyQueue*)malloc(sizeof(MyQueue)); 

    if(obj == NULL)

    {

        perror("malloc fail::");

        return;

    }

    STInit(&obj->pushst);

    STInit(&obj->popst); 

    return obj;

}

//入队

void myQueuePush(MyQueue* obj, int x) {

     assert(obj);

     STPush(&obj->pushst,x);

}

//出队

int myQueuePop(MyQueue* obj) {

     assert(obj);

     int ret = 0;

     if(!STEmpty(&obj->popst))

     {

         ret = STTop(&obj->popst);

         STPop(&obj->popst);

     }

     else 

     {

         while(STSize(&obj->pushst))

         {

             STPush(&obj->popst,STTop(&obj->pushst));

             STPop(&obj->pushst);

         }

          ret = STTop(&obj->popst);

         STPop(&obj->popst);

     }

     return ret;

}

//获取队首元素

int myQueuePeek(MyQueue* obj) {

    assert(obj);

    if(!STEmpty(&obj->popst))

     {

         return STTop(&obj->popst);

     }

     else 

     {

         while(STSize(&obj->pushst))

         {

             STPush(&obj->popst,STTop(&obj->pushst));

             STPop(&obj->pushst);

         }

         return STTop(&obj->popst);

     }

}

//队列判空

bool myQueueEmpty(MyQueue* obj) {

    assert(obj);

    return (STEmpty(&obj->pushst)&&(STEmpty(&obj->popst)));

}

//释放队列空间

void myQueueFree(MyQueue* obj) {

     STDestroy(&obj->popst);

     STDestroy(&obj->pushst);

     free(obj);

     obj=NULL;

}

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

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

相关文章

C++之工厂模式

目录 一、为什么要使用工厂模式 优点 缺点 二、简单工厂(Simple Factory) 好处: 不足: 三、工厂方法: 好处: 不足: 四、抽象工厂(Abstract Factory) 一、为什…

RWA 成下一轮加密大叙事,PoseiSwap 的价值正在凸显

PoseiSwap是Nautilus Chain上的首个DEX,在Nautilus Chain模块化开发的支持下,PoseiSwap能够以更具延展性的方式来构建应用,并能够为交易者提供极佳的交易体验。基于Nautilus Chain支持下的Zk-Rollup方案,PoseiSwap构建了基于零知识…

文心一言 VS 讯飞星火 VS chatgpt (45)-- 算法导论6.1 3题

三、证明:在最大堆的任一子树中,该子树所包含的最大元素在该子树的根结点上。 文心一言: 在最大堆中,根结点是整个堆中最大元素的孩子,因此它包含的最大元素是在该子树的根结点上。 我们可以通过递归的方式证明任意子树中的最大…

C++11 线程库—互斥锁

前言 多线程因其调度的随机性和时间片分配,如果没有限制的访问临界资源,会导致出现无法预测的结果,也无法达到预期。 所以,访问临界区,需要是原子性的,在一个线程完成之前,不能有其他线程访问&…

找bug号召

我的博客是为了完成这个找 bug 号召: https://bbs.csdn.net/topics/614134877。 文章目录 测试场景之三: 选择你的身份 测试场景之三: 选择你的身份 同样在个人中心的最下面,你可以看到身份选择的界面。 注意,你要把鼠…

Python元组、集合、字典(超详细举例、讲解和区分)

总有一天你要一个人在暗夜中,向那座桥走过去 文章目录 一、元组 字符串、元组、列表的总结 二、集合 1.定义空集合 2.创建集合 (1)直接创建 (2)set函数 3.列表、元组、字符串、字典的去重 4.向集合中添加元素…

python---js逆向------再接再励------案例

作者前言 这是我的gitee仓库:https://gitee.com/qin-laoda/python-exercises 有兴趣的小可爱们可以点进去看看, 目录 常见的js加密算法 微信公众号的简单案例 ________________________________ 鉴于有一些小可爱对于js逆向的理解还有一些不解,下面我会再进一步的介绍js…

【计算机视觉 | 目标检测】arxiv 计算机视觉关于目标检测的学术速递(6月 23 日论文合集)

文章目录 一、检测相关(4篇)1.1 Targeted collapse regularized autoencoder for anomaly detection: black hole at the center1.2 RXFOOD: Plug-in RGB-X Fusion for Object of Interest Detection1.3 Toward Automated Detection of Microbleeds with Anatomical Scale Loca…

axios简单使用

axios简单使用 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" content"widthdevice-wid…

【杂谈】过往时期2-嵌入式求学故事线简忆

前一篇文章 过往时期 - 欢迎来到 Staok - 瞰百易 (gitee.io)。 在我兴趣广泛的过去&#xff0c;关于嵌入式方面的经历啊&#xff0c;讲一条这个的故事线。 小学&#xff0c;电子积木&#xff0c;灯泡&#xff0c;电机&#xff0c;上电发光、风扇旋转&#xff0c;风扇转的快了还…

AnyLogic仿真软件 8.8.2 Crack

AnyLogic仿真软件用于以下行业&#xff1a; 供应链 制造业 运输 仓库运营 铁路物流 矿业 石油和天然气 港口及码头 更多行业 为什么要进行仿真建模&#xff1f; 无风险环境 仿真建模提供了一种安全的方法来测试和探索不同的“假设”场景。在做出现实世界的改变之前做出正确的决…

第10章 隐式转换

第10章 隐式转换 package chapter10object Test01_TestImplicit {def main(args: Array[String]): Unit {val richInt new MyRichInt(12)println(richInt.myMax(15))// 1. 隐式函数implicit def convert(num: Int): MyRichInt new MyRichInt(num)println(12.myMax(15))// 2.…

登录校验原理过程和统一拦截技术(Cookie、Sesstion 和JWT令牌)

一、登录校验 问题&#xff1a;在未登录情况下&#xff0c;我们也可以直接访问部门管理、员工管理等功能。由于浏览器与web服务器中的数据交互是通过HTTP协议的&#xff0c;而HTTP协议是无状态的–即每个页面中的请求和响应都是独立的&#xff0c;没有状态存在。所以我们需要进…

【数据库】关系型数据库与非关系型数据库解析

【数据库】关系型数据库与非关系型数据库解析 文章目录 【数据库】关系型数据库与非关系型数据库解析1. 介绍2. 关系型数据库3. 非关系型数据库4. 区别4.1 数据存储方式不同4.2 扩展方式不同4.3 对事务性的支持不同4.4 总结 参考 1. 介绍 一个通俗易懂的比喻&#xff1a;关系型…

Xpath介绍以及语法

Xpath介绍 XML路径语言&#xff08;XML Path Language&#xff09;&#xff0c;它是一种用来确定XML文档中某部分位置的语言。 XPath基于XML的树状结构&#xff0c;提供在数据结构树中找寻节点的能力。 起初XPath的提出的初衷是将其作为一个通用的、介于XPointer与XSL间的语法模…

第8章 模式匹配

第8章 模式匹配 基本概念和用法 模式守卫 package chapter08object Test01_PatternMatchBase {def main(args: Array[String]): Unit {// 1. 基本定义语法val x 5val y x match {case 1 > "one"case 2 > "two"case 3 > "three"ca…

《Reinforcement Learning: An Introduction》第6章笔记

Chapter 6 Temporal-Difference Learning If one had to identify one idea as central and novel to reinforcement learning, it would undoubtedly be temporal-difference (TD) learning. 时序差分学习&#xff08;temporal-difference (TD) learning&#xff09;组合了Mon…

PID控制算法 – 0、PID原理

1、开局一张图 很多地方都觉得PID的控制结构示意图是这样的&#xff1a; 2、目标值&#xff08;Setpoint&#xff09;、输入值&#xff08;Input&#xff09;、误差&#xff08;Error&#xff09; 其实把上图那个输入改为目标值&#xff08;Setpoint&#xff09;更合适&#…

canvas详解08-基本动画

由于我们是用 JavaScript 去操控 canvas 对象,这样要实现一些交互动画也是相当容易的。在本章中,我们将看看如何做一些基本的动画。 可能最大的限制就是图像一旦绘制出来,它就是一直保持那样了。如果需要移动它,我们不得不对所有东西(包括之前的)进行重绘。重绘是相当费…

CoreMark 跑个分:OrangePi5 RK3588S

一、 Orange Pi 5 简介 Orange Pi 5 采用了瑞芯微 RK3588S 新一代八核 64 位处理器&#xff0c;具体为四核A76四核A55&#xff0c;采用了 8nm 工艺设计&#xff0c;主频最高可达 2.4GHz&#xff0c;集成 ARM Mali-G610 MP4 GPU&#xff0c;内嵌高性能 3D 和 2D 图像加速模块&am…