【初阶数据结构题目】16.用队列实现栈

news2024/9/22 11:40:06

用队列实现栈

点击链接答题

思路:

出栈:找不为空的队列,将size-1个数据导入到另一个队列中。

入栈:往不为空队列里面插入数据

取栈顶元素:

例如:

两个队列:

  1. Q1:1 2 3
  2. Q2:NULL

如果是栈的话:

  1. 插入1 2 3
  2. 出栈一次
  3. 插入4
  4. 全部出栈

得到:3 4 2 1


Q1里面的1 2出栈到Q2,把3取出来,此时Q1NULL

取出了3

Q2里面插入4,此时Q21 2 4

Q2里面的1 2出栈到Q1,此时Q24,把4取出来,此时Q2NULL

取出了3 4

Q1里面的1出栈到Q2,把2取出来 ,此时Q1NULL

取出了3 4 2

Q2里面的1取出来

取出了3 4 2 1

代码:

//定义队列结构
typedef int QDataType;

typedef struct QueueNode {
	QDataType data;
	struct QueueNode* next;
}QueueNode;

typedef struct Queue {
	QueueNode* phead;//队头:删
	QueueNode* ptail;//队尾:插
	int size;//保存队列有效数据个数
}Queue;

//初始化队列
void QueueInit(Queue* pq) {
	assert(pq);
	pq->phead = pq->ptail = NULL;
	pq->size = 0;
}

// 入队列,队尾
void QueuePush(Queue* pq, QDataType x) {
	assert(pq);
	//申请新结点
	QueueNode* newnode = (QueueNode*)malloc(sizeof(QueueNode));
	if (newnode == NULL) {
		perror("malloc fail!");
		exit(1);
	}
	newnode->data = x;
	newnode->next = NULL;
	
	if (pq->phead == NULL) {//判断队列是否为空
		pq->phead = pq->ptail = newnode;
	}
	else {
		//队列不为空
		pq->ptail->next = newnode;
		pq->ptail = newnode;
	}
	pq->size++;//入一次,size++ 一次
}

//队列判空
bool QueueEmpty(Queue* pq) {
	assert(pq);
	return (pq->phead == NULL) && (pq->ptail == NULL);
}

// 出队列,队头
void QueuePop(Queue* pq) {
	assert(pq);
	assert(!QueueEmpty(pq));

	//只有一个结点的情况,避免ptail变成野指针
	if (pq->ptail == pq->phead) {
		free(pq->phead);
		pq->phead = pq->ptail = NULL;
	}
	else {
		//删除队头元素
		QueueNode* next = pq->phead->next;
		free(pq->phead);
		pq->phead = next;
	}
	--pq->size;//出一次,size-- 一次
}

//取队头数据
QDataType QueueFront(Queue* pq) {
	assert(pq);
	assert(!QueueEmpty(pq));//判断队列不为空
	
	return pq->phead->data;
}

//取队尾数据
QDataType QueueBack(Queue* pq) {
	assert(pq);
	assert(!QueueEmpty(pq));//判断队列不为空

	return pq->ptail->data;
}

//队列有效元素个数
int QueueSize(Queue* pq) {
	assert(pq);
	return pq->size;//复杂度O(1)
}

//销毁队列
void QueueDestroy(Queue* pq) {
	assert(pq);
    //这里允许pq为空
	// assert(!QueueEmpty(pq));//判断队列不为空,空队列不需要销毁

	QueueNode* pcur = pq->phead;
	while (pcur) {
		QueueNode* Next = pcur->next;
		free(pcur);
		pcur = Next;
	}
	pq->phead = pq->ptail = NULL;
	pq->size = 0;
}



//两个队列来实现栈
typedef struct {
    Queue q1;//队列1
    Queue q2;//队列2
} MyStack;

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

    return pst;
}

//Push入栈
void myStackPush(MyStack* obj, int x) {
    //往不为空的队列中插入数据
    if(!QueueEmpty(&obj->q1)){//如果q1不为空,执行这个
        QueuePush(&obj->q1,x);//往队列q1里面插入x
    }
    else{//如果q2不为空,执行这个
        QueuePush(&obj->q2,x);//往队列q2里面插入x
    }
}

//Pop出栈
int myStackPop(MyStack* obj) {
    //找不为空的队列
    Queue* empQ = &obj->q1;//定义q1为空
    Queue* noneQ = &obj->q2;//定义q2为非空
    if(!QueueEmpty(&obj->q1)){//如果q1不为空,执行这个
        noneQ = &obj->q1;//q1是非空队列
        empQ = &obj->q2;//q2是空队列
    }
    //将不为空队列中size-1个数据导入到空队列中
    while(QueueSize(noneQ) > 1){//循环结束的判断,是只剩下一个数据
        int front = QueueFront(noneQ);//取队头数据
        QueuePush(empQ,front);//往空队列q2里面插入队头元素
        QueuePop(noneQ);//把非空队列q1里面的队头元素拿出来,这样下次循环出来的队头元素就不会重复了
    }
    //非空队列中只剩下一个数据------要出栈的数据
    int pop = QueueFront(noneQ);//把要取出的数据存起来
    QueuePop(noneQ);//将数据出队列,让q1变成空队列
    return pop;//返回要取出的数据
}

//取栈顶元素:找不为空的队列,取队尾元素
//不出栈
int myStackTop(MyStack* obj) {
    if(!QueueEmpty(&obj->q1)){
        //q1不为空
        return QueueBack(&obj->q1);//取队尾数据
    }
    else{
        //q2不为空
        return QueueBack(&obj->q2);//取队尾数据
    }
}

//判断栈是否为空
//也就是判断两个队列是否为空
bool myStackEmpty(MyStack* obj) {//栈是空的,返回 true ;否则,返回 false 。
    return QueueEmpty(&obj->q1) && QueueEmpty(&obj->q2);
}

//栈的销毁
//也就是判断两个队列的销毁
void myStackFree(MyStack* obj) {
    QueueDestroy(&obj->q1);//销毁q1
    QueueDestroy(&obj->q2);//销毁q2
    //因为MyStack* myStackCreate()里面有个指针pst,所以我们还要销毁指针obj
    free(obj);//销毁指向栈的指针
    obj = NULL;
}

/**
 * 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/1990243.html

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

相关文章

『大模型笔记』从API到Agent:万字长文洞悉LangChain工程化设计

『大模型笔记』从API到Agent:万字长文洞悉LangChain工程化设计 具体内容来自:从API到Agent:万字长文洞悉LangChain工程化设计

Spring源码解析(30)之AOP拦截链执行过程

一、前言 在上一节中我们介绍了AOP动态代理对象的创建过程,并且看到了Spring AOP在生成calllBacks的时候第一个拦截器就是:DynamicAdvisorInterceptor,所以我们通过代理对象执行对应的方法的时候就如跳入到这个拦截器中,接下来我们…

【RISC-V设计-07】- RISC-V处理器设计K0A之CSR

【RISC-V设计-07】- RISC-V处理器设计K0A之CSR 文章目录 【RISC-V设计-07】- RISC-V处理器设计K0A之CSR1.简介2.顶层设计3.端口说明4.寄存器说明5.代码设计6.总结 1.简介 控制和状态寄存器(Control and Status Register,简称CSR)是用于控制和…

使用历史版本比对法排查C++程序中的内存泄漏问题

目录 1、问题描述 2、使用Process Explorer实时查看程序的虚拟内存占用 2.1、对于内存泄漏问题,需要查看程序占用的虚拟内存 2.2、Windows任务管理器中看不到程序进程占用的虚拟内存,使用Process Explorer工具可以看到 2.3、通过Process Explorer工…

通世智库:姚力渟——第一次走进缓和医疗

2024年7月9日,我因工作原因,第一次以工作者的视角走进了位于北京市中心最具盛名的协和医院缓和医疗门诊,亲临现场去感受缓和医疗给患者及家属的贴心温暖和有益帮助。在此之前,我是一个惧怕医院,并时刻抱着能不去医院就…

Waterfox水狐浏览器:追求性能与隐私的64位网络探索者

大家好,今天电脑天空要为大家详细介绍一款基于Mozilla Firefox源代码开发的浏览器——Waterfox(水狐浏览器)。它专为64位系统优化,致力于提供更快速、更高效的浏览体验,并高度重视用户隐私保护。 主要特点 1. 高性能…

Stable Diffusion绘画 | 图生图-批量处理

批量处理中,对待处理图片的要求:宽高比一致 修改提示词后批量处理 调整参数: 确保宽高与原图一致增加一定的重绘幅度 调整提示词信息: 批量处理后,出图如下所示: 修改模型后批量处理 恢复提示词&#xf…

【数学建模】 多模数据与智能模型

文章目录 多模数据与智能模型1. 数字图像处理与计算机视觉1.1 数字图像的表示与处理1.1.1 认识OpenCV1.1.2 色彩学1.1.3 常见图像操作 1.2 数字图像的特征点1.2.1 Sobel算子1.2.2 Canny算子1.2.3 Harris角点检测1.2.4 ORB特征点检测 1.3 计算机视觉1.3.1 卷积神经网络1.3.2 YOL…

学习日志8.7--NGFW(Next Generation Firewall)下一代防火墙

目录 一、NGFW(Next Generation Firewall)下一代防火墙 二、防火墙CLI命令行配置 三、防火墙初始化Web登入 一、NGFW(Next Generation Firewall)下一代防火墙 防火墙是用来实现识别外部的安全流量,抵御外部的攻击流…

vue3+element-plus+flask 简易【工作日志本】小软件(过程超详细)

终于有时间继续学习技术了!开发了一个简易的用于记录日常工作内容的小软件,权当学习和练手。功能如下:用户登录、日志内容的查、增、删、改以及导出。 开发环境: windows 10,mysql 8,Hbuilder X&#xff08…

Linux -- 进度条小程序

目录 一、缓冲区 二、回车与换行 三、进度条 1、版本一 2、版本二 在写小程序之前先来了解两个知识点 一、缓冲区 缓冲区(buffer),它是内存空间的一部分。也就是说在内存空间中预留了一定的存储空间,这些存储空间用来缓冲输入或者输出的数据&#…

【eNSP模拟实验】交换机调整stp根端口和配置边缘端口

拓扑 关闭提示和设备重命名 将S1~S4交换机都做如下相关对应的配置 <Huawei>sys [Huawei]un in en [Huawei]sys S1 调整根端口 当前S3交换机生成树简要信息&#xff0c;其中e0/0/1是阻塞端口&#xff0c;e0/0/5是根端口。如何让e0/0/5变成阻塞端口&#xff0c;让e0/0/1…

【面试题】IDEA实现Debug远程调试Linux中的系统

有朋友面试时被问到&#xff0c;怎么远程调试部署在Linux中的系统&#xff1f;听到这个问题&#xff0c;那位朋友直接懵了&#xff0c;第一反应是震惊&#xff0c;已经部署在Linux中的系统还能调试&#xff1f; 沉默了几秒&#xff0c;只好说没有远程调试过Linux中的系统&#…

Debian 12 Linux系统安装Mongodb服务器步骤

在本地或云中运行的 Debian12 或 11 Linux 发行版上设置 MongoDB 数据库服务器并不是一件困难的事情&#xff0c;但是&#xff0c;必须知道如何使用终端和 Linux 命令行。虽然 MongoDB 除了社区版之外还提供了企业版&#xff0c;但在这里我们将使用这个免费的开源 NoSQL 文档数…

Spring基础知识学习总结(四)

&#xff08;5&#xff09;Spring新注解 使用上面的注解还不能全部替代xml配置文件&#xff0c;还需要使用注解替代的配置如下&#xff1a; 非自定义的Bean的配置&#xff1a;<bean>加载properties文件的配置&#xff1a;<context:property-placeholder>组件扫描…

Linux 文件、重定向、缓冲区

个人主页&#xff1a;仍有未知等待探索-CSDN博客 专题分栏&#xff1a; Linux 目录 一、文件 1、文件的理解&#xff08;浅层&#xff09; 1.文件是什么&#xff1f; 2.文件操作的前提 3.文件的存储 4.一个进程可以打开多个文件吗&#xff1f;如果可以怎么管理的&#xf…

【Android】网络技术知识总结之WebView,HttpURLConnection,OKHttp,XML的pull解析方式

文章目录 webView使用步骤示例 HttpURLConnection使用步骤示例GET请求POST请求 okHttp使用步骤1. 添加依赖2. 创建OkHttpClient实例3. 创建Request对象构建请求4. 发送请求5. 获取响应 Pull解析方式1. 准备XML数据2. 创建数据类3. 使用Pull解析器解析XML webView WebView 是 An…

三大浏览器Google Chrome、Edge、Firefox内存占用对比

问题 Chrome、Edg、Firefox三家究竟谁的占用少 结论 打开一个页面内存占用 Firefox>Edge>Chrome 打开打量页面内存占用 Firefox>Chrome>Edge 从监视器可以看到Edge增加一个页面增加一个页面不到100M而其它浏览器需要150M左右;Firefox浏览器主线程内存占用800M比…

Java之TCP网络编程

TCP网络编程 1 概述 在TCP通信协议下&#xff0c;计算机网络中不同设备上的应用程序之间可以通信&#xff0c;通信时需严格区分客户端&#xff08;Client&#xff09;与服务器端&#xff08;Server&#xff09;。 在Java中&#xff0c;对于这样基于TCP协议下连接通信的客户端…

数据结构-常见排序的七大排序

1.排序的概念及其运用 1.1排序的概念 排序&#xff1a;所谓排序&#xff0c;就是使一串记录&#xff0c;按照其中的某个或某些关键字的大小&#xff0c;递增或递减的排列起来的操作。 稳定性&#xff1a;假定在待排序的记录序列中&#xff0c;存在多个具有相同的关键字的记录…