#数据结构 链式栈

1. 概念

链式栈LinkStack

  1. 逻辑结构:线性结构
  2. 物理结构:链式存储
  3. 栈的特点:后进先出

栈具有后进先出的特点,我们使用链表来实现栈,即链式栈。那么栈顶是入栈和出栈的地方,单向链表有头有尾,那我们将链表的头作为栈顶还是链表的尾作为栈顶呢?如果每次在链表的尾部进行插入或删除,就需要遍历整个链表来找到尾结点即终端结点。而在头部即起始结点进行插入或删除时,仅需头指针找到链表的起始结点,而无需遍历整个链表。

所以链式栈的入栈、出栈都是通过对链表进行头插、头删来实现。

既然要对单向链表进行头插、头删,那么头结点的存在会让操作变得复杂,故我们使用无头单向链表。

无头单向链表的头就是栈顶,故栈针是指向无头单向链表的起始结点的,所以我们在链式栈中将头指针H称做栈针top。top栈针永远指向无头单向链表的第一个节点,栈空的时候除外。

对于链栈来说,基本不存在栈满的情况,除非内存已经没有可以使用的空间。

对于空栈来说,链表即H == NULL,链式栈即top == NULL

2. 接口实现

#ifndef _LINKSTACK_H_
#define _LINKSTACK_H_
#include <stdio.h>
#include <stdlib.h>
//入栈和出栈只在第一个节点位置操作
typedef int datatype;
typedef struct linkstack
{
	datatype data;//数据域
	struct linkstack *next;//指针域
}linkstack_t;
//1.创建一个空的栈
void CreateEpLinkStack(linkstack_t **ptop);
//2.入栈   data是入栈的数据
//参数上之所以采用二级指针,因为我们要随着入栈添加新的节点作为头,top需要永远指向当前链表的头,那么修改main函数中的top,我们采用地址传递
int PushLinkStack(linkstack_t **ptop, datatype data);
//3.判断栈是否为空
int IsEpLinkStack(linkstack_t *top);
//4.出栈
datatype PopLinkStack(linkstack_t **ptop);
//5.清空栈
void ClearLinkStack(linkstack_t **ptop);//用二级指针,是因为清空后需要将main函数中的top变为NULL
//6.求栈的长度
int LengthLinkStack(linkstack_t *top);//用一级指针,是因为我只是求长度,不需要修改main函数中top指针的指向
//7.获取栈顶数据,不是出栈,不需要移动main函数中的top,所以用一级指针
datatype GetTopLinkStack(linkstack_t *top);
#endif

2.1. 定义操作链式栈的结构体

//入栈和出栈只在第一个节点位置操作
typedef int datatype;
typedef struct linkstack
{
	datatype data;//数据域
	struct linkstack *next;//指针域
}linkstack_t;

2.2. 创建空的链式栈

#include "linkstack.h"
void CreateEpLinkStack(linkstack_t **ptop)
{	
	//top = NULL;
	*ptop = NULL;
}
#include "linkstack.h"
int main(int argc, const char *argv[])
{
	linkstack_t *top;
	CreateEpLinkStack(&top);
	return 0;
}

2.3. 入栈

思想:

开辟新结点存放入栈数据

每次都将新结点链接到无头单向链表的头

栈针top永远指向无头单向链表的头,栈空时除外

顺序栈需要判满,但链式栈无需判满

/*2.入栈   data是入栈的数据
//参数上之所以采用二级指针,因为我们要随着入栈添加新的节点作为头,top需要永远指向当前链表的头,
//那么修改main函数中的top,我们采用地址传递*/
int PushLinkStack(linkstack_t **ptop, datatype data)
{	
	linkstack_t *pnew = (linkstack_t *)malloc(sizeof(linkstack_t));
	if(NULL == pnew)
	{
		printf("PushLinkStack pnew malloc failed\n");
		return -1;
	}
	//给新节点初始化
	pnew->data = data;
	pnew->next = *ptop;      
	*ptop = pnew;
  
	return 0;
}
#include "linkstack.h"
int main(int argc, const char *argv[])
{
	linkstack_t *top;
	CreateEpLinkStack(&top);
	int i;
	for(i = 0; i < 5; i++)
	{
		PushLinkStack(&top,i);
	}
	return 0;
}

2.4. 出栈

顺序栈需要判空即PS->top==-1

链式栈也需要判空即top == NULL

判空无需改变主函数栈针top的指向,故无需传递top的地址。

但出栈后需要移动栈针,改变top的指向,故需要传递栈针top的地址&top

综上,出栈函数需要传递栈针top的地址&top

//3.判断栈是否为空
int IsEpLinkStack(linkstack_t *top)
{
	return top == NULL;
}
//4.出栈
datatype PopLinkStack(linkstack_t **ptop)
{
	if(IsEpLinkStack(*ptop))
	{
		printf("PopLinkStack failed\n");
		return -1;
	}
	datatype temp;
	linkstack_t *pdel = NULL;
#if 0
	pdel = *ptop;
	temp = pdel->data;
	*ptop = pdel->next;
	free(pdel);
	pdel = NULL;
	return temp;
#endif
#if 1
	temp = (*ptop)->data;
	pdel = *ptop;
	*ptop = (*ptop)->next;
	free(pdel);
	pdel = NULL;
	return temp;
}
#include "linkstack.h"
int main(int argc, const char *argv[])
{
	linkstack_t *top;
	CreateEpLinkStack(&top);
	int i;
	for(i = 0; i < 5; i++)
	{
		PushLinkStack(&top,i);
	}
#if 0
	for(i = 0; i < 5; i++)	
		printf("%d ",PopLinkStack(&top));
	}
	printf("\n");		
#endif
	return 0;
}
4 3 2 1 0 

2.5. 栈长

问:求栈长是否需要传递栈针的地址? 无需

问:求栈长能否传递栈针的地址? 可以

//6.求栈的有效长度
int LengthLinkStack(linkstack_t *top)//用一级指针,是因为我只是求长度,不需要修改main函数中top指针的指向
{
	int len = 0;
	while(top != NULL)
	{
		len++;
		top = top->next;
	}
	return len;
}
#include "linkstack.h"
int main(int argc, const char *argv[])
{
	linkstack_t *top;
	CreateEpLinkStack(&top);
	int i;
	for(i = 0; i < 5; i++)
	{
		PushLinkStack(&top,i);
	}
#if 0
	for(i = 0; i < 5; i++)
	{
		printf("%d ",PopLinkStack(&top));
	}
	printf("\n");		
#endif
	printf("len:%d\n",LengthLinkStack(top));
return 0;
}

2.6. 获取栈顶数据

问:获取栈顶数据是否需要移动栈针?

问:获取栈顶数据是否需要传递栈针地址?

获取栈顶数据,部署出栈,无需移动栈针,故无需传递栈针top的地址&top

//7.获取栈顶数据,不是出栈,不需要移动main函数中的top,所以用一级指针
datatype GetTopLinkStack(linkstack_t *top)
{
	if(!IsEpLinkStack(top))
	{
		return top->data;
	}
	return -1;
}
#include "linkstack.h"
int main(int argc, const char *argv[])
{
	linkstack_t *top;
	CreateEpLinkStack(&top);
	int i;
	for(i = 0; i < 5; i++)
	{
		PushLinkStack(&top,i);
	}
#if 0
	for(i = 0; i < 5; i++)
	{
		printf("%d ",PopLinkStack(&top));
	}
	printf("\n");		
#endif
	printf("len:%d\n",LengthLinkStack(top));
	printf("top_data%d\n",GetTopLinkStack(top));
	return 0;
}

2.7. 清空

只要不空一直出栈

//5.清空栈
void ClearLinkStack(linkstack_t **ptop)//用二级指针,是因为清空后需要将main函数中的top变为NULL
{	
	while(!IsEpLinkStack(*ptop))
	{
		PopLinkStack(ptop);
	}
}
#include "linkstack.h"
int main(int argc, const char *argv[])
{
	linkstack_t *top;
	CreateEpLinkStack(&top);
	int i;
	for(i = 0; i < 5; i++)
	{
		PushLinkStack(&top,i);
	
#if 0
	for(i = 0; i < 5; i++)
	{
		printf("%d ",PopLinkStack(&top));
	}
	printf("\n");		
#endif
	printf("len:%d\n",LengthLinkStack(top));
	printf("top_data%d\n",GetTopLinkStack(top));
	ClearLinkStack(&top);
	return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Java + MySQL 实现存储完整 Json

Java MySQL 实现存储完整 Json 一、应用场景二、数据库配置三、后端代码配置1、maven 依赖2、实体类3、Service 实现类4、xml 文件 四、测试1、新增接口2、查询接口3、数据表内容 一、应用场景 将前端传过来的 Json 完整存储到 MySQL 中&#xff0c;涉及技术栈为 Java、MyBat…

Git中两个开发分支merge的原理

一 分支合并 1.1 原理 分支合并&#xff1a;就是将A分支修改后且commit的内容&#xff0c;合并到B分支&#xff0c;这些修改且提交的内容和B分支对应的内容和位置进行比较&#xff1a; 1.不一样的话&#xff0c;提示冲突&#xff0c;需要人工干预。 2.一样的话&#xff0c;…

python读取csv出错怎么解决

Python用pandas的read_csv函数读取csv文件。 首先&#xff0c;导入pandas包后&#xff0c;直接用read_csv函数读取报错OSError&#xff0c;如下&#xff1a; 解决方案是加上参数&#xff1a;enginepython。 运行之后没有报错&#xff0c;正在我欣喜之余&#xff0c;输出一下d…

LT8712 支持USB Type-C的DP到HDMI/VGA 用于对接站 适配器

描述 LT8712是一个DisplayPort(DP)到HDMI和VGA转换器&#xff0c;设计用于同时连接一个DP源到一个VGA收发器和最多两个HDMI收发器。LT8712集成了一个DP1.2兼容的接收器、一个高速三通道视频DAC和两个HDMI1.4兼容的发射器(发射器0和发射器1)。接收端口集成了CC控制器&#xff0c…

『古籍自有答案』古风H5案例赏析

「古籍自有答案」&#xff0c;一部由新京报与字节跳动公益联合打造的古风H5&#xff0c;以诗意盎然的开篇引领用户穿梭于千年文脉。 part1. 创意定位 "人生有惑问先贤&#xff0c;先贤答案存古籍"&#xff0c;在这里&#xff0c;每一个灵魂的探问&#xff0c;都能在…

ElasticSearch 如何计算得分及一个不太成熟的使用

1.背景 最近在做 ES 相关东西&#xff0c;只最会在查询的时候给不同的字段设置不同的权重&#xff0c;但是得分具体怎么算的不太明白&#xff0c;花了4-5 天研究和总结了一下。这样不至于被别人问到“这个分数怎么算出来的&#xff1f;”&#xff0c;两眼一抹黑&#xff0c;不…

前端面试题19(vue性能优化)

Vue.js应用的性能优化是一个多方面的过程&#xff0c;涉及初始化加载、运行时渲染以及用户交互等多个环节。以下是一些关键的Vue性能优化策略&#xff0c;包括详细的说明和示例代码&#xff1a; 1. 懒加载组件 对于大型应用&#xff0c;可以使用懒加载来减少初始加载时间。Vu…

策略模式的应用

前言 系统有一个需求就是采购员审批注册供应商的信息时&#xff0c;会生成一个供应商的账号&#xff0c;此时需要发送供应商的账号信息&#xff08;账号、密码&#xff09;到注册填写的邮箱中&#xff0c;通知供应商账号信息&#xff0c;当时很快就写好了一个工具类&#xff0…

华为机试HJ34图片整理

华为机试HJ34图片整理 题目&#xff1a; 想法&#xff1a; 将输入的字符串中每个字符都转为ASCII码&#xff0c;再通过快速排序进行排序并输出 input_str input() input_list [int(ord(l)) for l in input_str]def partition(arr, low, high):i low - 1pivot arr[high]f…

基于深度学习LightWeight的人体姿态检测跌倒系统源码

一. LightWeight概述 light weight openpose是openpose的简化版本&#xff0c;使用了openpose的大体流程。 Light weight openpose和openpose的区别是&#xff1a; a 前者使用的是Mobilenet V1&#xff08;到conv5_5&#xff09;&#xff0c;后者使用的是Vgg19&#xff08;前10…

啥?你没听过SpringBoot的FatJar?

写在最前面&#xff1a; SpringBoot是目前企业里最流行的框架之一&#xff0c;SpringBoot的部署方式多数采用jar包形式。通常&#xff0c;我们使用java -jar便可以直接运行jar文件。普通的jar只包含当前 jar的信息&#xff0c;当内部依赖第三方jar时&#xff0c;直接运行则会报…

数字化精益生产系统--MRP 需求管理系统

MRP&#xff08;Material Requirements Planning&#xff0c;物料需求计划&#xff09;需求管理系统是一种在制造业中广泛应用的计划工具&#xff0c;旨在通过分析和计划企业生产和库存需求&#xff0c;优化资源利用&#xff0c;提高生产效率。以下是对MRP需求管理系统的功能设…

[FreeRTOS 功能应用] 事件组 功能应用

文章目录 一、基础知识点二、代码讲解三、结果演示四、代码下载 一、基础知识点 [FreeRTOS 基础知识] 事件组 概念 [FreeRTOS 内部实现] 事件组 本实验是基于STM32F103开发移植FreeRTOS实时操作系统&#xff0c;事件组实战操作。(当task1和task2同时完成&#xff0c;才执行ta…

Python爬虫教程第1篇-基础知识

文章目录 什么是爬虫爬虫的工作原理用途搜索引擎爬虫Robots协议HTTP的请求过程URL的含义HTTP常见请求头爬虫常用的技术 什么是爬虫 信息的交互是通过web网页、或者移动端等不同的客户端端形式进行交互&#xff0c;这个过程是一个人与网路正常的交互行为。而爬虫可以用来模拟人…

easyx图形库

目录 1、绘制简单的图形化窗口 2、设置窗口属性 2.1 颜色设置 2.2 刷新 3、基本绘图函数 3.1 绘制直线 3.2 绘制圆 3.3 绘制矩形 4、贴图 4.1 原样贴图 4.1.1 IMAGE变量去表示图片 4.1.2 加载图片 4.1.3 显示图片 4.2 透明贴图 4.2.1 认识素材 4.3 png贴图 5…

使用块的网络 VGG

一、AlexNet与VGG 1、深度学习追求更深更大&#xff0c;使用VGG将卷积层组合为块 2、VGG块&#xff1a;3*3卷积&#xff08;pad1&#xff0c;n层&#xff0c;m通道&#xff09;、2*2最大池化层 二、VGG架构 1、多个VGG块后接全连接层 2、不同次数的重复块得到不同的架构&a…

go语言day10 接口interface 类型断言 type关键字

接口&#xff1a; 空接口类型&#xff1a; 要实现一个接口&#xff0c;就要实现该接口中的所有方法。因为空接口中没有方法&#xff0c;所以自然所有类型都实现了空接口。那么就可以使用空接口类型变量去接受所有类型对象。 类比java&#xff0c;有点像Object类型的概念&#x…

使用Docker、Docker-compose部署单机版达梦数据库(DM8)

安装前准备 Linux Centos7安装&#xff1a;https://blog.csdn.net/andyLyysh/article/details/127248551?spm1001.2014.3001.5502 Docker、Docker-compose安装&#xff1a;https://blog.csdn.net/andyLyysh/article/details/126738190?spm1001.2014.3001.5502 下载DM8镜像 …

数据按月分表

当数据量过大&#xff0c;从数据层面可以按月分表&#xff0c;报表查询时可以根据&#xff0c;查询时间来计算查询的年月&#xff0c;查询对应的表 1、按月分表&#xff1a; 存储过程SP_BRANCH_TABLE_TEST 以下存储过程分表&#xff0c;加了索引可以方便后续查询 USE [DASHBOAR…

三分钟内了解卷轴模式

在数字化时代的浪潮中&#xff0c;卷轴商业模式巧妙地将积分体系、互动任务、社交裂变、虚拟经济体系以及个性化成长路径等多元要素融为一体。 积分体系&#xff1a;激发参与动力的源泉 卷轴商业模式的核心在于其精心构建的积分系统。新用户踏入平台&#xff0c;即获赠一笔启…