数据结构C语言练习(两个栈实现队列)

一、引言

在数据结构的学习中,我们经常会遇到一些有趣的问题,比如如何用一种数据结构去实现另一种数据结构的功能。本文将深入探讨 “用栈实现队列” 这一经典问题,详细解析解题思路、代码实现以及每个函数的作用,帮助读者更好地理解数据结构之间的转换与应用。

练习题:

1.力扣 232. 用栈实现队列

二、解题思路

队列的特点是先进先出(FIFO),而栈的特点是后进先出(LIFO)。为了用栈实现队列,我们使用两个栈:pushST 和 popST

  • 入队操作(push:直接将元素压入 pushST 栈。
  • 出队操作(pop)和获取队头元素(peek:若 popST 栈为空,将 pushST 栈中的所有元素依次弹出并压入 popST 栈,此时 popST 栈的栈顶元素就是队列的队头元素,然后进行相应的弹出(pop)或返回(peek)操作。
  • 判空操作(empty:只有当 pushST 和 popST 两个栈都为空时,队列才为空。

三、数据结构定义

typedef int STDataType;
typedef struct Stack {STDataType* _a;int _top;int _capacity;
} Stack;typedef struct {Stack pushST;Stack popST;
} MyQueue;
  • Stack 结构体表示栈,包含存储数据的数组 _a、栈顶指针 _top 和容量 _capacity
  • MyQueue 结构体包含两个栈 pushST 和 popST,用于实现队列功能。

四、栈的基础操作函数详解

1. 栈初始化(StackInit

void StackInit(Stack* ps) {ps->_a = NULL;ps->_capacity = ps->_top = 0;
}
  • 功能:初始化栈,将栈的存储数组、容量和栈顶指针都置为初始状态。
  • 步骤:将 _a 置为 NULL_capacity 和 _top 置为 0,表示空栈。

2. 入栈操作(StackPush

void StackPush(Stack* ps, STDataType data) {assert(ps);if (ps->_capacity == ps->_top) {int newCapacity = ps->_capacity == 0 ? 4 : 2 * ps->_capacity;STDataType* tmp = (STDataType*)realloc(ps->_a, newCapacity * sizeof(STDataType));if (tmp == NULL) {perror("Fail realloc");exit(1);}ps->_a = tmp;ps->_capacity = newCapacity;}ps->_a[ps->_top++] = data;
}
  • 功能:将元素压入栈顶。
  • 步骤
    1. 检查栈是否已满,若满则扩容(初始容量为 4,每次扩容为原来的 2 倍)。
    2. 扩容后将新元素插入到栈顶位置,更新 _top 指针。

三、队列操作函数详解

1. myQueueCreate:创建队列

MyQueue* myQueueCreate() {MyQueue* pq = (MyQueue*)malloc(sizeof(MyQueue));StackInit(&pq->pushST);StackInit(&pq->popST);return pq;
}

 

  • 功能:创建队列实例。
  • 步骤
    • 为 MyQueue 分配内存,确保存储队列相关数据的空间。
    • 初始化内部的 pushST(入) 和 popST(出) 栈,通过 StackInit 清空栈状态,为后续操作做准备。

2. myQueuePush:入队操作

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

 

  • 功能:将元素加入队列尾部。
  • 原理:直接利用 pushST 栈的入栈操作。入队操作只需关注元素添加,无需处理顺序,因此直接将元素压入 pushST,后续出队时再通过 popST 调整顺序。

3. myQueuePop:出队操作(取后删)

int myQueuePop(MyQueue* obj) {if (StackEmpty(&obj->popST)) {while (!StackEmpty(&obj->pushST)) {StackPush(&obj->popST, StackTop(&obj->pushST));StackPop(&obj->pushST);}}int top = StackTop(&obj->popST);StackPop(&obj->popST);return top;
}

 

  • 功能:移除并返回队列头部元素。
  • 步骤
    • 检查 popST 是否为空。若为空,需将 pushST 中元素转移到 popST,以模拟队列的先进先出。转移过程:不断获取 pushST 栈顶元素(StackTop),压入 popSTStackPush),再弹出 pushST 栈顶元素(StackPop)。
    • 转移完成后,popST 栈顶即为队列头部元素,获取该元素值(StackTop),弹出 popST 栈顶元素(StackPop),并返回元素值。

4. myQueuePeek:获取队头元素(取不删)

int myQueuePeek(MyQueue* obj) {if (StackEmpty(&obj->popST)) {while (!StackEmpty(&obj->pushST)) {StackPush(&obj->popST, StackTop(&obj->pushST));StackPop(&obj->pushST);}}return StackTop(&obj->popST);
}

 

  • 功能:返回队列头部元素,不弹出。
  • 逻辑:与 myQueuePop 类似。先确保 popST 有元素(若 popST 空,转移 pushST 元素),再通过 StackTop 获取 popST 栈顶元素,即队列头部元素,不执行弹出操作。

5. myQueueEmpty:判断队列是否为空

bool myQueueEmpty(MyQueue* obj) {return StackEmpty(&obj->pushST) && StackEmpty(&obj->popST);
}

 

  • 功能:判断队列是否为空。
  • 原理:队列由 pushST 和 popST 共同维护,只有两者都为空时,队列才为空。通过同时检查两个栈的 StackEmpty 状态实现判断。

6. myQueueFree:释放队列资源

void myQueueFree(MyQueue* obj) {StackDestroy(&obj->pushST);StackDestroy(&obj->popST);free(obj);
}
  • 功能:释放队列及内部栈占用的内存。
  • 步骤
    • 先调用 StackDestroy 销毁 pushST 和 popST 栈,释放栈内部存储元素的内存。
    • 最后释放队列结构体 obj 本身的内存,完成资源清理。

六、总结

通过两个栈的巧妙配合,我们成功地实现了队列的功能。这种实现方式不仅加深了我们对栈和队列特性的理解,还展示了如何通过组合数据结构来解决实际问题。在实际编程中,灵活运用数据结构的特性可以让我们更高效地解决各种问题。希望本文的解析能帮助读者更好地掌握这一经典实现方法。

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

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

相关文章

前端如何导入谷歌字体库

#谷歌字体库内容丰富,涵盖上千种多语言支持的字体,学习导入谷歌字体库来增加网站的阅读性,是必不可少的一项技能# 1,前往谷歌字体网站 要会魔法,裸连很卡 2, 寻找心仪字体 Googles Fonts下面的filters可…

SnapdragonCamera骁龙相机源码解析

骁龙相机是高通开发的一个测试系统摄像头的demo,代码完善,功能强大。可以配合Camera驱动进行功能联调。 很多逻辑代码在CaptureModule.java里。 CaptureModule有8000多行,包罗万象。 涉及到界面显示要结合CaptureUI.java 一起来实现。 Ca…

多线程猜数问题

题目:线程 A 生成随机数,另外两个线程来猜数,线程 A 可以告诉猜的结果是大还是小,两个线程都猜对后,游戏结束,编写代码完成。 一、Semaphore 多个线程可以同时操作同一信号量,由此实现线程同步…

seq2seq

理解 transformer 中的 encoder decoder 详细的 transformer 教程见:【极速版 – 大模型入门到进阶】Transformer 文章目录 🌊 Encoder: 给一排向量输出另外一排向量🌊 Encoder vs. Decoder: multi-head attention vs. masked multi-head at…

Proxmox pct 部署ubuntu

pct 前言 PCT(Proxmox Container Tool)是 PVE 中用于管理 Linux 容器(LXC)的命令行工具。通过 PCT,用户可以执行各种容器管理任务,例如创建新的容器、启动和停止容器、更新容器、安装软件包、导出和导入容器等。PCT 提供了与 Web 界面相同的功能,但通过命令行进行操作,…

Google Play关键字优化:关键排名因素与实战策略

如果您准备发布应用程序或开始专注于关键字优化,您可能想知道如何向Google Play上的应用程序添加关键字。Google Play上的搜索量和排名与App Store不同,而且被索引排名的关键字也不同。在此文中,我们将确定Google Play上的关键排名因素&#…

Kafka延迟队列实现分级重试

技术方案 方案背景 Kafka队列消息消费处理过程中,发生处理异常,需要实现重试机制,并基于重试次数实现不同延迟时间重试方案。 方案介绍 通过实现Kafka延迟队列来实现消息重试机制。 目标: 支持所有业务场景的延迟重试支持多…

Maven核心配置文件深度解析:pom.xml完全指南

🧑 博主简介:CSDN博客专家、全栈领域优质创作者、高级开发工程师、高级信息系统项目管理师、系统架构师,数学与应用数学专业,10年以上多种混合语言开发经验,从事DICOM医学影像开发领域多年,熟悉DICOM协议及…

MSTP多域生成树

协议信息 MSTP 兼容 STP 和 RSTP,既可以快速收敛,又提供了数据转发的多个冗余路径,在数据转发过程中实现 VLAN 数据的负载均衡。 MSTP 可以将一个或多个 VLAN 映射到一个 Instance(实例)(一个或多个 VLAN…

MQTT 服务器(emqx)搭建及使用(一)

一. EMQX 服务器搭建 1.下载EMQX 下载链接:Windows | EMQX 文档 官方手册 2.下载内容解压至盘符根目录 3.进入bin文件夹,在地址栏输入cmd 4.依次输入下面命令安装服务 .\emqx.cmd install .\emqx.cmd console 5.设置自启动 创建批处理文件&#x…

在Thinkphp中使用JWT 包括JWT是什么,JWT的优势

首先了解一下什么是JWT JWT 是一种开放标准(RFC 7519),用于在各方之间以 JSON 对象形式安全传输信息4。其核心特点包括: 结构:由三部分组成(Header、Payload、Signature),通过点号…

hackmyvn-casino

arp-scan -l nmap -sS -v 192.168.255.205 目录扫描 dirsearch -u http://192.168.255.205/ -e * gobuster dir -u http://192.168.255.205 -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -x php -b 301,401,403,404 80端口 随便注册一个账号 玩游戏时的…

图表配置表增加分析指标字段

在设计报表图表配置表时,为存储 同比、环比 这类分析指标,建议通过以下方式定义字段结构和命名: 一、字段设计方案 // 配置表示例结构 interface ChartConfig {id: string; // 唯一标识name: string; // 图表…

广州SMT贴片加工厂精密制造工艺解析

内容概要 在电子制造领域,SMT贴片加工技术已成为现代电子产品精密组装的核心环节。广州作为华南地区电子产业的重要枢纽,其SMT贴片加工厂通过融合自动化设备与严格工艺标准,构建起高效可靠的制造体系。 对于电子产品制造商而言,…

RK3568-适配ov5647摄像头

硬件原理图 CAM_GPIO是摄像头电源控制引脚,连接芯片GPIO4_C2 CAM_LEDON是摄像头led灯控制引脚,连接芯片GPIO4_C3编写设备树 / {ext_cam_clk: external-camera-clock {compatible = "fixed-clock";clock-frequency = <25000000>;clock-output-names = "…

关于 @Autowired 和 @Value 使用 private 字段的警告问题分析与解决方案

问题背景 在使用 Spring 框架进行开发时&#xff0c;我们经常会使用 Autowired 和 Value 注解来进行依赖注入和属性值注入。然而&#xff0c;当我们将这些注解应用于 private 字段时&#xff0c;IDE&#xff08;如 IntelliJ IDEA&#xff09;可能会显示警告信息&#xff0c;提…

Flutter 开发环境配置--宇宙级教学!

目录 一、安装环境&#xff08;Windows&#xff09;二、Android 创建Flutter项目三、VSCode 搭建环境四、补充 一、安装环境&#xff08;Windows&#xff09; Flutter SDK 下载 推荐使用中国镜像站点下载 Flutter SDK&#xff0c;速度更快&#xff1a;中国环境 或者从官网下载…

碰一碰发视频网页版本开发的源码搭建指南

引言 在数字化信息快速传播的时代&#xff0c;近场通信&#xff08;NFC&#xff09;技术为信息交互带来了新的便捷方式。通过网页版本实现碰一碰发视频功能&#xff0c;能够让用户在浏览器环境中轻松实现视频分享&#xff0c;拓展了视频传播的途径。本文将详细介绍碰一碰发视频…

OMNIWeb 数据介绍

网址&#xff1a;SPDF - OMNIWeb Service 注&#xff1a;OMNI并非特定缩写&#xff0c;仅表示"多样化"含义。 About the Data All the data to which this interface and its multiple underlying interfaces provide access have in common that they are relevan…

Python学习(二)操作列表

一、列表的遍历 每个缩进的代码行都是循环的一部分&#xff0c;且将针对列表中的每个值都执行一次。因此&#xff0c;可对列表中的每个值执行任意次数的操作。 magicians [alice, david, carolina] for magician in magicians:print(magician)注意&#xff1a; 1、遍历的时…