【数据结构初阶】--- 栈和队列

栈的定义

栈:只允许在一端进行插入或删除的操作
事实上,线性表和链表都可以实现栈,但栈的特点更符合用顺序表实现

  • 顺序表的队尾相当于栈顶,对栈放入数据,相当于顺序表的下标arr[index++] = x,而栈弹出数据时,相当顺序表的下标index–,即可。
  • 相比之下链表就没有这么的符合,入栈时,链表为其创建一个结点进行尾插,出栈时,进行尾删,中间的过程稍微繁琐,并没有顺序表方便
  • 所以今天我们也是用顺序表来实现一个栈
    在这里插入图片描述
    在这里插入图片描述

栈的操作

定义

说明:
top:是指向栈顶的位置,还是栈顶的下一个位置,在初始化讨论
capacity:表示栈的容量,因为是用顺序表实现,入栈的时候也需要判断是否现有元素个数是否达到容量
arr:就是个指向数组的指针

typedef int STDataType;
typedef struct ST
{int top;int capacity;STDataType* arr;
}ST;

初始化

说明:
初始化的时候我并没有给数组开辟空间,那么后面入栈的时候再进行扩容
因此capacity也就是0;
top:

  1. 这里我将top初始化为0,top指向的是栈顶的下一个元素
    • 此时top指向的是下标为4的位置
    • 而栈内的元素也是4,因此,我们可以用top直接表示栈内的元素个数(优势)
    • 当栈为空时,top为0
      在这里插入图片描述
  2. top指向栈顶的位置,当栈为空的时候top为-1;
    这种方式的优势在于可以将top直接当做下标
void STInit(ST* st)
{assert(st != NULL);st->arr = NULL;st->capacity = 0;st->top = 0;//指向栈顶的下一个元素
}

入栈

说明:
因为初始化的时候没有给数组开辟空间,所以入栈的时候要考虑是给栈开辟空间还是为栈扩容

void STPush(ST* st, STDataType x)
{assert(st != NULL);if (st->capacity == st->top){int capacity = st->capacity == 0 ? 4 : st->capacity * 2;STDataType* newp = (STDataType*)realloc(st->arr, sizeof(STDataType) * capacity);if (newp == NULL){perror("realloc fail");return;}st->arr = newp;st->capacity = capacity;newp = NULL;}st->arr[st->top++] = x;}

出栈

void STPop(ST* st)
{assert(st);if (!STEmpty(st)){st->top--;}
}

返回栈顶元素

因为这里的top表示栈顶的下一个位置,所以栈顶元素的下标是top-1

STDataType STTop(ST* st)
{assert(st);if (!STEmpty(st)){return st->arr[st->top - 1];}return -1;
}

判断栈是否为空

top为0就表示栈为空

bool STEmpty(ST* st)
{assert(st);return st->top == 0;
}

返回栈内元素个数

前面说了,top表示为栈顶元素的优点在于,top可以直接表示为元素个数

int STSize(ST* st)
{assert(st);return st->top;
}

销毁栈

void STDestory(ST* st)
{assert(st);free(st->arr);st->top = 0;st->capacity = 0;}

队列

队列的定义

从队的一头插入元素,另一头弹出元素
在这里插入图片描述

用顺序表实现还是用链表

  • 队列的特点是不符合顺序表来实现的,入队相当于顺序表的尾插,出队时,顺序表将下标为0的元素移除,那么只能将后面的数据依次向前移一位,出一次队就要将整个顺序表移动一次,这样的代价是非常大的。
  • 链表就很符合这个特点,入队就相当于尾插,出队就是头插,相比之下很方便,还是链表实现比较好

队列的操作

定义

用链表实现队列,那么就需要用到链表的这个结构体
队列想要入栈,是尾插,那么总不能每次插入一次就将链表遍历一遍寻找尾结点,所以,我们需要一个指针tail去记录尾结点
队列想要出栈,是头插,当然这只是原因之一,因为有了指向头结点的指针才能找到这个链表

typedef int QDataType;
typedef struct ListNode
{QDataType data;struct ListNode* next;
}ListNode;typedef struct Queue
{ListNode* head;ListNode* tail;
}Queue;

初始化

因为队列里还没有元素,指针都置空

void QueueInit(Queue* qu)
{assert(qu);qu->head = NULL;qu->tail = NULL;
}

入队

每一次入队都是先创建一个结点,在进行连接
这里要考虑队列为空的情况与不为空的情况是否可以共用一套代码

void QueuePush(Queue* qu, QDataType x)
{assert(qu);ListNode* new_node = (ListNode*)malloc(sizeof(ListNode));if (new_node == NULL){perror("malloc fail");return;}new_node->next = NULL;new_node->data = x;if (QueueEmpty(qu)){qu->head = new_node;qu->tail = new_node;}else{qu->tail->next = new_node;qu->tail = qu->tail->next;}
}

出队

先考虑队列为空的情况,
接着是不为空,不为空又分为一个结点和多个节点
分别去处理三种情况,尤其是要考虑只有一个结点的情况

void QueuePop(Queue* qu)
{assert(qu);if (!QueueEmpty(qu)){ListNode* tmp = qu->head;if (qu->head == qu->tail)//这个条件说明只有一个结点{free(tmp);tmp = NULL;qu->head = NULL;qu->tail = NULL;}else{qu->head = qu->head->next;free(tmp);tmp = NULL;}}
}

返回队头元素

不为空就返回head指向结点的数据,为空返回-1

QDataType QueueTop(Queue* qu)
{assert(qu);if (!QueueEmpty(qu)){return qu->head->data;}return -1;
}

返回队尾元素

QDataType QueueBack(Queue* qu)
{assert(qu);if (!QueueEmpty(qu)){return qu->tail->data;}return -1;
}

判断队列是否为空

判断是否为空很简单,只用判断两个指针是否同时为空
但也要考虑到意外状况,如果在函数外传参传错,导致两个指针其中一个为空,一个不为空,这种情况检查起来非常麻烦,所以在这里断言一下

bool QueueEmpty(Queue* qu)
{assert(qu);assert(!(qu->head == NULL && qu->tail != NULL));assert(!(qu->head != NULL && qu->tail == NULL));return qu->head == NULL && qu->tail == NULL;
}

返回队列元素个数

int QueueSize(Queue* qu)
{assert(qu);int size = 0;ListNode* cur = qu->head;while (cur != NULL){size++;cur = cur->next;}return size;
}

销毁队列

相当于销毁一个链表,最后函数结束时,手动将实参qu置空

void QueueDestory(Queue* qu)
{assert(qu);ListNode* cur = qu->head;while (cur != NULL){ListNode* nxt = cur->next;free(cur);cur = nxt;}qu->head = NULL;qu->tail = NULL;
}

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

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

相关文章

threejs导入import报错

1.安装 three: npm install three -d 2.引入: import * as THREE from "three"import { OrbitControls } from "three/examples/controls/OrbitControls.js" 报错: 3.解决办法: 3.1引入: im…

车道偏离预警系统技术规范(简化版)

车道偏离预警系统技术规范(简化版) 1 系统概述2 预警区域3 功能条件4 显示需求5 指标需求1 系统概述 车道偏离预警系统工作在中高速驾驶的情况下,当驾驶员因注意力不集中导致车辆偏离本车道时,系统通过光学和声学信号对驾驶员进行提醒,减少因此导致的交通事故。功能主要依…

嵌入式操作系统_4.任务管理

1.任务的概念 任务管理是嵌入式操作系统最基本功能之一,这里的任务(task)是指嵌入式操作系统调度的最小单位,类似于一般操作系统进程或线程的概念。任务是运行中的一个程序,一个程序加载到内存后就变成任务&#xff1…

将自己md文件发布到自己的博客园实现文件的持久化存储

上传markdown文件到博客园 目录 【0】需求原因【1】功能【2】环境【最佳实践测试】 (1)查看 Typora 设置(2)配置 pycnblog 配置文件 config.yaml(3)运行 pycnblog 中的文件 cnblog_markdown.cmd&#xff0…

基于hispark_taurus开发板示例学习OpenHarmony编译构建系统(2)

3、hispark_taurus产品解决方案-Vendor 产品解决方案为基于开发板的完整产品,主要包含产品对OS的适配、组件拼装配置、启动配置和文件系统配置等。产品解决方案的源码路径规则为:vendor/{产品解决方案厂商}/{产品名称}_。_产品解决方案也是一个特殊的组…

CentOs7 安装mysql5.7

1.卸载原系统中的mariadb…… 首先执行命令rpm -qa|grep mariadb查看是否有mariadb的安装包,没有可以不管 接下来,执行 rpm -e --nodeps mariadb-libs #删除掉下载mysql5.7安装包 1.前往官方网站复制yum源链接Mysql官网 然后鼠标右键粘贴 wget 执行…

信息系统架构风格-系统架构师(十)

1、信息系统架构风格是描述特定应用领域中系统组织方式的惯用模式。架构风格定义了一个系统家族,即一个架构定义()。 A一组设计原则 B一组模式 C一个词汇表和一组约束 D一组最佳实践 解析: 信息系统架构风格是描述某一特定 应…

OrangePi Kunpeng Pro 安装 ROS2 + Gazebo

文章目录 1. 初识1.1 到手开箱1.2 OrangePi Kunpeng Pro1.2 上电 2. 安装Ubuntu2.1 准备工作2.2 安装 3. 安装ROS23.1 设置支持UTF-8的locale编码3.2 添加证书3.3 安装ROS3.4 设置环境变量3.5 小海龟来啦 4. 运行实例4.1 安装Gazebo4.2 安装turtlebot 总结 1. 初识 1.1 到手开…

机器学习python实践——数据“相关性“的一些补充性个人思考

在上一篇“数据白化”的文章中,说到了数据“相关性”的概念,但是在统计学中,不仅存在“相关性”还存在“独立性”等等,所以,本文主要对数据“相关性”进行一些补充。当然,如果这篇文章还能入得了各位“看官…

openGauss学习笔记-300 openGauss AI特性-AI4DB数据库自治运维-DBMind的AI子功能-SQL Rewriter SQL语句改写

文章目录 openGauss学习笔记-300 openGauss AI特性-AI4DB数据库自治运维-DBMind的AI子功能-SQL Rewriter SQL语句改写300.1 概述300.2 使用指导300.2.1 前提条件300.2.2 使用方法示例300.3 获取帮助300.4 命令参考300.5 常见问题处理openGauss学习笔记-300 openGauss AI特性-AI…

MySQL问题篇2:关于IN字段不按照顺序返回问题

一、发现问题 数据库表结构如下: 其查询语句如下: SELECT* FROMdepartment WHEREdepartment_id IN (5,4,2,3,1) 其返回结果如下: 到此处我们发现了问题,其中我in写的是(5,4,2,3,1),其返回结果顺…

vue+elementUI实现在表格中添加输入框并校验的功能

背景: vue2elmui 需求: 需要在一个table中添加若干个输入框,并且在提交时需要添加校验 思路: 当需要校验的时候可以考虑添加form表单来触发校验,因此需要在table外面套一层form表单,表单的属性就是ref…

单触控单输出触摸开关芯片PT2052A

1.产品概述 PT2052封装和丝印 PT2052A 是一款单通道触摸检测芯片。该芯片内建稳压电路,提供稳定电压给触摸感应电路使用,同时内部集成高效完善的触摸检测算法,使得芯片具有稳定的触摸检测效果。该芯片专为取代传统按键而设计,具有…

【LeetCode】4,寻找两个正序数组中的中位数

题目地址 B站那个官方解答视频实在看不懂,我就根据他那个代码和自己的理解写一篇文章 1. 基本思路 在只有一个有序数组的时候,中位数把数组分割成两个部分。中位数的定义:中位数,又称中点数,中值。中位数是按顺序排列…

【QT5】<总结> QT主要技术点

文章目录 前言 一、QT串口编程 二、QT网络编程 三、QT多线程 四、QT连接数据库 五、开发板上运行QT程序 前言 在学习QT的过程中,旨在更好地巩固所学到的知识,本篇总结QT在嵌入式开发中的主要技术点。 一、QT串口编程 思维导图: 知识点…

webrtc新版本无法连接peerconnection_server、无法音视频互通no incoming video...问题解决

问题1:无法连接peerconnection_server 在webrtc大概2022之后的版本,会出现无法连接peerconnection_server的现象,如下图: 在peerconnection_client界面点击Connect无法连接server. 解决办法 我们需要修改peerconnection_client的main.cc代码,如下图: 新添加的类代码…

Python第二语言(十一、Python面向对象(下))

目录 1. 封装 1.1 私有成员:__成员、__成员方法 2. 继承:单继承、多继承 2.1 继承的基础语法 2.2 复写 & 子类使用父类成员 3. 变量的类型注解:给变量标识变量类型 3.1 为什么需要类型注解 3.2 类型注解 3.3 类型注解的语法 3.…

LeetCode452用最少数量的箭引爆气球

题目描述 有一些球形气球贴在一堵用 XY 平面表示的墙面上。墙面上的气球记录在整数数组 points ,其中points[i] [xstart, xend] 表示水平直径在 xstart 和 xend之间的气球。你不知道气球的确切 y 坐标。一支弓箭可以沿着 x 轴从不同点 完全垂直 地射出。在坐标 x 处…

【C++进阶学习】第一弹——继承(上)——探索代码复用的乐趣

前言: 在前面,我们已经将C的初阶部分全部讲完了,包括类与对象、STL、栈和队列等众多内容,今天我们就进入C进阶部分的学习,今天先来学习第一弹——继承 目录 一、什么是继承?为什么会有继承? 二…

视频监控汇聚平台:系统日志介绍及在运维中的实际应用

目录 一、系统日志的重要性 (一)安全保障 (二)故障排查 (三)运营管理 (四)事件回溯与分析 二、产品说明 (一)产品介绍 (二)接…