当前位置: 首页 > news >正文

【数据结构】栈与队列的实现

栈与队列是数据结构中重要的结构,
可以用于解决一些题目
模拟实现时可以增加对于这些结构的理解,也可以巩固我们的语言水平,解决某些题目也会有很好的效果

话不多说

目录

  • 栈的实现
    • 结构体的定义:
    • 初始化栈:
    • 压栈:
    • 出栈:
    • 获取栈顶元素:
    • 获取栈中有效元素个数 :
    • 检测栈是否为空:
    • 销毁栈 :
  • 栈模拟源代码:
  • 队列的实现:

栈的实现

先来看一下栈的定义:

栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端
称为栈顶,另一端称为栈底。栈中的数据元素遵守后进先出LIFO(Last In First Out)的原则。
压栈:栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶。
出栈:栈的删除操作叫做出栈。出数据也在栈顶。

在这里插入图片描述

栈的实现一般可以使用数组或者链表实现,
相对而言数组的结构实现更优一些。因为数组在尾上插入数据的代价比较小。

结构体的定义:

// 支持动态增长的栈
typedef int STDataType;
typedef struct Stack
{STDataType* a;int top;		// 栈顶int capacity;  // 容量 
}Stack;

初始化栈:

栈在初始化时,
我们可以定义top为栈顶元素的下一个,故这样我们就可以将top定义为0,若将top定义为栈顶元素,则需要将top定义为-1

这里我在仔细的讲解一下:
top0时,我们不能将top视作栈顶元素,因为如果压栈,压入的元素就会在top == 0的位置压入,压入的top仍为0,我们将判断不了top == 0时是否有元素,
则若top = 0,我们应当定义栈顶元素的下一个,这样我们赋值时:ps->a[top] = data;top++;

同理,若是初始化top == -1,则赋值:top++;ps->a[top] = data;

// 初始化栈 
void StackInit(Stack* ps)
{ps->a = NULL;ps->capacity = 0;ps->top = 0;
}

压栈:

因为只有压栈时会增加元素个数,故我们不需要封装一个函数用来创造新节点

void StackPush(Stack* ps, STDataType data)
{assert(ps);//检查容量if (ps->capacity == ps->top){int newcapacity = (ps->capacity == 0 ? 4 : 2 * ps->capacity);STDataType* tmp = (STDataType*)realloc(ps->a, sizeof(STDataType) * newcapacity);if (tmp == NULL){perror("realloc fail");return;}ps->a = tmp;ps->capacity = newcapacity;}ps->a[ps->top] = data;ps->top++;
}

出栈:

void StackPop(Stack* ps)
{assert(ps);assert(ps->top);ps->top--;
}

获取栈顶元素:

STDataType StackTop(Stack* ps)
{assert(ps);return ps->a[ps->top - 1];
}

获取栈中有效元素个数 :

int StackSize(Stack* ps)
{assert(ps);return ps->top;
}

检测栈是否为空:

检测栈是否为空,如果为空返回非零结果,如果不为空返回0

bool StackEmpty(Stack* ps)
{assert(ps);return ps->top == 0;
}

销毁栈 :

void StackDestroy(Stack* ps)
{free(ps->a);ps->a = NULL;ps->capacity = 0;ps->top = 0;
}

栈模拟源代码:

stack.c

#define _CRT_SECURE_NO_WARNINGS 1#include "stack.h"// 初始化栈 
void StackInit(Stack* ps)
{ps->a = NULL;ps->capacity = 0;ps->top = 0;
}void StackPush(Stack* ps, STDataType data)
{assert(ps);//检查容量if (ps->capacity == ps->top){int newcapacity = (ps->capacity == 0 ? 4 : 2 * ps->capacity);STDataType* tmp = (STDataType*)realloc(ps->a, sizeof(STDataType) * newcapacity);if (tmp == NULL){perror("realloc fail");return;}ps->a = tmp;ps->capacity = newcapacity;}ps->a[ps->top] =data;ps->top++;
}void StackPop(Stack* ps)
{assert(ps);assert(ps->top);ps->top--;
}STDataType StackTop(Stack* ps)
{assert(ps);return ps->a[ps->top - 1];
}int StackSize(Stack* ps)
{assert(ps);return ps->top;
}bool StackEmpty(Stack* ps)
{assert(ps);return ps->top == 0;
}void StackDestroy(Stack* ps)
{free(ps->a);ps->a = NULL;ps->capacity = 0;ps->top = 0;
}

stack.h

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>
// 支持动态增长的栈
typedef int STDataType;
typedef struct Stack
{STDataType* a;int top;		// 栈顶int capacity;  // 容量 
}Stack;// 初始化栈 
void StackInit(Stack* ps);
// 入栈 
void StackPush(Stack* ps, STDataType data);
// 出栈 
void StackPop(Stack* ps);
// 获取栈顶元素 
STDataType StackTop(Stack* ps);
// 获取栈中有效元素个数 
int StackSize(Stack* ps);
// 检测栈是否为空,如果为空返回非零结果,如果不为空返回0 
bool StackEmpty(Stack* ps);
// 销毁栈 
void StackDestroy(Stack* ps);

队列的实现:

队列的定义:
队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出
FIFO(First In First Out) 入队列:进行插入操作的一端称为队尾 出队列:进行删除操作的一端称为队头

在这里插入图片描述

持续更新中…
敬请期待

相关文章:

  • Elasticsearch 索引库操作与 Rest API 使用详解
  • Cloud
  • 【解决】使用Element-Plus icon图标不显示
  • 云ES高级监控告警
  • 【机器学习】朴素贝叶斯算法:多项式、高斯、伯努利,实例应用(心脏病预测)
  • 跨境电商测评新方案,安全可靠,高成功率
  • Python开源项目GPEN——人脸重建(Face Restoration),模糊清晰、划痕修复及黑白上色的实践
  • 基于蝠鲼觅食算法优化概率神经网络PNN的分类预测 - 附代码
  • 简单的 UDP 网络程序
  • Flink CDC
  • Android R.fraction
  • 快速使用vscode写python
  • element-plus使用el-date-picker组件时,如何禁止用户选择当前时间之后的日时分秒
  • 有什么进销存软件,比较适合零售行业日常开单要求及库存记录?
  • 设计模式-状态模式-笔记
  • 【跃迁之路】【444天】程序员高效学习方法论探索系列(实验阶段201-2018.04.25)...
  • android高仿小视频、应用锁、3种存储库、QQ小红点动画、仿支付宝图表等源码...
  • Android开发 - 掌握ConstraintLayout(四)创建基本约束
  • Hibernate最全面试题
  • JavaScript 基本功--面试宝典
  • JavaScript 事件——“事件类型”中“HTML5事件”的注意要点
  • mac修复ab及siege安装
  • Nginx 通过 Lua + Redis 实现动态封禁 IP
  • PAT A1017 优先队列
  • Python打包系统简单入门
  • Python学习之路13-记分
  • Travix是如何部署应用程序到Kubernetes上的
  • 从重复到重用
  • 将回调地狱按在地上摩擦的Promise
  • 猫头鹰的深夜翻译:JDK9 NotNullOrElse方法
  • 浅析微信支付:申请退款、退款回调接口、查询退款
  • 区块链分支循环
  • 设计模式(12)迭代器模式(讲解+应用)
  • 为什么要用IPython/Jupyter?
  • puppet连载22:define用法
  • 测评:对于写作的人来说,Markdown是你最好的朋友 ...
  • 分布式关系型数据库服务 DRDS 支持显示的 Prepare 及逻辑库锁功能等多项能力 ...
  • ​二进制运算符:(与运算)、|(或运算)、~(取反运算)、^(异或运算)、位移运算符​
  • (2)(2.10) LTM telemetry
  • (aiohttp-asyncio-FFmpeg-Docker-SRS)实现异步摄像头转码服务器
  • (floyd+补集) poj 3275
  • (Redis使用系列) Springboot 使用redis的List数据结构实现简单的排队功能场景 九
  • (附源码)springboot 智能停车场系统 毕业设计065415
  • (利用IDEA+Maven)定制属于自己的jar包
  • (篇九)MySQL常用内置函数
  • (原創) 如何優化ThinkPad X61開機速度? (NB) (ThinkPad) (X61) (OS) (Windows)
  • (转)Linux NTP配置详解 (Network Time Protocol)
  • (转)Sql Server 保留几位小数的两种做法
  • .bat批处理(七):PC端从手机内复制文件到本地
  • .NET 事件模型教程(二)
  • .net实现头像缩放截取功能 -----转载自accp教程网
  • :如何用SQL脚本保存存储过程返回的结果集
  • ??javascript里的变量问题
  • @Autowired @Resource @Qualifier的区别
  • @for /l %i in (1,1,10) do md %i 批处理自动建立目录