《栈和队列》的模拟实现(顺序栈) (链队列)

news2024/11/17 9:54:29

目录

前言:

栈和队列:

栈:

队列:

模拟实现《栈》:

1.typedef数据类型

2.初始化栈 

3.销毁栈

4.入栈

5.出栈

6.取栈顶元素

7.判断栈是否为空

8.栈的大小

9.打印栈

模拟实现《队列》 :

1.typedef数据类型

2.初始化队列

3.销毁队列

 4.入队列

5.出队列

6.取队头

7.取队尾

8.判断队列是否为空

9.队列的元素个数

 10.打印队列

总结:


 

前言:

我们在上几篇的blog中,对于顺序表和两种链表都进行了模拟实现,已经相关的Leecode的oj题目我们都已经见识过了,下面我们就来对我们所学习的顺序表和链表进行提高练习,那就不得动手来实现实现《栈和队列》了。

栈和队列:

栈:

栈(Stack)是一种数据结构,可以理解为“一摞书”,它的特点是只能在一端进行操作,也就是称为栈顶(top),另一端称为栈底(bottom)。栈的基本操作有两个:push(入栈)和pop(出栈)。push操作往栈顶添加元素,pop操作从栈顶删除元素。

栈的特点是先进后出(Last In First Out,LIFO),即后

加入的元素先被取出。这种特性使得栈常常被用来处理一些具有“后效性”的问题,比如递归的函数调用、表达式求值、括号匹配、浏览器的“前进”和“后退”功能等等。

示意图:

  +---+         <- 栈顶
  | 3 |
  +---+
  | 2 |
  +---+
  | 1 |
  +---+         <- 栈底

队列:

队列是一种具有特定操作的数据结构,遵循“先进先出”(First In, First Out,FIFO)的原则。

示意图:

  Front                          Rear
    |                             |
  +---+  +---+  +---+  +---+  +---+
  | 1 |  | 2 |  | 3 |  | 4 |  | 5 |
  +---+  +---+  +---+  +---+  +---+
 

在这个示意图中,队列的前端(Front)指向队列的第一个元素,队列的后端(Rear)指向队列的最后一个元素。元素1最先进队列,然后是2、3、4、5。如果要出队列,将首先出队列的是元素1,然后是2、3、4、5。

队列的基本操作包括:

  • enqueue:将元素加入队列的末尾。
  • dequeue:从队列的前端移除元素。
  • front:获取队列的前端元素,但不移除。
  • isEmpty:检查队列是否为空。

队列通常用于模拟实际情况,例如任务调度、广度优先搜索等场景。在编程中,队列是一种常见的数据结构。

模拟实现《栈》:

1.typedef数据类型

typedef int STDataType;

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

由于这部分与咱们上次将的顺序表的实现,也就是通讯录大为相似,所以在这里我也不过多赘述,有需要的同学可以访问顺序表的blog:

《动态顺序表》的实现-CSDN博客

2.初始化栈 

void STInit(ST* pst)
{
	assert(pst);
	pst->a = NULL;
	pst->capacity = 0;
	pst->top = -1;
}

 这里要注意的是,在之前的顺序表中我们是定义了size来表示数组的长度,但是在这里,我们是利用top来定义的栈顶元素,并将其初始化为-1。

其实初始化为0还是初始化为-1都可以,没有过多的讲究,如果初始化为0的话,我们在后续判断栈是否为空理解起来就显得十分麻烦。

如果是定义top = -1,就显得尤为轻松。

在此我们统一定义top = -1.

3.销毁栈

void STDestory(ST* pst)
{
	assert(pst);
	free(pst->a);
	pst->a = NULL;
	pst->top = -1;
	pst->capacity = 0;
}

4.入栈

void STPush(ST* pst, STDataType x)
{
	assert(pst);
	int newcapacity = (pst->capacity == 0) ? 4 : 2 * (pst->capacity);
	STDataType* tmp = (STDataType*)realloc(pst->a, sizeof(STDataType) * newcapacity);
	if (tmp == NULL)
	{
		perror("STPush -> realloc");
		exit(-1);
	}
	pst->a = tmp;
	pst->capacity = newcapacity;
	pst->top++;
	pst->a[pst->top] = x;

}

我们在此作出了与顺序表和通讯录不一样的地方,就是我们在此并没有再创建一个函数用来实现判断扩容,因为我们全部函数中有且只有入栈函数要进行判断是否需要扩容的操作。

因此我们直接在函数内部实现即可。

5.出栈

void STPop(ST* pst)
{
	assert(pst);
	if (pst->top != -1)
	{
		pst->top--;
	}
}

6.取栈顶元素

STDataType STTop(ST* pst)
{
	assert(pst);
	if (pst->top != -1)
	{
		return pst->a[pst->top];
	}
	return -1;
}

7.判断栈是否为空

bool STEmpty(ST* pst)
{
	assert(pst);
	if (pst->top == -1)
	{
		return true;
	}
	return false;
}

8.栈的大小

int STSize(ST* pst)
{
	assert(pst);
	return pst->top + 1;
}

9.打印栈

void STPrint(ST* pst)
{
	assert(pst);
	for (int i = 0; i <= pst->top; i++)
	{
		printf("%d  ", pst->a[i]);
	}
}

以上就是栈的全部模拟实现,因为我们用的是顺序表来模拟实现栈,所以大部分内容参考之前blog即可,接下来我们一起实现队列。


 

模拟实现《队列》 :

1.typedef数据类型

typedef int QDataType;

typedef struct QueueNode
{
	QDataType val;
	struct QueueNode* next;
}QNode;

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

我们在本文实现的是链队列,但是不同于我们之前对单链表的实现,由于我们在此需要经常进行找尾操作,而且尾指针时不时会发生改变,因此我们可以再创建一个结构体,里面包含了我们所需要的两个指针,一个头指针和一个尾指针,这样我们在调试的时候也不必需要传二级指针了。

如图:

 可能现在还不是很理解,接下来我们动手实现几个函数,就能迎刃而解了。

2.初始化队列

void QueueInit(Queue* pq)
{
	pq->sz = 0;
	pq->phead = pq->ptail = NULL;
}

3.销毁队列

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

 4.入队列

void QueuePush(Queue* pq, QDataType x)
{
	assert(pq);
	QNode* newnode = (QNode*)malloc(sizeof(QNode));
	if (newnode == NULL)
	{
		perror("QueuePush -> malloc");
		exit(-1);
	}
	newnode->val = x;
	newnode->next = NULL;

	if (pq->phead == NULL)
	{
		pq->phead = pq->ptail = newnode;
	}
	else
	{
		pq->ptail->next = newnode;
		pq->ptail = newnode;
	}
	pq->sz++;

}

因为是链表,所以我们入队列的时候要动态开辟出一个新的节点来存放数据而此时链表是空的,而队列本质是尾插,头删,所以我们才采用的链表。如图:

继续入队时,注意仔细观察*phead和*ptail的变化。

 

后面当我想要加入数据的时候就以此类推。

5.出队列

void QueuePop(Queue* pq)
{
	assert(pq);
	assert(pq->phead);
	if (pq->ptail == pq->phead)
	{
		free(pq->phead);
		pq->phead = pq->ptail = NULL;
	}
	else
	{
		QNode* cur = pq->phead->next;
		free(pq->phead);
		pq->phead = cur;
		pq->sz--;
	}
}

由于队列是“先进先出”实际上是链表的头删操作。

这里要注意的是,存在两种情况

1.队列仅有一个节点

2.队列多个节点

当队列仅有一个节点时,随着对pq->phead释放,不仅要将pq->phead置为NULL,

同时也要对pq->ptail进行操作!!!

6.取队头

QDataType QueueFront(Queue* pq)
{
	assert(pq);
	assert(pq->phead);
	return pq->phead->val;
}

7.取队尾

QDataType QueueBack(Queue* pq)
{
	assert(pq);
	assert(pq->phead);
	return pq->ptail->val;
}

8.判断队列是否为空

bool QueueEmpty(Queue* pq)
{
	if (pq->phead != NULL)
	{
		return false;
	}
	return true;
}

9.队列的元素个数

int QueueSize(Queue* pq)
{
	return pq->sz;
}

 10.打印队列

void QueuePrint(Queue* pq)
{
	assert(pq);
	QNode* cur = pq->phead;
	while (cur)
	{
		printf("%d->", cur->val);
		cur = cur->next;
	}
	printf("NULL\n");
}

总结:

以上就是栈和队列的模拟实现。

《栈》的源代码:Data structures amd algorithms: 关于数据结构和算法的代码 - Gitee.com

《队列》的源代码:Data structures amd algorithms: 关于数据结构和算法的代码 - Gitee.com 

记住

“坐而言不如起而行”

Action speak louder than words! 

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

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

相关文章

基于C#实现KMP算法

一、BF 算法 如果让你写字符串的模式匹配&#xff0c;你可能会很快的写出朴素的 bf 算法&#xff0c;至少问题是解决了&#xff0c;我想大家很清楚的知道它的时间复杂度为 O&#xff08;MN&#xff09;&#xff0c;原因很简单&#xff0c;主串和模式串失配的时候&#xff0c;我…

做黄金代理可以代理什么品种?

近几年&#xff0c;黄金代理这个职业发展的比较迅猛&#xff0c;主要是受金融环境越来越稳定、金融投资越来越发达的大势所推动。那些有意想做黄金代理的朋友就会有疑问&#xff0c;做了黄金代理可以代理什么品种的&#xff1f; 其实广义上来说&#xff0c;黄金代理有很多种&am…

【Pytorch】Visualization of Feature Maps(1)

学习参考来自 CNN可视化Convolutional Featureshttps://github.com/wmn7/ML_Practice/blob/master/2019_05_27/filter_visualizer.ipynb 文章目录 filter 的激活值 filter 的激活值 原理&#xff1a;找一张图片&#xff0c;使得某个 layer 的 filter 的激活值最大&#xff0c…

C#核心笔记——(二)C#语言基础

一、C#程序 1.1 基础程序 using System; //引入命名空间namespace CsharpTest //将以下类定义在CsharpTest命名空间中 {internal class TestProgram //定义TestProgram类{public void Test() { }//定义Test方法} }方法是C#中的诸多种类的函数之一。另一种函数*&#xff0c;还…

机器学习介绍与分类

随着科学技术的不断发展&#xff0c;机器学习作为人工智能领域的重要分支&#xff0c;正逐渐引起广泛的关注和应用。本文将介绍机器学习的基本概念、原理和分类方法&#xff0c;帮助读者更好地理解和应用机器学习技术。 一、机器学习的基本概念 机器学习是一种通过从数据中学…

每日汇评:美日在两个月低点附近似乎较为脆弱,熊市可能会在FOMC会议纪要公布前暂停

美元/日元跌至两个月低点&#xff0c;并受到多种因素的压力&#xff1b; 美联储鸽派预期和美国债券收益率下降继续令美元承压&#xff1b; 美日利差缩小以及日本央行政策转变的押注提振了日元&#xff1b; 美元/日元货币对在周二持续第四天承受着沉重的卖压&#xff0c;同时也标…

Vue+Swiper实现轮播图效果

效果展示 实现了自带切换按钮在图片外部实现了自定义的切换按钮 背景 在项目中使用到了轮播图&#xff0c;实现点击上一张下一张时实现循环显示&#xff0c;同时预览两个图片&#xff0c;并加以文字对图片的说明。 设计 使用 Swiper 插件&#xff0c;可以实现当前这个需求。…

linux制作 ext4镜像image 脚本demo

结构如下&#xff1a; build_linux_targetfs.sh #!/bin/bashCHECK_MARK"\033[0;32m\xE2\x9C\x94\033[0m" X_MARK"\033[0;1;31mX\033[0m"export TOP_DIR$PWD export TARGET_IMAGE_PATH$TOP_DIR/filesystem/targetfs-images export BSP_IMAGE_PATH${TOP_DI…

数据库表的内连接和外连接

1.内连接查询语法 -- 隐式内链接 SELECT 字段列表 FROM 表1&#xff0c;表2WHERE 条件&#xff1b; -- 显示内连接 select 字段列表 from 表1 [inner] join 表2 on 条件&#xff1b; 如果两个表没用进行内连接&#xff0c;会生成笛卡尔积。A集合和B集合全部元素进行排列组合。 …

关于校园网使用罗技flow功能

目录 情况概述问题及解决方案 情况概述 我目前设备是一台Macbook air m1处理器&#xff0c;学校给配了一台windows台式&#xff0c;台式机不能连蓝牙&#xff0c;不能连wifi&#xff0c;只能用网线&#xff0c;我的需求是想让mac和windows共用一套键鼠&#xff0c;在了解到罗技…

万宾科技智能井盖的效果怎么样?

日常出行过程中&#xff0c;人们最不想看到交通拥堵或者道路维修等现象&#xff0c;因为这代表出行受到影响甚至会导致不能按时赴约等。所以城市路面的安全和稳定&#xff0c;是市民朋友非常关心的话题。骑行在路上的时候&#xff0c;如果经过井盖时发出异常声响&#xff0c;骑…

福州大学《嵌入式系统综合设计》实验四:边缘检测

一、实验目的 BMCV 提供了一套基于 Sophon AI 芯片优化的机器视觉库&#xff0c;通过利用芯片的 TPU 和 VPP模块&#xff0c;可以完成色彩空间转换、尺度变换、仿射变换、透射变换、线性变换、画框、JPEG 编解码、BASE64 编解码、NMS、排序、特征匹配等操作。 本实验的目的是…

navicat --CSV导出数据乱码情况(三种情况解决方式)

CSV导出数据乱码情况分析及处理 在navicat 中有很多导出方式&#xff0c;大家都知道csv导出要比xlse要快很多&#xff0c;但是在使用csv导出时要防止乱码情况&#xff0c; 下面我列出三种处理方式&#xff08;如有其他方式大家可以帮忙补充一下&#xff09;&#xff1a; 文章目…

使用Python的Turtle库绘制一个心形图像(含详细Python代码与注释)

1.1引言&#xff1a; Python的Turtle库是一个非常实用的图形绘制库&#xff0c;它让我们可以使用简单的命令来绘制各种图形。这个库特别适合用来绘制几何图形&#xff0c;尤其是那些需要精细控制的图形。在本博客中&#xff0c;我们将使用Turtle库来绘制一个具体的图形。 1.2…

如何验证命令执行漏洞(无回显)

如何验证命令执行漏洞&#xff08;无回显&#xff09; 使用yakit&#xff0c;选择dnslog模块 点击生成一个可用域名 以dvwa为例 命令执行ping一下刚才的域名 随后yakit中会出现回显信息&#xff0c;以此证明拥有命令执行漏洞 信息&#xff0c;以此证明拥有命令执行漏洞

WMS系统先验后收策略

在制造业工厂的仓库管理中&#xff0c;确保物料的质量和数量是至关重要的。传统的仓库管理方式往往采用“先收后验”策略&#xff0c;即先接收物料&#xff0c;然后再进行质量检验。然而&#xff0c;这种方式存在一定的风险&#xff0c;例如不良品流入、数量不准确等问题。为了…

洛谷 P4568 [JLOI2011] 飞行路线 pytho解析

P4568 [JLOI2011] 飞行路线 pytho解析 时间&#xff1a;2023.11.20 题目地址&#xff1a;[JLOI2011] 飞行路线 题目分析 对于这个题呢就是最短路的问题了。那就可以用Dijkstra 算法&#xff0c;唯一不同的地方就是有免费的机票次数&#xff0c;那我们就先不考虑这个&#xf…

HTML+CSS+ElementUI搭建个人博客页面(纯前端)

网站演示 搭建过程 html部分 首先下载Vue2&#xff0c;ElementUI等插件&#xff0c;放在你的本地。我这里为了运行方便&#xff0c;把代码放在了一个框架里运行。 下载后引入部分 <link rel"stylesheet" href"{{URL::asset(elementui/lib/theme-chalk/ind…

最新最全系列之Selenium:传入webdriver驱动的新方法 Service()函数;以前的executable_path报警告,即将弃用

传入webdriver驱动的新方法 Service()函数&#xff1b;以前的executable_path报警告&#xff0c;即将弃用 以前的方法 举例&#xff1a;webdriver.Chrome(executable_pathdriver_path)&#xff1b;看提示警告&#xff0c;提示该方法即将被弃用&#xff1b;如下图&#xff1a; …