栈和队列详解(1)

news2025/2/25 5:51:48

目录

一、什么是栈?

二、创建一个我们自己的栈

1.前置准备

1.1需要的三个文件

 1.2结构体的创建和头文件的引用

 2.接口的实现

2.1初始化栈结构体

2.2尾插(压栈)

2.3栈存放的元素个数和判断栈是否为空

2.4获取栈顶元素

2.5出栈

2.6摧毁栈

2.7测试接口

三、所有代码

1.接口实现

2.栈的头文件

3.测试代码


一、什么是栈?

栈是计算机科学中的一种数据结构,它是一种线性结构,按照先进后出的原则进行存储和访问。栈通常也称作堆栈、堆叠或简称电梯。

在栈中,添加或删除元素只能在同一端进行,这一端被称为栈顶。当向栈顶添加一个元素时,我们称之为入栈;当从栈顶删除一个元素时,我们称之为出栈。对于栈的一项重要特性是,每次只能访问位于栈顶的元素,因此栈是不支持随机访问的数据结构。栈和我们之前所学习过的顺序表很相似,区别就在于,顺序表支持尾插尾删,头插头删,而栈只支持后进先出也就是只支持尾插尾删。它就像一个竖井,当队伍走进这个井后,要退出来也只能是队伍的末端最先退出。这里博主给大家画了张图,方便大家好理解。

二、创建一个我们自己的栈

1.前置准备

1.1需要的三个文件

在开始之前,我们最好创建三个文件,一个放栈函数的实现,一个用来测试栈函数,最后一个放栈函数的引用和头文件的引用,这样到时侯想要使用栈函数直接包这一个头文件即可。创建完之后,呈现出来的效果与下图差不多即可。

 1.2结构体的创建和头文件的引用

在进行操作之前,我们先在存放头文件和栈函数的文件中包几个常用的头文件,并且定义一下栈的结构体类型,栈只需要后进先出,也就是尾插尾删,那么使用数组亦或者使用链表实现难度是差不多的,这里我们使用数组实现。

使用数组实现要注意的便是,我们应该使用数组指针的形式实现,而不是单纯就一个数组,如果单纯就一个数组 ,就是一个静态的栈空间,而静态的栈空间在实际中几乎是没有任何用处的,这里我们要实现的是动态的。既然要实现的是动态的,那么我们应该想办法存储一下数组存放的元素个数,以及这个数组的容量大小,这样才能够判断出这个栈空间是否满了,从而根据需求扩大空间。因此我们创建的结构体应该要有一个数组指针,一个存放容量的大小,一个存放数组里面已经存放的元素个数。

最后呈现出来的差不多就是这个样子

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
typedef int STDateType;
//到时修改类型时只用改这里的一个就可以,不需要一个个修改
//同样,这也是为了和单一的int作区分
typedef struct stack
{
	STDateType* stack;//栈空间
	int top;//已经存放的元素个数
	int capacity;//容量大小
}ST;//创建栈的结构体,并将它的名字自定义为ST

 2.接口的实现

2.1初始化栈结构体

初始化栈结构体,一共有三步,第一步是将栈空间的空间开辟好,第二步是初始化栈结构体的容量,最后一步初始化栈结构体中存放元素个数的变量。

void init_stack(ST* s1)
{
	assert(s1);
	//传过来的是一个指针,不应该是空指针,空指针无法操作,故断言
	s1->stack = (STDateType*)malloc(sizeof(STDateType)*4);
	//将栈空间初始化成只可以存放4个元素的空间
	if (s1->stack == NULL)
	{
		perror("init_stack");
		//如果连基本的初始化都完成失败,就没有进行下去的必要了
		exit(-1);
	}
	s1->capacity = 4;
	//容量初始化成4
	s1->top = 0;
	//已经存放的元素个数初始化为0
}

2.2尾插(压栈)

压栈需要注意的一点便是,当栈满了的时候我们应该要考虑扩容

void push_stack(ST* s1, STDateType x)
{
	assert(s1);
	if (s1->capacity == s1->top)
	//空间满了,要扩容
	{
		int newcapacity = (s1->capacity) * 2;
		//扩容至原来的两倍
		s1->stack=(STDateType*)realloc(s1->stack, sizeof(STDateType)*newcapacity);
		if (s1->stack == NULL)
		{
			perror("push_stack");
			exit(-1);//扩容失败也别玩了
		}
		s1->capacity = newcapacity;
		//扩容成功,容量改变
	}
	s1->stack[s1->top] = x;//压栈
	s1->top++;//压栈成功,存放的元素个数+1
}

2.3栈存放的元素个数和判断栈是否为空

可能有小伙伴不明白为什么又要设计这两个接口,因为这两个信息都可以直接通过栈的结构体获得,好像没什么作用啊。设计这两个接口并使用它们而不是直接通过结构体的内容来判断是因为,当我们的需求发生改变了,所创建的结构体可能也会跟着修改,可能提取的方式会发生一些改变。如果我们在使用栈的时候已经直接通过结构体的内容进行了多次的判断,那么我们要修改起来,要修改多次,很不方便,这样做的好处就是只用修改一次即可。

栈存放的元素个数

int size_stack(ST* s1)
{
	assert(s1);
	return s1->top;
	//返回元素个数
}

 判断栈是否为空

int empty_stack(ST* s1)
{
	assert(s1);
	return s1->top == 0;
	//当存放的元素个数等于0意味着空
    //为空返回1(真),不为空返回0(假)
}

2.4获取栈顶元素

需要注意的点是,首先栈不能够是空的,其次top是元素的个数,不是当前元素的下标,上一个才是对应元素的下标。举个例子,当栈有一个元素时,top就为1了,而1指的是数组的第二个元素。

STDateType sttop(ST* s1)
{
	assert(s1);
	assert(!empty_stack(s1));
	//栈不能为空,为空则出不了栈
	return s1->stack[s1->top - 1];
}

2.5出栈

出栈相当简单,直接将存放元素个数的内容-1即可,如此就不可能再次访问到它

void pop_stack(ST* s1)
{
	assert(s1);
	assert(!empty_stack(s1));
	//栈不能为空
	s1->top--;
}

2.6摧毁栈

这个很简单,没什么好说的,直接将栈结构体的空间释放掉,并将对应的内容归零即可。

void destory_stack(ST* s1)
{
	assert(s1);
	s1->capacity = 0;
	s1->top = 0;
	free(s1->stack);
	s1->stack = NULL;
}

2.7测试接口

测试代码:
 

#include"stack.h"
void test1()
{
	ST s1;
	init_stack(&s1);
	push_stack(&s1, 1);
	push_stack(&s1, 2);
	push_stack(&s1, 3);
	push_stack(&s1, 4);
	push_stack(&s1, 5);
	printf("%d\n", size_stack(&s1));
	while (!empty_stack(&s1))
	{
		printf("%d ", sttop(&s1));
		pop_stack(&s1);
		//边打印栈顶元素边出栈
	}
	destory_stack(&s1);
    //摧毁栈
}
int main()
{
	test1();
}

测试结果:

三、所有代码

1.接口实现

#include"stack.h"
void init_stack(ST* s1)
{
	assert(s1);
	//传过来的是一个指针,不应该是空指针,空指针无法操作,故断言
	s1->stack = (STDateType*)malloc(sizeof(STDateType)*4);
	//将栈空间初始化成只可以存放4个元素的空间
	if (s1->stack == NULL)
	{
		perror("init_stack");
		//如果连基本的初始化都完成失败,就没有进行下去的必要了
		exit(-1);
	}
	s1->capacity = 4;
	//容量初始化成4
	s1->top = 0;
	//已经存放的元素个数初始化为0
}
void push_stack(ST* s1, STDateType x)
{
	assert(s1);
	if (s1->capacity == s1->top)
	//空间满了,要扩容
	{
		int newcapacity = (s1->capacity) * 2;
		//扩容至原来的两倍
		s1->stack=(STDateType*)realloc(s1->stack, sizeof(STDateType)*newcapacity);
		if (s1->stack == NULL)
		{
			perror("push_stack");
			exit(-1);//扩容失败也别玩了
		}
		s1->capacity = newcapacity;
		//扩容成功,容量改变
	}
	s1->stack[s1->top] = x;//压栈
	s1->top++;//压栈成功,存放的元素个数+1
}
void pop_stack(ST* s1)
{
	assert(s1);
	assert(!empty_stack(s1));
	//栈不能为空
	s1->top--;
}
STDateType sttop(ST* s1)
{
	assert(s1);
	assert(!empty_stack(s1));
	//栈不能为空,为空则出不了栈
	return s1->stack[s1->top - 1];
}
int size_stack(ST* s1)
{
	assert(s1);
	return s1->top;
	//返回元素个数
}
int empty_stack(ST* s1)
{
	assert(s1);
	return s1->top == 0;
	//当存放的元素个数等于0意味着空
	//为空返回1(真),不为空返回0(假)
}
void destory_stack(ST* s1)
{
	assert(s1);
	s1->capacity = 0;
	s1->top = 0;
	free(s1->stack);
	s1->stack = NULL;
}

2.栈的头文件

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
typedef int STDateType;
//到时修改类型时只用改这里的一个就可以,不需要一个个修改
//同样,这也是为了和单一的int作区分
typedef struct stack
{
	STDateType* stack;//栈空间
	int top;//已经存放的元素个数
	int capacity;//容量大小
}ST;//创建栈的结构体,并将它的名字自定义为ST
void init_stack(ST* s1);
void push_stack(ST* s1,STDateType x);
STDateType sttop(ST* s1);
int size_stack(ST*s1);
int empty_stack(ST* s1);
void destory_stack(ST* s1);
void pop_stack(ST* s1);

3.测试代码

#include"stack.h"
void test1()
{
	ST s1;
	init_stack(&s1);
	push_stack(&s1, 1);
	push_stack(&s1, 2);
	push_stack(&s1, 3);
	push_stack(&s1, 4);
	push_stack(&s1, 5);
	printf("%d\n", size_stack(&s1));
	while (!empty_stack(&s1))
	{
		printf("%d ", sttop(&s1));
		pop_stack(&s1);
		//边打印栈顶元素边出栈
	}
	destory_stack(&s1);
    //摧毁栈
}
int main()
{
	test1();
}

好了,栈就说完了,再来个三小时,博主爆肝一篇队列的。

感谢各位友友的来访,祝各位友友前程似锦O(∩_∩)O

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

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

相关文章

ipad触控笔有必要买原装吗?平价触控笔排行榜

“ipad好买&#xff0c;但是ipad的配件不好买”&#xff0c;我想大多数人都会遇到这样的问题&#xff0c;如果你想要购买像Apple Pencil这样的官方配件&#xff0c;有很难舍得入手&#xff0c;因为一款Apple Pencil的价格已经接近一千元了。正如很多人不会购买价格不菲的苹果官…

Falco操作系统安全威胁监测利器

原理简介 Falco是一个开源的云原生安全工具&#xff0c;用于检测和防御容器和云原生环境中的安全威胁。它基于Linux内核的eBPF技术&#xff0c;通过监控系统调用和内核事件来实现安全检测和响应。 具体来说&#xff0c;Falco的实现原理如下&#xff1a; 1. 内核模块&#xf…

「展会预告」飞凌嵌入式邀您共聚Elexcon 2023深圳国际电子展

Elexcon 2023深圳国际电子展将于8月23~25日在深圳会展中心&#xff08;福田&#xff09;隆重举行&#xff0c;飞凌嵌入式将于本届展会亮相&#xff0c;展位号1Z55。 本届展会规模达40,000平方米&#xff0c;预计将吸引600家全球优质品牌厂商、50,000专业观众齐聚现场&#xff…

登录界面中图片验证码的生成和校验

一、用pillpw生成图片验证码 1、安装pillow pip install pip install pillow2、下载字体 比如&#xff1a;Monaco.ttf 3、实现生成验证码的方法 该方法返回一个img ,可以把这个img图片保存到内存中&#xff0c;也可以以文件形式保存到磁盘&#xff0c;还返回了验证码的文字…

线上小程序电影票订单录入系统开发--Java、app、H5

在当今数字化时代&#xff0c;电影票订单的分销渠道和智能化分类已经成为电影产业不可或缺的一部分。为了满足这一需求&#xff0c;开发一款H5用户端电影票订单分销渠道智能分类小程序具有重要的实际意义。下面是该小程序开发的详细步骤。 一、需求分析 在开发H5用户端电影票…

用vim打开后中文乱码怎么办

Vim中打开文件乱码主要是文件编码问题。用户可以参考如下解决方法。 1、用vim打开.vimrc配置文件 vim ~/.vimrc**注意&#xff1a;**如果用户根目录下没有.vimrc文件就把/etc/vim/vimrc文件复制过来直接用 cp /etc/vim/vimrc ~/.vimrc2、在.vimrc中加入如下内容 set termen…

【选择排序】直接选择排序 与 堆排序

目录 1. 排序的概念&#xff1a; 2.选择排序的基本思想 3.直接选择排序 4.堆排序 1. 排序的概念&#xff1a; 排序&#xff1a;所谓排序&#xff0c;就是使一串记录&#xff0c;按照其中的某个或某些关键字的大小&#xff0c;递增或递减的排列起来的操作。 稳定性&#xf…

MySQL_DQL语句(查询语句以及常用函数)

基础查询 不带条件的查询查询多个字段 语法&#xff1a; #查询指定字段的数据 SELECT 字段1, 字段2, 字段3 ... FROM 表名 ; #查询表中全部字段的数据 SELECT * FROM 表名 ;案例&#xff1a;查询表中所有信息数据 SELECT * FROM employee;案例&#xff1a;查询表中姓名和性别…

IntellIJ Idea 连接数据库-MySql

前言&#xff1a;可以用mariaDB工具&#xff0c;在本地创建服务器主机和数据库&#xff0c;而后用intellIJ Idea尝试连接 MariaDB创建数据库练习 1.IntellIJ Idea打开界面右侧Database工具&#xff0c;选择MySQL数据库。 2.填写数据库账号密码&#xff0c;地址端口号&#xff…

树莓派安装Ubuntu系统(无屏幕)

树莓派安装ubuntu系统 前言 软件需要: 1.方案一 win32diskimager-1.0.0-install.exe SDFormatterha Ubuntu镜像&#xff08;可以官网下载也可以清华源&#xff09; 方案二: 树莓派镜像烧录器 树莓派镜像烧录器直达下载 硬件需要: 64GB内存卡&#xff08;推荐Sanddisk Ultra&am…

程序员自由创业周记#6:劝退

程序员自由创业周记#6&#xff1a;劝退 photo-1547496614-154dee7fd157 这是一位程序员进行独立开发创业的记录&#xff0c;将分享创业过程中的所思所想以及收支明细。 劝退 如果一位程序员问我要不要进行独立开发创业&#xff0c;我100%会建议他不要冲动&#xff0c;因为这条路…

话题暴涨2344%,“妆面减负”成大势,小红书数据发掘潮流新趋势

Less is more&#xff0c;简约风吹遍时尚界&#xff0c;小红书上继Clean fit穿搭风热度高涨后&#xff0c;Clean makeup的妆容也逐渐走红&#xff0c;成为当下年轻人争相更风的时髦新趋势。 2023时尚新趋势&#xff0c;Clean fit→Clean makeup Clean makeup&#xff0c;即轻妆…

腾讯云轻量应用服务器端口怎么打开?图文方法来了

腾讯云轻量应用服务器端口放行在哪设置&#xff1f;在防火墙中可以开启端口号&#xff0c;腾讯云轻量应用服务器端口怎么开通&#xff1f;在轻量服务器管理控制台的防火墙中开启端口&#xff0c;如果是CVM云服务器在安全组中开通&#xff0c;腾讯云服务器网以轻量应用服务器开通…

MySQL数据库-基础篇

基础篇 一、SQL 分类 DDL-数据库操作 查询 创建表 数据类型 数值类型 字符串类型 日期类型 添加 修改 删除字段 修改表名 删除表 小结 DML-数据增删改 添加数据 修改数据 删除数据 小结 DQL-数据查询数据 基本查询 条件查询 聚合函数 分组查询 排序查询 分页查…

图片转表格方法分享,几个步骤轻松转换

在日常工作和学习中&#xff0c;我们经常会遇到需要将图片中的表格转换为可编辑的电子表格的情况。这时候&#xff0c;我们通常会手动一个一个地输入表格中的数据&#xff0c;费时费力&#xff0c;还容易出错。但是&#xff0c;其实有一些简单的方法可以帮助我们快速地将图片转…

关于npoi插入一条斜向上得线记录一下

在使用hssf可以直接按照行列插入。 HSSFWorkbook book new HSSFWorkbook();HSSFSheet sheet1 (HSSFSheet)book.CreateSheet("Sheet1");HSSFPatriarch patriarch (HSSFPatriarch)sheet1.CreateDrawingPatriarch();HSSFClientAnchor a1 new HSSFClientAnchor(255, …

k8s service

1、认识Service 程序在容器中、容器在Pod中&#xff0c;可以通过pod的ip来访问应用程序&#xff0c;但是podIP会随着创建销毁而改变。由此&#xff0c;Service出现&#xff1a; Service会对提供同一个服务的多个pod进行聚合&#xff0c;并且提供一个统一的入口地址。通过访问…

摄影照片后期处理工具:Athentech Perfectly Clear Complete

Athentech Perfectly Clear Complete 是一款强悍便捷的LR图像清晰化滤镜插件&#xff0c;可以让你想要更好的处理照片&#xff0c;Perfectly Clear完美清晰掌握了智能图像校正的技术原理 &#xff0c;可以在很短的时间里创造出高质量的照片&#xff0c;所以你可以回到做你真正的…

ISO/IEC技术标准-RFID

ISO/IEC技术标准规定了RFID有关技术特征、技术参数和技术规范&#xff0c;主要包括ISO/IEC 18000(空中接口参数)、ISO/IEC 10536(密耦合、非接触集成电路卡)、ISO/IEC 15693(疏耦合、非接触集成电路卡)和ISO/IEC 14443(近耦合、非接触集成电路卡)等。ISO/IEC的RFID技术标准构成…

nginx的rewrite功能和案例介绍

一.定义 二.作用 1.调整用户浏览的url&#xff0c;模板更规范 2.提升搜索引擎网站给予用户的体验&#xff0c;可以将动态的url伪装成静态地址提供服务 3.在网站更换新域名后&#xff0c;可以通过旧域名访问到新域名 4.便于根据特殊变量1、客户信息进行url调整 三.区分地址…