深入了解栈和队列

小伙伴们,今天我们来继续学习数据结构的第二部分内容,就是栈和队列了。那么栈和队列有什么用呢?

栈和队列是两种重要的线性结构。从数据结构的角度看,栈和队列也是线性表,其特殊性在于栈和队列的基本操作是线性表操作的子集,它们是操作受限的线性表,因此,可称为具有限定性的数据结构。但从数据类型角度看,它们是和线性表不同的两类重要的抽象数据类型。

首先,我们先来学习栈

1.栈

1.1栈的概念及结构
栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。 进行数据插入和删除操作的一端
称为栈顶,另一端称为栈底。 栈中的数据元素遵守 后进先出 LIFO Last In First Out )的原则。
压栈:栈的插入操作叫做进栈 / 压栈 / 入栈, 入数据在栈顶
出栈:栈的删除操作叫做出栈。 出数据也在栈顶
1.2栈的实现
栈的实现一般可以使用 数组或者链表实现 ,相对而言数组的结构实现更优一些。因为数组在尾上插入数据的代价比较小。

单链表形式

 还是像链表一样,创建3个文件,一个头文件,两个.c文件。我们通过数组来实现栈的创建。

首先我们要想的一个问题是初始化时top是为0还是-1?(不要把top理解为数组下标)

 先来看一下静态的栈

// 下面是定长的静态栈的结构,实际中一般不实用,所以我们主要实现下面的支持动态增长的栈
typedef int STDataType;
#define N 10
typedef struct Stack
{
     STDataType _a[N];
     int _top; // 栈顶
}Stack;

静态的栈一般很少用到,所以我们对动态的栈进行书写

stack.h

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>

typedef int STDataType;
typedef struct Stack
{
	STDataType* a;//数组
	int top;
	int capacity;
}ST;

//初始化
void STInit(ST* pst);
//销毁
void STDestroy(ST* pst);
//入栈
void STPush(ST* pst, STDataType x);
//出栈
void STPop(ST* pst);
//检查是否为空
bool STEmpty(ST* pst);
//获取有效元素个数
int STSize(ST* pst);
//获取栈顶元素
STDataType STTop(ST* pst);

stack.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"stack.h"

//初始化
void STInit(ST* pst)
{
	assert(pst);
	pst->a = NULL;
	pst->top = 0;//0时是指向栈顶数据的下一个位置
	//pst->top = -1;//-1时是指向栈顶数据
	pst->capacity = 0;
}

//销毁
void STDestroy(ST* pst)
{
	assert(pst);

	free(pst->a);
	pst->a = NULL;
	pst->top = pst->capacity = 0;
}

//入栈
void STPush(ST* pst, STDataType x)
{
	if (pst->top == pst->capacity)
	{
		int newcapacity = pst->capacity == 0 ? 4 : pst->capacity * 2;
		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] = x;
	pst->top++;
}

//出栈
void STPop(ST* pst)
{
	assert(pst);
    //如果栈为空时,是true,再取非,说明栈内没有元素,无法出栈就会报错
	assert(!STEmpty(pst));
	pst->top--;
}

//获取栈顶元素
STDataType STTop(ST* pst)
{
	assert(pst);
	assert(!STEmpty(pst));

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

//检查是否为空
bool STEmpty(ST* pst)
{
	assert(pst);
	//方法1
	/*if (pst->top == 0)
	{
		return true;
	}
	else
	{
		return false;
	}*/

	//方法2
	return pst->top == 0; //等于0返回true,不等于返回false
}

//获取有效元素个数
int STSize(ST* pst)
{
	assert(pst);
	return pst->top;
}



test.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"stack.h"
#include<stdio.h>
void TestStack()
{
	ST st;
	STInit(&st);
	STPush(&st, 1);
	STPush(&st, 2);
	STPush(&st, 3);
	STPush(&st, 4);
	while (!STEmpty(&st))
	{
		printf("%d ", STTop(&st));
		STPop(&st);
	}

	STDestroy(&st);
}

int main()
{
	TestStack();

	return 0;
}

2.队列

2.1 队列的结构及概念
队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出
FIFO(First In First Out) 入队列:进行插入操作的一端称为 队尾 出队列:进行删除操作的一端称为 队头
2.2 队列的实现

我们这次用单链表来实现队列的实现,当然也可以通过数组来实现。

我们可以将链表的“头节点”和“尾节点”分别视为“队首”和“队尾”,规定队尾仅可添加
节点,队首仅可删除节点。(图片来源:hello算法
链接: hello‑algo.com
首先我们要先定义队列,再定义队列的结构。
//链式结构:表示队列
typedef int QDataType;
typedef struct QueueNode
{
	struct QueueNode* next;
	QDataType data;
}QNode;

//队列的结构
typedef struct Queue
{
	QNode* phead;
	QNode* ptail;
	int size;
}Queue;

另外我们不需要对开辟节点重新写一个函数,因为只需要插入才会开辟新的节点,所以可以直接在插入队列的函数里面开辟节点。

Queue.h

#pragma once

#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>

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

typedef struct Queue
{
	QNode* phead;
	QNode* ptail;
	int size;
}Queue;

//初始化
void QueueInit(Queue* pq);
//销毁
void QueueDestroy(Queue* pq);
//插入队列
void QueuePush(Queue* pq, QDataType x);
//出队列
void QueuePop(Queue* pq);
//寻找队头
QDataType QueueFront(Queue* pq);
//寻找队尾
QDataType QueueBack(Queue* pq);
//计算个数
int QueueSize(Queue* pq);
//检查队列是否为空
bool QueueEmpty(Queue* pq);

Queue.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"Queue.h"

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

//销毁
void QueueDestroy(Queue* pq)
{
	assert(pq);
	QNode* cur = pq->phead;
	while (cur)
	{
		QNode* next = cur->next;
		free(cur);
		cur = next;
	}
	pq->phead = pq->ptail = NULL;
	pq->size = 0;
}

//插入队列
void QueuePush(Queue* pq, QDataType x)
{
	assert(pq);
	QNode* newnode = (QNode*)malloc(sizeof(QNode));

	if (newnode == NULL)
	{
		perror("malloc fail");
	}
	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);
	assert(!QueueEmpty(pq));

	//分为一个节点和多个节点
	if (pq->phead->next == NULL)
	{
		free(pq->phead);
		pq->phead = pq->ptail == NULL;
	}
	else
	{
		QNode* next = pq->phead->next;
		free(pq->phead);
		pq->phead = next;
	}
	pq->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;
}

//检查队列是否为空
bool QueueEmpty(Queue* pq)
{
	assert(pq);
	return pq->size == 0;
}

tect.c

void TestQueue()
{
	Queue q;
	QueueInit(&q);
	QueuePush(&q, 1);
	QueuePush(&q, 2);
	QueuePush(&q, 3);
	QueuePush(&q, 4);
	while (!QueueEmpty(&q))
	{
		printf("%d ", QueueFront(&q));
		QueuePop(&q);
	}
	printf("\n");
	QueueDestroy(&q);
}

好了,小伙伴们,这次我们对栈和队列先学到这里,以后我会继续补充一些知识点在这里,一定要记得常回来看看。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Linux系统部署Swagger Editor结合内网穿透实现公网管理本地接口文档

文章目录 Swagger Editor本地接口文档公网远程访问1. 部署Swagger Editor2. Linux安装Cpolar3. 配置Swagger Editor公网地址4. 远程访问Swagger Editor5. 固定Swagger Editor公网地址 正文开始前给大家推荐个网站&#xff0c;前些天发现了一个巨牛的 人工智能学习网站&#xf…

数据结构:图的存储与遍历(待续)

图&#xff08;Graph&#xff09;是一种较线性表和树更为复杂的非线性结构。在图结构中&#xff0c;对结点&#xff08;图中常称为顶点&#xff09;的前驱和后继个数不加限制&#xff0c; 即结点之间的关系是任意的。 一、基本概念和一般结论 因为一条边关联两个顶点&#xff0…

计算机服务器中了devos勒索病毒怎么解密,devos勒索病毒解密工具流程

随着网络技术的不断发展与更新&#xff0c;越来越多的企业利用网络开展了各项工作业务&#xff0c;网络也为企业提供了极大便利&#xff0c;大大提高了办公效率。但网络是一把双刃剑&#xff0c;企业的数据安全问题一直是企业关心的主要话题&#xff0c;近日&#xff0c;云天数…

如何在Windows搭建WebDav服务,并外网可访问

目录 1. 安装IIS必要WebDav组件 2. 客户端测试 3. 使用cpolar内网穿透&#xff0c;将WebDav服务暴露在公网 3.1 打开Web-UI管理界面 3.2 创建隧道 3.3 查看在线隧道列表 4. 公网远程访问 4.1 浏览器访问测试 4.2 映射本地盘符访问 4.3 安装Raidrive客户端 总结&…

由世界第一个AI软件工程师Devin引发的热潮背后----程序员到底会不会被代替?AI发展至如今是否初衷已变?

目录 一.Devin的登场是突破也是导火索 二.Devin的"逆天"能力 1、端到端构建和部署程序 2、自主查找并修复bug 3、训练和微调自己的AI模型 4、修复开源库 5、成熟的生产库也能做贡献 6、学习能力 三.Devin的出现甚至整个AI领域的进步,编程还有未来吗? 1.业…

机试:蛇形矩阵

问题描述: 代码示例: //蛇形矩阵 #include <bits/stdc.h> using namespace std;int main(){int n;cout << "输入样例" << endl; cin >> n;int k 1; for(int i 0; i < n; i){if( i %2 0){//单数行for(int j 0; j < n; j){ cout &…

国际前十正规外汇实时行情走势app软件最新排名(综合版)

外汇交易&#xff0c;作为当今世界金融市场上一个重要的板块&#xff0c;备受关注和热议。随着金融市场的日益发展&#xff0c;外汇交易也发展成为一个新兴的投资交易渠道。为了更好地满足投资者对外汇市场的需求&#xff0c;外汇实时行情走势app软件应运而生&#xff0c;它为投…

字符指针

1、字符指针 在指针的类型中我们知道有一种指针类型为字符指针 char* 一般使用方式&#xff1a; 还有使用方式如下&#xff1a; 注意观察区别&#xff1a;%C 与 %S &#xff1a; 这种方式是将字符串的首地址放到指针中&#xff0c;通过指针可以找到该字符串&#xff08;千万不要…

配置华为交换机环路检测案例

知识改变命运&#xff0c;技术就是要分享&#xff0c;有问题随时联系&#xff0c;免费答疑&#xff0c;欢迎联系&#xff01; ①微思网络&#xff0c;始于2002年&#xff01;专注IT认证培训22年。 ② 领取学习资料/课程咨询&#xff1a;小美老师&#xff08;wx&#xff09;&…

使用采购管理软件构建更高效的采购模式

采购流程是企业整个采购部门的关键要素。无论企业规模大小&#xff0c;构建采购流程的模式都将直接影响企业控制成本、管理风险和保持流程弹性的能力。 下面我们将解释采购模式的类型、优缺点&#xff0c;以及如何确定哪种模式最适合你的采购部门。 集中采购的优缺点 在集中采…

关于腾讯云服务器“地域”选择,地域四点因素请牢记!

腾讯云服务器地域怎么选择&#xff1f;不同地域之间有什么区别&#xff1f;腾讯云哪个地域好&#xff1f;地域选择遵循就近原则&#xff0c;访客距离地域越近网络延迟越低&#xff0c;速度越快。腾讯云百科txybk.com告诉大家关于地域的选择还有很多因素&#xff0c;地域节点选择…

关于nginx做正向代理的那些事

声明&#xff1a;该文章只是用于技术探索的实践与讨论&#xff0c;没有其他用途。 准备&#xff1a; 一台能访问外网的服务器&#xff1b;一个域名&#xff0c;映射到上面的服务器&#xff1b;https的证书及密钥&#xff1b;nginx安装包&#xff1b; 协议使用&#xff1a; 开…

neo4j网页无法打开,启动一会儿后自动关闭,查看neo4j status显示Neo4j is not running.

目录 前情提要User limit of inotify watches reached无法访问此网站 前情提要 公司停电&#xff0c;服务器未能幸免&#xff0c;发现无法访问此网站&#xff0c;http://0.0.0.0:7474 在此之前都还好着 User limit of inotify watches reached (base) [rootlocalhost ~]# n…

ctf_show笔记篇(web入门---sql注入)171-189

sql注入 171&#xff1a;简单的sql注入&#xff0c;尝试万能密码直接过 172&#xff1a;基础联合查询可过 173&#xff1a;过滤flag那就利用substr少取几个flag的名字或者replace 174&#xff1a;两种方法&#xff0c;使用盲注或者利用replace嵌套替换&#xff0c;然后在逆…

新 树莓派4B 温湿度监测 基于debian12的树莓派OS

前言 本文旨在完成通过外接温湿度传感器至树莓派使得树莓派不断记录并存储温湿度数据 这个领域有很多文章&#xff0c;但是部分文章已经缺乏了时效性&#xff0c;在最新系统不适用&#xff0c;本文目前适用 硬件 硬件连接 温湿度传感器常选用DHT11和DHT22&#xff0c;淘宝…

No transform from [base_footprint] to [base_link]

需要查看这两个坐标系之间的转换 果然&#xff0c;demo05_car_base中父坐标系是base_footprint&#xff0c;意思是从base_footprint到base_link的转换&#xff0c;而不是从固定坐标系base_link到base_footprint 修改&#xff1a; 父坐标系修改成base_link即可

1356:计算(calc)

【算法分析】解法1&#xff1a;中缀表达式直接求值 1、设数字栈、运算符栈。设数组表示运算符优先级&#xff0c;其中(优先级最高&#xff0c;)优先级最低。 从左向右扫描表达式字符串&#xff1a; 2、遇到数字时&#xff0c;入数字栈。 3、遇到运算符时&#xff0c;入栈条件为…

20240314一种各向同性负泊松比多孔材料的设计

Design of a porous material with isotropic negative Poisson’s ratio DOI&#xff1a;http://dx.doi.org/10.1016/j.mechmat.2016.02.012 摘要&#xff1a;本文提出了一种具有全方位负泊松比的二维多孔体的设计方法。孔隙的六边形周期性分布使力学性能&#xff08;泊松比…

计算机msvcr120.dll丢失怎样修复,教你5种方法轻松搞定

我们在玩游戏运行软件的时候&#xff0c;电脑系统提示无法启动此程序&#xff0c;因为计算机中丢失MSVCR120.dll&#xff0c;尝试重新安装该程序以解决此问题。究其原因&#xff0c;是由于在我们的计算机系统中&#xff0c;发现缺失了一个至关重要的动态链接库文件——MSVCR120…

国外visa卡怎么办理,可充ChatGPTPLUS、Claude、Midjourney

很多小伙都在使用ChatGPT&#xff0c;但是想充值ChatGPTPLUS缺需要国外的visa卡&#xff0c;拿自己的银联卡&#xff0c;尝试了好多次还是不行&#xff0c;其实用一张国外的visa卡几分钟就可以升级好 办理国外visa卡&#xff0c;点击获取 国外的visa卡&#xff0c;具体要看你…
最新文章