数据结构 栈与队列详解!!

一.栈

 关于内存中的栈和数据结构中的栈是不同的,本章着重讲的是数据结构的栈。

 这是一张关于栈的表达图。从图中可以看出栈很像是一副卡牌,发牌时只能从上取出,即出栈。

而入栈则是像你出牌后,要把你出的牌压在上一张出的牌上面。这是入栈。

栈可以用链表或者顺序表实现,这里采用的是顺序表的结构。

1.栈的头文件 

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>
typedef int StackDatatype;
typedef struct Stack
{StackDatatype* data;int capacity;int Top;
}ST;
void STPush(ST* pst, StackDatatype x);
void StackInit(ST* pst);
void StackDestroy(ST* pst);
void Push(ST* pst, StackDatatype x);
void Pop(ST* pst);
StackDatatype StackTop(ST* pst);
int StackSize(ST* pst);
bool StackEmpty(ST* pst);

 2.栈的初始化

void StackInit(ST* pst)
{assert(pst);pst->capacity = 0;pst->data = NULL;pst->Top = -1;
}

这里的pst->Top可以用-1,或者0.用-1的话后续你的pst->Top 所代表的下标就是栈顶元素。

如果用0 那pst-Top 之后的下标就是栈顶元素的下一个位置。这里可以自己考虑,代码的多样性。 (本章采用的是-1 的写法)

3.栈的插入

void Push(ST* pst, StackDatatype x)
{assert(pst);pst->Top++;JudgeCapacity(pst);pst->data[pst->Top] = x;
}

栈的插入就是入栈,top++ 是pst->top 指向当前即将插入元素的位置(栈顶的位置)。

后面在判断pst中的容量,不够需要扩容。把x 插入栈顶位置。 

4.栈的取出

void Pop(ST* pst)
{assert(pst);assert(pst->Top > -1);pst->Top--;
}

和顺序表一样只要 top--即可,不用删除,因为top -- 以后,你下次在使用该位置的时候,其实就是把原来这个位置的元素更改就可以了,不需要删除。

5.栈的栈顶元素

StackDatatype StackTop(ST* pst)
{assert(pst);return pst->data[pst->Top];
}

 这个函数的存在意义就是取当前的栈顶元素的值。

6.栈的元素个数

int StackSize(ST* pst)
{assert(pst);return pst->Top+1;
}

因为我们的Top 用的是-1开头,所以,当它指向第一个元素的时候,这时候Top == 0, 所以加一。

7.栈的判空

bool StackEmpty(ST* pst)
{assert(pst);return pst->Top == -1;
}

判断栈此时是否为空,用pst- top == -1 的判断表达式返回即可。 

8.栈的销毁

void StackDestroy(ST* pst)
{assert(pst);free(pst->data);pst->data = NULL;pst->capacity = 0;pst->Top = -1;
}

因为栈是创建出来的一个空间。所以最后要将这段空间free,并将所有数据都置空 

栈的容量判断

void JudgeCapacity(ST* pst)
{assert(pst);if (pst->capacity == pst->Top){int newcapacity = pst->capacity == 0 ? 4 : 2 * pst->capacity;StackDatatype* tmp = (StackDatatype*)realloc(pst->data, sizeof(StackDatatype) * newcapacity);if (tmp == NULL){perror("malloc failed!");return;}pst->data = tmp;pst->capacity = newcapacity;}
}

 和顺序表的容量判断一样,有兴趣的可以直接去看我的顺序表详解,这里给大家简单的说一下,用三目表达式判断并赋值newcapacity,然后扩容pst->data这一段空间。

最后把扩容好的空间地址给到tmp,newcapacity给到原来的capacity。

二.队列

 上图是队列的表达图,队列如字意就像是排队一样,先进入的人,就先获得服务。

所以 队列和 栈的不同点就是出栈和出队,队列出的是头元素,而栈出的是尾元素(栈顶)

对比入队和 入栈两者相似都是尾插。

,还有队列用的是链表,栈用的是顺序表。

1.队列的头文件

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>typedef int QeDataType;
typedef struct QueueNode
{struct QueueNode* next;QeDataType data;
}Qnode;
typedef struct Queue
{Qnode* head;Qnode* back;
}Qe;
void QueueInit(Qe* q);
void QueueDestroy(Qe* q);
void Queuepush(Qe* q, QeDataType x);
void QueuePop(Qe* q);
QeDataType QueueFront(Qe* q);
QeDataType QueueBack(Qe* q);
int QueueSize(Qe* q);
bool QueueEmpty(Qe* q);

 相比栈 队列多用了一个typedef 原因是,队列要记录头元素和尾元素。因为入队入的在尾部,出队出的是头部

2.队列的初始化

void QueueInit(Qe* q)
{assert(q);Qnode* newnode = CreateNode(-1);q->head = newnode;q->back = newnode;
}

 这里采用的是有头结点的队列,当然没有头结点(哨兵位)也是可以的,根据个人喜好选择。

初始化创立一个头结点(哨兵位)后,头指针和尾指针都指向头结点(哨兵位)

3.队列的插入

void Queuepush(Qe* q, QeDataType x)
{assert(q);Qnode* newnode = CreateNode(x);q->back->next = newnode;q->back = newnode;
}

 关于队列的插入,就是链表的尾插,如果链表还没明白的朋友,可以去看我之前关于单链表的博客。

4.队列的取出

void QueuePop(Qe* q)
{assert(q);assert(q->head->next);Qnode* next = q->head->next;q->head->next = next->next;free(next);next = NULL;if (q->head->next == NULL){q->back = q->head;q->back->next = NULL;}
}

关于队列的取出,实质上就是链表的头删。 

5.队列的头元素

QeDataType QueueFront(Qe* q)
{assert(q);assert(q->head->next);return q->head->next->data;
}

 队列的头元素返回就是返回哨兵位后的第一个节点的数据。因为要返回数值,所以这个第一个节点不能为空,用assert断言。

6.队列的尾元素

QeDataType QueueBack(Qe* q)
{assert(q);assert(q->head->next);return q->back->data;
}

 既然要返回尾元素的数据,那就是用到尾指针,当然链表第一个节点不能为空。

7.队列的元素个数

int QueueSize(Qe* q)
{Qnode* size = q->head->next;int num = 0;while (size){size = size->next;num++;}return num;
}

队列的元素个数,就把链表遍历一遍,用num记录遍历次数,就是元素个数。 

8.队列的判空

bool QueueEmpty(Qe* q)
{return q->head->next == NULL;
}

 队列的判空就是判断第一个节点是否为空,return 一个 表达式即可,也可以用if else 语句。因人而异。

创造一个节点

Qnode* CreateNode(QeDataType x)
{Qnode* newnode = (Qnode*)malloc(sizeof(Qnode));newnode->data = x;newnode->next = NULL;return newnode;
}

 创造一个节点在链表的初始化和插入都会用到,在之前链表的那篇博客有讲到,偏简单。

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux系统编程学习 NO.9——git、gdb

前言 本篇文章简单介绍了Linux操作系统中两个实用的开发工具git版本控制器和gdb调试器。 git 什么是git&#xff1f; git是一款开源的分布式版本控制软件。它不仅具有网络功能&#xff0c;还是服务端与客户端一体的软件。它可以高效的处理程序项目中的版本管理。它是Linux内…

Windows10下Maven3.9.5安装教程

文章目录 1.下载maven2.安装3.配置系统变量3.1.新建系统变量 MAVEN_HOME3.2.编辑系统变量Path 4.CMD命令测试是否安装成功5.配置maven本地仓库6.配置国内镜像仓库 1.下载maven 官网 https://maven.apache.org/download.cgi 点击下载。 2.安装 解压到指定目录 D:\installSoft…

Git企业开发级讲解(四)

&#x1f4d8;北尘_&#xff1a;个人主页 &#x1f30e;个人专栏:《Linux操作系统》《经典算法试题 》《C》 《数据结构与算法》 ☀️走在路上&#xff0c;不忘来时的初心 文章目录 一、理解分⽀二、创建分支三、切换分⽀四、合并分⽀五、删除分⽀六、合并冲突七、分⽀管理策略…

搭建mysql主从错误集合

1 mysqld --verbose --help --log-bin-index/tmp/tmp.Frnt2oibYI mysqld: Cant read dir of /etc/mysql/conf.d/ my.cnf是在/etc/mysql/conf.d/文件夹下&#xff0c;所以挂载的时候不要写/etc/mysql 2 COLLATION utf8_unicode_ci is not valid for CHARACTER SET latin1 配…

大数据研发工程师课前环境搭建

大数据研发工程师课前环境搭建 第一章 VMware Workstation 安装 在Windows的合适的目录来进行安装&#xff0c;如下图 1.1 双击打开 1.2 下一步&#xff0c;接受协议 1.3 选择安装位置 1.4 用户体验设置 1.5 快捷方式 已经准备好安装&#xff0c;点击安装 1.6 安装中 1.7 安装…

【算法每日一练]-图论(保姆级教程 篇5(LCA,最短路,分层图)) #LCA #最短路计数 #社交网络 #飞行路线 # 第二短路

今天讲最短路统计和分层图 目录 题目&#xff1a;LCA 思路&#xff1a; 题目&#xff1a;最短路计数 思路&#xff1a; 题目&#xff1a;社交网络 思路&#xff1a; 题目&#xff1a;飞行路线 思路&#xff1a; 题目&#xff1a;第二短路 思路&#xff1a; 题目&a…

轻量服务器和云服务器的区别,轻量应用服务器和云服务器区别对比

在云计算时代&#xff0c;服务器作为互联网应用的基础设施&#xff0c;扮演着重要的角色。对于个人用户、个人开发者、学生用户和个人站长来说&#xff0c;选择一款适合自己的服务器是一个关键的决策。本文将介绍轻量服务器和标准云服务器的优点和应用场景&#xff0c;帮助读者…

Confluence 快速安装教程

安装jdk yum install -y java-1.8.0-openjdk.x86_64 java -version 安装MySQL mkdir -p /data/mysql/data chmod 777 /data/mysql/datadocker rm -f mysql docker run -d --name mysql \-p 3306:3306 \-e MYSQL_ROOT_PASSWORDfingard1 \-v /data/mysql/data:/var/lib/mysql …

​软考-高级-系统架构设计师教程(清华第2版)【第15章 面向服务架构设计理论与实践(P527~554)-思维导图】​

软考-高级-系统架构设计师教程&#xff08;清华第2版&#xff09;【第15章 面向服务架构设计理论与实践&#xff08;P527~554&#xff09;-思维导图】 课本里章节里所有蓝色字体的思维导图

视频剪辑技巧:简单步骤,批量剪辑并随机分割视频

随着社交媒体平台的广泛普及和视频制作需求的急剧增加&#xff0c;视频剪辑已经成为了当今社会一项不可或缺的技能。然而&#xff0c;对于许多初学者来说&#xff0c;视频剪辑可能是一项令人望而生畏的复杂任务。可能会面临各种困难&#xff0c;如如何选择合适的软件和硬件、如…

Halcon (0):C# 联合Halcon方式简介和就业市场说明

文章目录 文章专栏前言相关视频联合C#开发直接导出C#代码Halcon引擎调用开发函数封装库工程导出 总结就业市场 文章专栏 Halcon开发 前言 根据我的测试&#xff0c;我发现Halcon和WPF中的halcon插件&#xff0c;代码具有对应性。就是你会了Halcon&#xff0c;WPF也差不多久会了…

【springboot笔记】程序可用性检测ApplicationAvailability

1.背景 springboot-3.1.5 ApplicationAvailability LivenessState ReadinessState AvailabilityChangeEvent 我们可以通过ApplicationAvailability获取当前应用程序的可用性&#xff0c;这个可用性包括ApplicationContext和对外请求路由两种。 LivenessState 是表示Applicatio…