顺序栈与链式栈

news2024/12/23 9:45:12

目录

栈的定义与结构

栈的实现

顺序栈的实现

 初始化空栈

 销毁栈

压栈

获取栈顶元素

出栈

判断栈是否为空

获取栈中有效数据的个数

链式栈的实现

初始化空栈

 销毁栈

压栈

获取栈顶元素

出栈

判断栈是否为空

获取栈中有效数据的个数

顺序栈与链栈的对比


栈的定义与结构

栈是只允许在固定的一端进行插入元素或删除元素的线性表;进行数据插入和删除操作的一端称为栈顶(top), 另一端称为栈底(bottom);栈中的数据元素遵循后进先出(Last In First Out)的原则;

栈的基本操作:

压栈:栈中插入元素的操作叫做压栈/入栈,插入数据在栈顶插入;

出栈:栈中删除元素的操作叫做出栈,删除数据也在栈顶;

栈的实现

栈可以由顺序表和链表实现,使用顺序存储结构实现栈存储结构称为顺序栈或数组栈,使用链式结构实现栈存储结构称为链式栈;

  • 顺序栈的优点:

顺序栈的底层采用的是数组,当在栈顶插入或者删除元素时,可以通过下标进行插入或者删除,方便快捷,而且由于在内存中连续存储,缓存利用率高;

  • 链式栈的缺点:

链式栈当插入数据(尾插)可以通过定义尾指针实现插入,但是当删除数据(尾删)时,需要找到 尾结点的前一个结点,而单向链表无法实现,只能采用双向链表,代价过大;

以单链表头结点作为栈顶,此时插入数据(头插),删除数据(头删),这样相比上述方案方便快捷,但是由于是链式存储,缓存利用率低;

顺序栈的实现

采用动态顺序表实现栈,当进行插入元素的操作时,若空间不够使用,可以通过动态内存函数realloc()函数扩容;

typedef int STDataType;
typedef struct Stack
{
	STDataType* nums;
	int top;//记录栈顶元素在顺序栈中的位置;
	int capacity;//记录栈的大小;
}Stack;

 初始化空栈

栈顶元素的位置与栈底元素的位置相同,说明栈为空栈;空栈时,top的取值应该为多少?

若top=0表示空栈 ,当插入一个元素A0,则top=top+1即top=1;而top记录的是栈顶元素在顺序栈中的位置,此时top指向栈顶元素的下一个位置;若top不自增,top仍然为0,那么也将无法区分栈为空还是存在一个数据;

结论:top=0时,意味着top是栈顶元素的下一个位置;

若top=-1表示空栈,当插入1个元素A0,则top=top+1即top=0;由于top记录的是栈顶元素在顺序栈中的位置,逻辑自洽;

结论:top=-1时,意味着top是栈顶元素位置;

void InitStack(Stack* ps)
{
	assert(ps != NULL);
	//开辟一定量的空间
	ps->nums = (STDataType*)malloc(4*sizeof(STDataType));
	//判断空间开辟是否成功
	if (ps->nums == NULL)
	{
		perror("malloc failed:");
		exit(-1);
	}
	ps->top = -1;
	ps->capacity = 4;
}

 销毁栈

//栈的销毁
void DestroyStack(Stack* ps)
{
	assert(ps != NULL);

	free(ps->nums);
	ps->nums = NULL;

	ps->top = 0;
	ps->capacity = 0;
}

压栈

压栈时需要先检查栈的容量,若容量已满,需要进行扩容;

  • 栈满情况:(top=capacity-1)

//压栈
void StackPush(Stack* ps, STDataType x)
{
	assert(ps != NULL);

	//栈满扩容
	if (ps->top == ps->capacity - 1)
	{
		STDataType* tmp = (STDataType*)realloc(ps->nums, sizeof(STDataType)* 2 * (ps->capacity));
		if (tmp == NULL)
		{
			perror("realloc failed:");
			exit(-1);
		}
		ps->nums = tmp;
		ps->capacity = 2 * (ps->capacity);
	}
	//插入数据
	ps->nums[ps->top + 1]=x;
	ps->top++;
}

获取栈顶元素

//获取栈顶元素
STDataType StackTop(Stack* ps)
{
	assert(ps);

	//空栈
	assert(ps->top > (-1));

	return ps->nums[ps->top];
}

出栈

void StackPop(Stack* ps)
{
	assert(ps);
	//空栈时不可进行删除操作
	assert(ps->top > -1);

	ps->top = ps->top - 1;
}

判断栈是否为空

检测栈是否为空,栈为空返回true,否则返回false;

c语言默认没有布尔值(true/false),使用时需包含头文件# include <stdbool.h>

bool StackEmpty(Stack* ps)
{
	assert(ps);

	return (ps->top == -1);
}

获取栈中有效数据的个数

int StackSize(Stack* ps)
{
	assert(ps);
	return ps->top + 1;
}
  • 测试如上接口函数:
//遍历栈中元素时,通过一边获取栈顶元素,一边删除的操作实现
int main()
{
	Stack st;
	InitStack(&st);
	StackPush(&st, 10);
	StackPush(&st, 20);
	StackPush(&st, 30);
	StackPush(&st, 40);
	StackPush(&st, 50);
	while (!StackEmpty(&st))
	{
		printf("%d->", StackTop(&st));
		StackPop(&st);
	}
	printf("\n");
	DestroyStack(&st);
	return 0;
}

运行结果:

链式栈的实现

采用带哨兵位的单链表实现,见下图存储结构

//链栈数据结点类型LinkStack声明
typedef int LSDataType;
typedef struct LinkStack
{
	LSDataType data;//数据域
	struct LinkStack* next;//指针域
}LinkStack;

链栈的4要素:

1.栈空条件:phead->next=NULL

2.栈满条件:对于链栈而言,基本不存在栈满的情况,除非内存已经没有可以使用的空间,不需要考虑;

3.进栈操作:头插

4.出栈操作:头删

初始化空栈

建立一个空栈实际上是创建哨兵位的结点,并将其的next置为空指针;

//为将哨兵位结点带出,采用返回值的方案
LinkStack* InitStack(LinkStack* phead)
{
	LinkStack* phead = (LinkStack*)malloc(sizeof(LinkStack));
	if (phead == NULL)
	{
		perror("malloc fail:");
		exit(-1);
	}
	phead->next = NULL;
	return phead;
}

 销毁栈

释放所有动态开辟的结点空间;

//销毁栈
//先保存当前结点的下一个结点,然后释放当前结点;
void DestroyStack(LinkStack* phead)
{
	assert(phead);
	LinkStack* cur = phead;
	LinkStack* curnext = cur->next;
	while (curnext != NULL)
	{
		free(cur);
		cur = curnext;
		curnext = cur->next;
	}
	//此时cur指向尾结点
	free(cur);
	cur = NULL;
}

压栈

void StackPush(LinkStack* phead, LSDataType x)
{
	assert(phead);
	//开辟新结点
	LinkStack* newnode = malloc(sizeof(LinkStack));
	if (newnode==NULL)
	{
		perror("malloc failed:");
		exit(-1);
	}
	newnode->data = x;
	//头插=压栈
	newnode->next = phead->next;
	phead->next = newnode;
}

获取栈顶元素

在栈不为空的条件下,将哨兵位结点后的头结点的数据返回;

//获取栈顶元素
LSDataType LinkStTop(LinkStack* phead)
{
	assert(phead);
	//空栈
	assert(phead->next != NULL);

	return phead->next->data;
}

出栈

//出栈
void StackPop(LinkStack* phead)
{
	assert(phead);
    //空栈不可删除
	assert(phead->next != NULL);

	LinkStack* Second = phead->next->next;
	free(phead->next);//释放首结点
	phead->next = Second;
}

判断栈是否为空

检测栈是否为空,栈为空返回true,否则返回false;

//判断栈是否为空
bool StackEmpty(LinkStack* phead)
{
	assert(phead);

	return (phead->next == NULL);
}

获取栈中有效数据的个数

//获取栈中有效数据的个数
int StackSize(LinkStack* phead)
{
	assert(phead);
	int count = 0;//计数
	LinkStack* cur = phead->next;
	while (cur != NULL)
	{
		count++;
		cur = cur->next;
	}
	return count;
}

顺序栈与链栈的对比

顺序栈与链栈的时间复杂度均为O(1);

空间性能由于顺序栈是动态内存函数开辟的,势必会有一定空间的浪费,但是存取定位方便;链栈恰好弥补了上述缺点,但是链栈缓存利用率不高;

当线性表中元素个数变化大或者不知道元素个数有多少,采用链式栈;

当事先知道线性表的大致长度,采用顺序栈存储结构效率高;

 

 

 

 

 

 

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

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

相关文章

32个uniapp项目源码 涵盖商城团购等

IT之家小程序版客户端(使用 Mpvue 开发&#xff0c;兼容 Web)ithome-lite-master.zip mpvue 仿网易严选mpvue-shop-master.zip mpvue-音乐播放器mpvue-music-master.zip mpvue性能测试与体验miniweibo-master.zip mpvue改造的日历.zip mpvue框架仿滴滴出行didi-master.zip mpVu…

华为云云耀云服务器L实例评测使用 | 云耀云服务器L实例Docker可视化Portainer容器管理

一、使用背景 之前一直在用阿里云或者腾讯云的服务器&#xff0c;现在接触了一下华为云的服务器实例&#xff0c;点开产品列表发现有弹性云服务器ECS、云耀云服务器HECS等&#xff0c;本文主要使用云耀云服务器&#xff0c;看到官方简介&#xff1a; 华为云耀云服务器&#x…

TensorFlow入门(十三、动态图Eager)

一个图(Graph)代表一个计算任务,且在模型运行时,需要把图放入会话(session)里被启动。一旦模型开始运行,图就无法修改了。TensorFlow把这种图一般称为静态图。 动态图是指在Python中代码被调用后,其操作立即被执行的计算。 它与静态图最大的区别是不需要使用session来建立会话…

从创作到表演的全方位改变,数字时代中的和声之音

随着ChatGPT的现象级走红&#xff0c;AIGC在全球范围内掀起热潮。 所谓AIGC&#xff08;Al-Generated Content&#xff09;&#xff0c;是指利用人工智能来根据用户需求&#xff0c;借助已有的材料库生成对应的内容。事实上&#xff0c;除了强大的文本能力之外&#xff0c;图像…

【Linux】工具:Bundle 库的安装和简单使用

文章目录 1. 下载 buddle 库2. 从 Win 传输文件到 Linux3. 解压缩 Bundle 库压缩解压缩 1. 下载 buddle 库 要求联网&#xff0c;笔者使用云服务器&#xff0c;在 Xshell 7 上完成的虚拟机操作。 安装 git 工具&#xff0c;通过代码 clone &#xff08;大概率连接不上&#x…

CVE-2021-4034 polkit提权漏洞复现

CVE-2021-4034 polkit提权漏洞复现 1.前期准备2.复现 1.前期准备 Github地址&#xff1a; https://github.com/berdav/CVE-2021-4034polkit是一个授权管理器&#xff0c;其系统架构由授权和身份验证代理组成&#xff0c;pkexec是其中polkit的其中一个工具&#xff0c;他的作用…

UML简介

UML&#xff0c;全称为Unified Modeling Language&#xff08;统一建模语言&#xff09;&#xff0c;是一种用于软件工程和系统设计的标准化建模语言。它提供了一套图形化的符号和标记&#xff0c;用于描述和表示软件系统、系统架构、流程、数据结构、行为和交互。UML的设计旨在…

docker安装wiki

1.docker pull mediawiki 2.docker run -d --name mywiki -p 8666:80 mediawiki 访问ip:8666,就可以看到配置页面了 3.docker pull mysql docker run -d --name my-mysql -e MYSQL_ROOT_PASSWORD123456 -p 3307:3306 mysql 4.在配置页面链接ip:3307,连接数据库&#xff0c;接下…

Excel 快速填充

文章目录 利用快速填充进行提取数据利用快速填充进行拆分重组 2013 及以上版本才有的功能. 利用快速填充进行提取数据 有一列的数据已有, 需要提取部分数据到另一列, 只需要输入部分内容, 后面内容可以自动显示, 按下回车即可快速填充. 只要前面手动输入的内容没有错得太离谱…

迅为龙芯开发板开发板系统烧写-启动系统

上面所有的步骤我们都做完以后&#xff0c;输入命令 sync 确保我们之前的步骤都可以保存到 ssd&#xff0c;接着拔下 U盘&#xff0c;最后输入命令 reboot 重启开发板&#xff0c;如下图所示&#xff1a; 如果启动成功&#xff0c;我们会看到 pmon 从硬盘加载 linux 内核和文件…

视频怎么压缩?这样做视频变小还清晰

在我们的日常生活和工作中&#xff0c;视频已经成为了不可或缺的一部分。然而&#xff0c;随着视频文件的增大&#xff0c;如何有效地压缩视频以方便存储和传输成了一个重要的问题&#xff0c;如果你还不知道怎么压缩视频大小&#xff0c;不妨试试下面的方法吧~ 方法一&#xf…

1.3 Linux目录操作

文章目录 零、学习目标一、导入新课二、新课讲解&#xff08;一&#xff09;常用权限操作1、常用权限操作&#xff08;1&#xff09;chgrp命令&#xff08;2&#xff09;chown命令&#xff08;3&#xff09;chmod命令 2、权限操作实战任务1、创建文件&#xff0c;设置其用户组任…

【C++设计模式之亨元模式:结构型】分析及示例

简介 享元模式&#xff08;Flyweight Pattern&#xff09;是一种结构型设计模式&#xff0c;旨在通过共享对象&#xff0c;有效地支持大量细粒度的对象&#xff0c;从而减少内存和性能消耗。它通过将对象分为可共享的内部状态和不可共享的外部状态&#xff0c;从而实现对象共享…

AMEYA360分析:纳芯微推出超低功耗TMR开关/锁存器 NSM105x系列

纳芯微推出基于隧道磁阻 (TMR) 的超低功耗磁开关/锁存器NSM105x系列&#xff0c;为数字位置检测提供高精度的解决方案&#xff0c;可被广泛应用于工业与消费领域的位置检测。 NSM105x产品系列包含了3个产品型号&#xff0c;即NSM1051(单极开关)、NSM1052(全极开关)、NSM1053(锁…

四种常见软件架构简介

文章目录 一、单体架构二、分布式应用三、微服务架构四、Serverless架构五、总结 如果一个软件开发人员&#xff0c;不了解软件架构的演进&#xff0c;会制约技术的选型和开发人员的生存、晋升空间。这里我列举了目前主要的四种软件架构以及他们的优缺点&#xff0c;希望能够帮…

uniapp 显示icon异常

按照文档创建的uni-ui项目&#xff0c;仿照示例程序写的代码中icon显示异常 &#xe470; 异常情况&#xff1a; 正常情况&#xff1a; 通过比对代码发现&#xff0c;示例程序的App.vue中 有一个引用是问题的关键 正是因为多了这一个引用文件&#xff0c;图表的显示才能正常 …

在Linux怎么用vim实现把一个文件里面的文本复制到另一个文件里面

2023年10月9日&#xff0c;周一下午 我昨天遇到了这个问题&#xff0c;但在网上没找到图文并茂的博客&#xff0c;于是我自己摸索出解决办法后&#xff0c;决定写一篇图文并茂的博客。 情景 假设现在我要用vim把file_transfer.cpp的内容复制到file_transfer.hpp里面 第一步 …

网络安全(黑客)小白学习笔记

前言 一、什么是网络安全 网络安全可以基于攻击和防御视角来分类&#xff0c;我们经常听到的 “红队”、“渗透测试” 等就是研究攻击技术&#xff0c;而“蓝队”、“安全运营”、“安全运维”则研究防御技术。 无论网络、Web、移动、桌面、云等哪个领域&#xff0c;都有攻与防…

linux centos出现No space left on device解决方案

问题是因为系统磁盘空间不足 解决方法: 找到那个磁盘不足问题 df -lh 发现/dev/mapper/cl-root磁盘已用50G,有如下 解决方案&#xff1a; 1、如果是虚拟机可以通过分配空间使其空间增加 2、将其他不常用磁盘空间分配给cl-root如&#xff08; /dev/mapper/cl-home &#…

路径总和 III

题目链接 路径总和 III 题目描述 注意点 二叉树的节点个数的范围是 [0,1000]求该二叉树里节点值之和等于 targetSum 的 路径 的数目 解答思路 可根据前缀和的思路解决本题&#xff0c;前缀和表示从根节点开始&#xff0c;往左或往右组成的路径和&#xff0c;统计从根节点开…