【数据结构】栈和队列(c语言实现)(附源码)

🌟🌟作者主页:ephemerals__

🌟🌟所属专栏:数据结构

目录

一、栈

1.栈的概念与结构

2.栈的实现

2.1 栈的结构定义

2.2 方法的声明

2.3 方法的实现

2.3.1  初始化

2.3.2 销毁

2.3.3 判空

2.3.4 压栈

2.3.5 出栈

2.3.6 取栈顶元素

2.4 程序全部代码

二、队列

1.队列的概念与结构

2.队列的实现

2.1 队列的结构定义

2.2 方法声明

2.3 方法实现

2.3.1 初始化

2.3.2 判空

2.3.3 入队列

2.3.4 出队列

2.3.5 取队头数据和队尾数据

2.3.6 销毁队列

2.4 程序全部代码

总结


正文开始

一、栈

1.栈的概念与结构

栈的概念:栈是一种特殊的线性表,它不允许被遍历,并且只能够在固定的一端进行数据的插入或者删除操作。进行插入或删除操作的一端称之为栈顶,另一端称为栈底。由于数据的插入和删除在同一端,所以栈的数据元素遵从“先进后出”的原则。

2.栈的实现

        一般可以使用顺序表或者链表实现栈,在进行插入删除操作时满足先进后出原则即可。由于顺序表的尾插与尾删操作效率较高,接下来我们尝试用顺序表实现它。

2.1 栈的结构定义

栈的结构定义与顺序表完全相同,定义如下:

typedef int STDataType;typedef struct Stack
{STDataType* arr;//起始指针int capacity;//栈的空间大小int top;//有效数据的个数
};

2.2 方法的声明

接下来是栈的一些常用方法:

//初始化
void STInit(ST* ps);//销毁
void STDestroy(ST* ps);//判空
bool STEmpty(ST* ps);//压栈
void STPush(ST* ps, STDataType n);//出栈
void STPop(ST* ps);//取栈顶元素
STDataType STTop(ST* ps);

2.3 方法的实现

2.3.1  初始化
//初始化
void STInit(ST* ps)
{assert(ps);//防止传空指针ps->arr = NULL;ps->capacity = ps->top = 0;
}
2.3.2 销毁
//销毁
void STDestroy(ST* ps)
{assert(ps);//防止传空if (ps->arr != NULL)//防止多次free{free(ps->arr);}ps->arr = NULL;ps->capacity = ps->top = 0;
}
2.3.3 判空

        当栈中有效数据个数为0时,栈即为空。

//判空
bool STEmpty(ST* ps)
{assert(ps);return ps->top == 0;
}
2.3.4 压栈

        进行压栈操作时,我们将结构成员top作为栈顶,在尾部插入数据

//压栈
void STPush(ST* ps, STDataType n)
{assert(ps);if (ps->capacity == ps->top)//若空间不够,则增容{int NewCapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;STDataType* tmp = (STDataType*)realloc(ps->arr, NewCapacity * sizeof(STDataType));if (tmp == NULL)//内存申请失败,则直接退出程序{perror("realloc");exit(1);}ps->arr = tmp;//成功则让arr指向申请好的空间ps->capacity = NewCapacity;}ps->arr[ps->top++] = n;//在栈顶插入数据
}
2.3.5 出栈

        为遵循“先进后出”原则,既然在尾部插入数据,那么删除数据时也要在尾部进行:

//出栈
void STPop(ST* ps)
{assert(ps);assert(!STEmpty(ps));//确保栈不为空ps->top--;
}
2.3.6 取栈顶元素

        对于栈这样的数据结构,我们不能进行遍历,但是可以访问到栈顶元素。代码如下:

//取栈顶元素
STDataType STTop(ST* ps)
{assert(ps && !STEmpty(ps));return ps->arr[ps->top - 1];//栈顶top-1的位置即为栈顶元素
}

2.4 程序全部代码

        关于栈实现的全部代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>typedef int STDataType;typedef struct Stack
{STDataType* arr;//起始指针int capacity;//栈的空间大小int top;//有效数据的个数
}ST;//初始化
void STInit(ST* ps);//销毁
void STDestroy(ST* ps);//判空
bool STEmpty(ST* ps);//压栈
void STPush(ST* ps, STDataType n);//出栈
void STPop(ST* ps);//取栈顶元素
STDataType STTop(ST* ps);//初始化
void STInit(ST* ps)
{assert(ps);//防止传空指针ps->arr = NULL;ps->capacity = ps->top = 0;
}//销毁
void STDestroy(ST* ps)
{assert(ps);//防止传空if (ps->arr != NULL)//防止多次free{free(ps->arr);}ps->arr = NULL;ps->capacity = ps->top = 0;
}//判空
bool STEmpty(ST* ps)
{assert(ps);return ps->top == 0;
}//压栈
void STPush(ST* ps, STDataType n)
{assert(ps);if (ps->capacity == ps->top)//若空间不够,则增容{int NewCapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;STDataType* tmp = (STDataType*)realloc(ps->arr, NewCapacity * sizeof(STDataType));if (tmp == NULL)//内存申请失败,则直接退出程序{perror("realloc");exit(1);}ps->arr = tmp;//成功则让arr指向申请好的空间ps->capacity = NewCapacity;}ps->arr[ps->top++] = n;//在栈顶插入数据
}//出栈
void STPop(ST* ps)
{assert(ps);assert(!STEmpty(ps));//确保栈不为空ps->top--;
}//取栈顶元素
STDataType STTop(ST* ps)
{assert(ps && !STEmpty(ps));return ps->arr[ps->top - 1];//栈顶top-1的位置即为栈顶元素
}

二、队列

        学习了栈的特性和方法实现之后,我们再来了解一个新的数据结构:队列

1.队列的概念与结构

队列也是一种特殊的线性表,与栈相反,它只能在一端插入数据,另一端删除数据。插入数据的端叫做队尾;删除数据的一端叫做队头。因此,队列的数据元素遵从“先进先出”的原则。

2.队列的实现

        与栈相同,队列的实现也可以用顺序表或链表。由于顺序表两端的插入和删除操作要涉及到数据的全体移动,效率较低,我们就尝试用链表来实现队列

2.1 队列的结构定义

        队列的结构定义如下:

typedef int QDataType;//定义队列的节点
typedef struct QueueNode
{QDataType data;//数据域struct QueueNode* next;//指针域
}QNode;//定义队列
typedef struct Queue
{QNode* phead;//队头指针QNode* ptail;//队尾指针int size;//队列元素个数
}Queue;

2.2 方法声明

//初始化
void QInit(Queue* pq);//判空
bool QEmpty(Queue* pq);//入队列
void QPush(Queue* pq, QDataType n);//出队列
void QPop(Queue* pq);//取队头数据
QDataType QFront(Queue* pq);//取队尾数据
QDataType QBack(Queue* pq);//销毁
void QDestroy(Queue* pq);

2.3 方法实现

2.3.1 初始化
//初始化
void QInit(Queue* pq)
{assert(pq);pq->phead = pq->ptail = NULL;//将两指针都制为空pq->size = 0;//数据个数为0
}
2.3.2 判空

        当队头指针和队尾指针都指向空时,说明队列为空。

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

        入队列的操作与单链表尾插十分相似,由于有队尾指针,就无需遍历链表。注意其中的一些细节处理。

//入队列
void QPush(Queue* pq, QDataType n)
{assert(pq);QNode* newnode = (QNode*)malloc(sizeof(QNode));//创建新节点if (newnode == NULL)//创建失败退出程序{perror("malloc");exit(1);}newnode->data = n;newnode->next = NULL;if (QEmpty(pq))//队列为空的情况{pq->phead = pq->ptail = newnode;//队头与队尾都指向新节点}else//其他情况,尾插操作{pq->ptail->next = newnode;//将新节点连接在队尾之后pq->ptail = newnode;//队尾指向新节点}pq->size++;//空间大小+1
}
2.3.4 出队列

        出队列时,注意是在队头删除数据。

//出队列
void QPop(Queue* pq)
{assert(pq && !QEmpty(pq));//确保队列不为空if (pq->phead == pq->ptail)//队列只有一个元素的情况{free(pq->phead);//删除该节点pq->phead = pq->ptail = NULL;//两指针制为空}else{QNode* next = pq->phead->next;//先记录下一个节点free(pq->phead);pq->phead = next;//让队头指向下一个节点}pq->size--;//空间大小-1
}
2.3.5 取队头数据和队尾数据
//取队头数据
QDataType QFront(Queue* pq)
{assert(pq && !QEmpty(pq));return pq->phead->data;
}//取队尾数据
QDataType QBack(Queue* pq)
{assert(pq && !QEmpty(pq));return pq->ptail->data;
}
2.3.6 销毁队列
//销毁
void QDestroy(Queue* pq)
{assert(pq);QNode* cur = pq->phead;while (cur != NULL)//遍历删除{QNode* next = cur->next;//记录后继节点free(cur);cur = next;//cur指针指向记录的节点}pq->phead = pq->ptail = NULL;pq->size = 0;
}

2.4 程序全部代码

        队列实现的全部代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>typedef int QDataType;//定义队列的节点
typedef struct QueueNode
{QDataType data;//数据域struct QueueNode* next;//指针域
}QNode;//定义队列
typedef struct Queue
{QNode* phead;//队头指针QNode* ptail;//队尾指针int size;//队列元素个数
}Queue;//初始化
void QInit(Queue* pq);//判空
bool QEmpty(Queue* pq);//入队列
void QPush(Queue* pq, QDataType n);//出队列
void QPop(Queue* pq);//取队头数据
QDataType QFront(Queue* pq);//取队尾数据
QDataType QBack(Queue* pq);//销毁
void QDestroy(Queue* pq);//初始化
void QInit(Queue* pq)
{assert(pq);pq->phead = pq->ptail = NULL;//将两指针都制为空pq->size = 0;//数据个数为0
}//判空
bool QEmpty(Queue* pq)
{assert(pq);return pq->phead == NULL && pq->ptail == NULL;
}//入队列
void QPush(Queue* pq, QDataType n)
{assert(pq);QNode* newnode = (QNode*)malloc(sizeof(QNode));//创建新节点if (newnode == NULL)//创建失败退出程序{perror("malloc");exit(1);}newnode->data = n;newnode->next = NULL;if (QEmpty(pq))//队列为空的情况{pq->phead = pq->ptail = newnode;//队头与队尾都指向新节点}else//其他情况,尾插操作{pq->ptail->next = newnode;//将新节点连接在队尾之后pq->ptail = newnode;//队尾指向新节点}pq->size++;//空间大小+1
}//出队列
void QPop(Queue* pq)
{assert(pq && !QEmpty(pq));//确保队列不为空if (pq->phead == pq->ptail)//队列只有一个元素的情况{free(pq->phead);//删除该节点pq->phead = pq->ptail = NULL;//两指针制为空}else{QNode* next = pq->phead->next;//先记录下一个节点free(pq->phead);pq->phead = next;//让队头指向下一个节点}pq->size--;//空间大小-1
}//取队头数据
QDataType QFront(Queue* pq)
{assert(pq && !QEmpty(pq));return pq->phead->data;
}//取队尾数据
QDataType QBack(Queue* pq)
{assert(pq && !QEmpty(pq));return pq->ptail->data;
}//销毁
void QDestroy(Queue* pq)
{assert(pq);QNode* cur = pq->phead;while (cur != NULL)//遍历删除{QNode* next = cur->next;//记录后继节点free(cur);cur = next;//cur指针指向记录的节点}pq->phead = pq->ptail = NULL;pq->size = 0;
}

总结

        今天我们学习了栈和队列这两种数据结构:栈只能从同一端进行插入、删除操作,遵从“先进后出”原则;而队列只能从一端插入、另一端删除,遵从“先进先出”原则。栈和队列在一些场景的实用性很高,例如二叉树的层序遍历、快速排序的非递归实现等。如果你觉得博主讲的还不错,就请留下一个小小的赞在走哦,感谢大家的支持❤❤❤

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

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

相关文章

常见CMS漏洞(WordPress、DeDeCMS、ASPCMS、PHPMyadmin、Pageadmin)

目录 一&#xff1a;WordPress 步骤一:进入Vulhub靶场并执行以下命令开启靶场;在浏览器中访问并安装好子... 步骤二:思路是修改其WP的模板写入一句话木马后门并访问其文件即可GetShel;登陆WP后点击【外观】--》【编辑】 --》 404.php 步骤三:访问以下连接即可获取WebShel...…

用VBA在Word中随机打乱单词表,进行分列

一、效果展示&#xff08;以下是三次随机打乱的结果&#xff09; 二、代码 Sub 随机分单词到后面的单元格()Dim C1 As CellDim str, str1, aDim shuffledArray() As VariantSet C1 Selection.Range.Tables(1).Cell(1, 1)str C1.Range.textstr mid(str, 3, Len(str) - 4)str…

ADC的介绍和工作原理

一&#xff0c;什么是ADC&#xff1f; Analog-to-Digital Converter&#xff0c;指模拟/数字转换器 什么是ADC&#xff1a; ADC可以将引脚上连续变化的模拟电压转换为内存中存储的数字变量&#xff0c;建立模拟电路到数字电路的桥梁 SUCH AS: 12 位 ADC 是一种逐次逼近…

C# Solidworks二次开发------设置按键打开模型查询

一、代码 public void Open_File(string FileNmae) {Process.Start("explorer.exe", FileNmae); }Open_File("路径"); 二、内容 这个代码很简单&#xff0c;我使用其主要的作用是设置一个按键&#xff0c;可以快速的查看我们已生成的三维模型&#xff0…

JS使用 navigator.clipboard 操作剪切板

注意&#xff1a;需要在安全域下才能够使用&#xff0c;比如&#xff1a;https 协议的地址、127.0.0.1、localhost safari浏览器需要打开配置&#xff0c;在地址栏输入 about:config&#xff0c;搜索 clipboard&#xff0c;将 asyncClipboard 由 false 改为 true&#xff0c;然…

C语言初阶(11)

1.结构体定义 结构体就是一群数据类型的集合体。这些数据类型被称为成员变量。结构的成员可以是标量、数组、指针&#xff0c;甚至是其他结构体。 2.结构体的声明和结构体变量命名与初始化 结构体声明由以下结构组成 struct stu {char name[12];int age; }; 结构体命名有两…

算法通关:017_2:二叉树及三种顺序的非递归遍历

文章目录 题目思路运行结果 题目 二叉树及三种顺序的非递归遍历 思路 import java.util.Stack;/*** Author: ggdpzhk* CreateTime: 2024-08-04* 二叉树非递归版本*/ public class _017_Tree2 {public static void main(String[] args) {TreeNode head new TreeNode(1);head.…

keil编程中#pragma NOAREGS的作用和优点

参考 功能 不直接操作内存地址 #pragma NOAREGS在Keil中的使用含义是禁用自动分配寄存器&#xff0c;开发人员指定控制的寄存器。‌例如中断的执行使用的寄存器需要人为的指定&#xff0c;避免分配同样的寄存器导致数据错误。对寄存器R0到R7不直接操作寄存器地址&#xff0c…

学习笔记-Cookie、Session、JWT

目录 一、验证码的生成与校验 1. 创建生成验证码的工具类 2. 写一个 Controller 3. 实现验证码验证 1. 获取验证码 2. 验证码请求过程 3. 验证码的校验 4. 原理说明 5. 验证 6. 总结 二、JWT登录鉴权 1. 为什么要做登录鉴权&#xff1f; 2. 什么是 JWT 3. JWT相比…

Open Interpreter - 开放解释器

文章目录 一、关于演示它是如何工作的&#xff1f;与 ChatGPT 的代码解释器比较 二、快速开始三、更多操作1、互动聊天2、程序化聊天3、开始新的聊天4、保存和恢复聊天5、自定义系统消息6、更改模型7、在本地运行 Open Interpreter终端Python上下文窗口&#xff0c;最大令牌 8、…

【Golang 面试 - 进阶题】每日 3 题(十四)

✍个人博客&#xff1a;Pandaconda-CSDN博客 &#x1f4e3;专栏地址&#xff1a;http://t.csdnimg.cn/UWz06 &#x1f4da;专栏简介&#xff1a;在这个专栏中&#xff0c;我将会分享 Golang 面试中常见的面试题给大家~ ❤️如果有收获的话&#xff0c;欢迎点赞&#x1f44d;收藏…

python pip怎么安装包

按WinR键打开运行窗口&#xff0c;输入“cmd”&#xff0c;再按回车键&#xff0c;打开命令行窗口。 找到pip安装路径。 Python2/Python3安装路径是相同的&#xff0c;都在x:\Python xx\Scripts路径下。 拖动pip主应用程序到命令行窗口。 输入“install 模块/包名”&#xff…

【Golang 面试 - 进阶题】每日 3 题(十)

✍个人博客&#xff1a;Pandaconda-CSDN博客 &#x1f4e3;专栏地址&#xff1a;http://t.csdnimg.cn/UWz06 &#x1f4da;专栏简介&#xff1a;在这个专栏中&#xff0c;我将会分享 Golang 面试中常见的面试题给大家~ ❤️如果有收获的话&#xff0c;欢迎点赞&#x1f44d;收藏…

PCIe总线-RK3588 PCIe RC初始化流程分析(十二)

1.简介 RK3588 PCIe RC的初始化涉及PCIe设备枚举、中断&#xff08;INTx、MSI、MSI-X&#xff09;配置、BAR配置、ATU配置、链路训练等&#xff0c;下面一一介绍。 2.初始化 当RC的模式为RK_PCIE_EP_TYPE时&#xff0c;平台驱动调用rk_add_pcie_port函数初始化RC&#xff0c…

【论文笔记】4D Millimeter-Wave Radar in Autonomous Driving: A Survey

原文链接&#xff1a;https://arxiv.org/abs/2306.04242 I. 引言 传统毫米波雷达&#xff08;3D毫米波雷达&#xff09;测量俯仰角的能力有限&#xff0c;数据通常仅包括距离、水平角和多普勒速度信息。此外&#xff0c;3D雷达数据存在噪声且分辨率低&#xff08;尤其是水平角…

python学习之路 - python的函数

目录 一、python函数1、函数介绍2、函数的定义3、函数的参数4、函数的返回值5、函数说明文档6、函数的嵌套调用7、变量的作用域8、综合案例9、函数与方法的区别 二、python函数进阶1、函数多返回值2、函数多种传参方式a、位置参数b、关键字参数c、缺省参数d、不定长参数 3、匿名…

【2024年华数杯C题老外游中国】(完整题解+代码+完整参考论文)

请问 352 个城市中所有 35200 个景点评分的最高分&#xff08;Best Score&#xff0c;简称 BS&#xff09;是多少&#xff1f;全国有多少个景点获评了这个最高评分&#xff08;BS&#xff09;&#xff1f;获评了这个最高评分&#xff08;BS&#xff09;景点最多的城市有哪些&am…

代码坏味道有24种?我看未必

微信公众号&#xff1a;牛奶 Yoka 的小屋 有任何问题。欢迎来撩~ 最近更新&#xff1a;2024/08/03 [大家好&#xff0c;我是牛奶。] 我在上一篇文章打开IDEA&#xff0c;程序员思考的永远只有两件事&#xff01;中&#xff0c;通过代码命名、重复代码、合格方法三个章节&#…

请你学习:前端布局3 - 浮动 float

1 标准流&#xff08;也称为普通流、文档流&#xff09; 标准流&#xff08;也称为普通流、文档流&#xff09;是CSS中元素布局的基础方式&#xff0c;它决定了元素在页面上的默认排列方式。这种布局方式遵循HTML文档的结构&#xff0c;不需要额外的CSS样式来指定元素的位置。…

MongoDB未授权访问漏洞

MongoDB未授权访问漏洞 mongodb数据库是由C编写&#xff0c;主要是为了提供web应可用扩展的一种高性能数据库。开启MongoDB服务时不添加任何参数时,默认是没有权限验证的,登录的用户可以通过默认端口无需密码对数据库任意操作(增、删、改、查高危动作)而且可以远程访问数据库。…