数据结构---栈队列

news2025/1/20 1:37:49

栈和队列是我们数据结构中经常使用的数据结构,所以现在来了解一下栈和队列。


特点:

栈是一种特殊的线性表,其中进行数据插入和弹出的部分叫做栈顶,另一端叫做栈底。

只允许数据从栈顶压入,从栈顶弹出即先进后出的特点,也称LIFO  (Last In First Out)。

压栈:将数据从栈顶压入栈中。

弹栈:将栈顶的数据从栈中弹出。

实现:

接下来基于C语言来实现一个栈,及其增删查改功能:

栈的初始化:

对于栈,肯定要和链表一样进行数据结构定义,但是对于链表我们只需要开一个大小的空间即可,但是栈可能会压入多个数据,我们无法得知具体数目,所以我们一开始选择将栈的大小设置成为4,后续对栈容量进行动态扩容即可。

typedef struct stack {
	int* data;
	int size, top;
}stack;

stack* Stack_Init() {
	stack* p = (stack*)malloc(sizeof(stack));
	p->data = (int*)malloc(sizeof(int) * 4);
	p->size = 4;
	p->top = -1;
	return p;
}

栈的销毁:

既然我们使用malloc函数来分配了栈的内存,那么我们就需要设置一个函数来释放栈的内存空间:


void Stack_Free(stack* p) {
	if (p == NULL) {
		return;
	}
	free(p->data);
	free(p);
	return;
}

栈的压入操作:

在上文,我们考虑到了由于栈要压入未知数据量,所以我们不能固定栈的大小,则需要动态内存开辟,实现栈的容量的增加。

但是又考虑到另外一个问题,我们要增加多少容量呢?当数据量很大时,只增加个位数或十位数级别的容量对栈的帮助不大,任然需要频繁增加栈的容量,那么我们每次改变栈的容量时,将栈的容量翻一倍即可,以达到减少扩容次数的需要。

在思考完栈的容量管理后,栈的压入就变得简单了,只需要将栈的size位置放入数据并且让size+1即可。

int Stack_Push(int val, stack* p) {
	if ( (p->top) + 1 == p->size || p == NULL) {
		p->data=(int*)realloc(p,p==NULL?sizeof(int)*4:2*p->size*sizeof(int));
	}
	p->data[p->top + 1] = val;
	p->top += 1;
	return 1;
}

查询栈顶元素:

由于栈后进先出的特性,我们只能查找到栈顶元素

int top(stack* p) {
	if (p->top == -1) {
		return NULL;
	}
	return p->data[p->top];
}

栈的判空:

当栈中不含有元素时,我们则不能继续弹出栈顶的元素,所以我们需要判断栈内此时是否存有元素。

int Empty(stack* p) {
	if (p == NULL) {
		return NULL;
	}
	return (p->top == -1);
}

栈的弹出操作:

栈的弹出存在一种特殊情况即栈为空时弹出元素,此时弹出操作则为违法操作。

所以在弹出操作前,我们需要调用判空函数来判断弹出操作是否合法。

若栈内不为空,则弹出栈顶元素;若栈内为空,则返回NULL即可。

int Stack_Pop(stack* p) {
	if (Empty(p) ==0) {
		return 0;
	}
	p->top -= 1;
	return p->data[(p->top) + 1];
}

此外栈还可以由链表实现,由链表实现的栈则省去了栈的扩容操作,节约了时间。


队列:

特点:

队列也是一种特殊的线性表,其中进行数据插入的部分叫做队尾,弹出数据的部分叫做队首。

队列只允许数据从队尾压入,从队首弹出。

具有先进先出的特点,也称FIFO  (First In First Out)。

实现:

接下来是基于C语言实现队列及其增删查改的操作:

队列的初始化:

队列与栈相似,我们都需要对其进行数据结构的定义。

在定义完数据结构后,我们任然需要与栈一样考虑队列的大小管理,所以我们将队列的大小初始化为4。

typedef struct queue {
	int* data;
	int size, count, head, tail;
}queue;


//初始化队列
queue* Init_Queue(int n) {
	queue* p = (queue*)malloc(sizeof(queue));
	p->data = (int*)malloc(sizeof(int)*4);
	//让count,head,size,tail为0
	p->count = p->head = p->size = p->tail = 0;
	//返回该队列的首地址
	return p;
}

队列的销毁:

由于队列使用了malloc函数分配了内存,所以我们需要手动销毁queue的内存。

//定义一个函数用于释放队列的空间
void Queue_Free(queue* head) {
	if (head == NULL) {
		return;
	}
    free(head->data);
	free(head);
	return;
}

队列的插入操作:

队列与栈一样,当队列容量即将满时,我们将队列的大小翻一倍。

然后将数据插入到队列中即可:

void Queue_Insert(queue* p,int val){
    if(p->data==NULL || (p->count+1==p->size)){
        p->data=(int*)realloc(p->data,p->data==NULL?4:2*sizeof(int)*p->size);
        p->size*=2;
    }
    p->data[p->count++]=val;
    p->tail++;
    return;
}

队列的判空:

队列与栈一致,当队列为空时,弹出队首元素为违法操作,所以我们需要对队列进行判空


int Empty(queue* p) {
	return (p->count == 0);
}

队列的弹出操作:

与栈操作一致,当队列为空时,弹出元素为违法操作;队列不为空时,则弹出队首元素。

int Delete(queue* p) {
	//判断队列中是否为空
	if (Empty(p)) {
		return 0;
	}
	//让队首向后一个,含有的数据-1
	p->head += 1;
	p->count -= 1;
	return  p->data[p->head-1];
}

查询队首元素:

对于队列,我们只能查询队首的元素。

//输出队首的数据
int Queue_Front(queue* p) {
	return p->data[p->head];
}

队列也可以由链表实现,你能构思并且设计一个由链表构成的队列吗?


至此,队列和栈的讲解到此结束。

如果我的文章对你有所帮助,不妨给我个关注何点赞吧。

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

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

相关文章

Mac | Mac M 芯片应用意外退出问题

现象问题 电脑配置:MacBook Pro M1,系统 Sonoma 很多小伙伴新买了 M 芯片的 MacBook,在下载下应用后进行安装,安装成功后却无法打开,提示意外退出。报错如图 原因 部分应用过适配了 M 芯片,但还是有些应…

Windows配置共享文件夹

正文共:888 字 16 图,预估阅读时间:1 分钟 我们前面介绍了如果安装NAS工具(废物利用,矿渣装个黑群晖。家庭小NAS搞起来!),也介绍过如果配置远程桌面的多账号登录(Windows…

Apache Nemo: A Framework for Optimizing Distributed Data Processing——论文泛读

TOCS 2021 Paper 论文阅读笔记整理 问题 针对资源和数据特性优化分布式数据处理的调度和通信,对于实现高性能至关重要。在最近的研究中广泛讨论的例子是:地理分布的资源[14,30,47,48]、廉价的瞬时资源[34&#xff0c…

五分钟“手撕”链表

为了提高大家的学习效率,我把代码放开头,供查阅。 目录 一、链表的实现代码 二、什么是链表 三、链表的分类 四、链表的常见操作 插入 删除 五、Java自带的LinkedList 两个构造方法 一些常用方法 六、LinkedList的遍历 七、ArrayList和Linke…

基恩士PLC与ModbusTCP转Profibus网关实现与激光设备的高效连接

本文将探讨如何通过使用基恩士PLC以及无锡耐特森ModbusTCP转Profibus网关来实现与激光设备的高效连接。在当今工业自动化领域,不同厂商的硬件设备和软件系统之间的互联互通性成为了提高生产效率、实现智能制造的关键因素。其中,可编程逻辑控制器&#xf…

spring boot 3.x版本 引入 swagger2启动时报错

一,问题 Spring Boot 3.x版本的项目里,准备引入Swagger2作为接口文档,但是项目启动报错: java.lang.TypeNotPresentException: Type javax.servlet.http.HttpServletRequest not present at java.base/sun.reflect.generics.…

高等教育的AI革新:OpenAI面向大学推出ChatGPT Edu

OpenAI推出了ChatGPT Edu,这是一个为大学设计的专用版本,旨在让学生、教职员工、研究人员和校园运营能够负责任地使用AI。 ChatGPT Edu 将AI技术引入了教育领域,其建立在GPT-4o的基础上,它不仅能够处理文本和图像,还…

【linux深入剖析】进程间通信

🍁你好,我是 RO-BERRY 📗 致力于C、C、数据结构、TCP/IP、数据库等等一系列知识 🎄感谢你的陪伴与支持 ,故事既有了开头,就要画上一个完美的句号,让我们一起加油 目录 1.进程间通信目的2. 什么…

dubbo复习:(17)dubbo连接skywalking

一、准备skywalking 8.7.0并启动 二、配置好skywalking agent 三、服务提供者端的依赖 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema…

结构体中内存的对齐

前言 学C的同学应该知道~ 想精通C语言就不得不面对—指针与内存 续上次指针进阶&#xff0c;这一章我来聊一聊C语言内存对齐的问题 学习结构体的你有没有注意过结构体向系统申请的内存为多少呢的&#x1f601; 思考 #include<stdio.h> typedef struct s1 {char a;char …

Firebase Local Emulator Suite详解

文章目录 Firebase Local Emulator Suite 组件安装和使用步骤1. 安装 Firebase CLI2. 初始化 Firebase 项目3. 配置模拟器4. 启动模拟器5. 配置应用程序使用本地模拟器 常见用途 Firebase Local Emulator Suite 是一组本地服务&#xff0c;可以模拟 Firebase 平台的在线服务&am…

抖音电商“山货上头条”走进广东茂名,助销白糖罂荔枝地标农产品

受异常天气影响&#xff0c;今年广西、广东等地“桂味”和“香荔”等荔枝品种罕见减产。入夏以来&#xff0c;“痛失荔枝自由”“荔枝价格暴涨”等话题频上热搜。 为帮助消费者尝到品质良好、价格实惠的新鲜荔枝&#xff0c;今年“抖音商城618好物节”活动期间&#xff0c;抖音…

优化CPU占用率及内存占用2

在标准化无线通信板时&#xff0c;关注过程序占用ram的问题&#xff0c;当时 发现每一个线程都会分配8M栈空间&#xff0c;这次换rk3568后&#xff0c;偶尔看了下RAM占用&#xff0c;吓了一跳&#xff0c;不但每个线程有8M栈空间&#xff0c;几乎每个线程都占用了64MB的一个RAM…

实战Qt 5:打造健壮性计算器的过程

新书上架~&#x1f447;全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 一、项目概述与初始化 二、功能测试与调整 三、性能优化与健壮性提升 四、项目总结与展望…

MathType2025数学公式编辑器有哪些新增功能?

在当今科技飞速发展的时代&#xff0c;数学、科学和工程教育领域对于精确性和效率的要求日益增高。随着教育数字化的不断深入&#xff0c;传统的教学方式和科研手段正逐渐被新型的数字工具所取代。在这一过程中&#xff0c;MathType作为一款强大的数学公式编辑器&#xff0c;其…

Qt 插件机制使用及原理

目录 1.引言 2.插件原理 3.插件实现 3.1.定义一个接口集(只有纯虚函数的类) 3.2.实现接口 4.插件的加载 4.1.静态插件 4.1.1.静态插件实现方式 4.1.2.静态插件加载的过程 4.1.3.示例 4.2.动态插件 4.2.1.动态插件的加载过程 5.定位插件 6.插件开发的优势 7.总结…

【MySQL数据库】:MySQL复合查询

目录 基本查询回顾 多表查询 自连接 子查询 单行子查询 多行子查询 多列子查询 在from子句中使用子查询 合并查询 前面我们讲解的mysql表的查询都是对一张表进行查询&#xff0c;在实际开发中这远远不够。 基本查询回顾 【MySQL数据库】&#xff1a;MySQL基本查…

电子电气SCI期刊,中科院1区TOP,收稿范围广泛

一、期刊名称 IEEE Transactions on Smart Grid 二、期刊简介概况 期刊类型&#xff1a;SCI 学科领域&#xff1a;工程技术 影响因子&#xff1a;9.6 中科院分区&#xff1a;1区 三、期刊征稿范围 IEEE Transactions on Smart Grid是一本跨学科期刊&#xff0c;旨在传播智…

【Linux】进程(1)

大家好&#xff0c;我是苏貝&#xff0c;本篇博客带大家了解Linux进程&#xff08;1&#xff09;&#xff0c;如果你觉得我写的还不错的话&#xff0c;可以给我一个赞&#x1f44d;吗&#xff0c;感谢❤️ 目录 1. 冯诺依曼体系结构2.操作系统&#xff08;Operator System / O…

mysql的增删查改(进阶)

一. 更复杂的新增 将从表名查询到的结果插入到表名2中 insert into 表名2 select .. from 表名1 ...; 创建一个学生表: 创建一个学生表2, 将学生表中的数据加到学生表2中: 注意: 列的类型可以匹配即可插入, 列名和列的类型不一定要完全一致 二. 查询 2.1 聚合查询 前面谈到…