c语言数据结构(5)——栈

欢迎来到博主的专栏——C语言数据结构
博主id:代码小豪

文章目录

    • 栈的顺序存储结构
      • 栈的插入
      • 空栈的初始化
      • 栈的删除
      • 判断空栈
      • 读取栈顶元素数据
    • 实现顺序栈的所有代码
    • 栈的链式存储结构
      • 链式栈的初始化
      • 链式栈的入栈操作
      • 链式栈的出栈操作
    • 实现链式栈的所有代码

栈是一个特殊线性表,其只能在表尾进行数据的插入与删除,进行数据的插入与删除的一端称为栈顶 (TOP)。

我们可以将栈想象成一个酸菜坛子,往坛子中开始放菜的时候,坛中的酸菜是从底部开始增加的。

当坛子放满酸菜后,我们开坛取出酸菜,酸菜会从顶部开始减少。

栈的顺序存储结构

前面提到了,栈是一个特殊的线性表,所以栈的储存形式也可以像线性表一样分为两种,一种为顺序存储结构的栈(顺序栈)。

既然顺序栈是用顺序结构实现的,那么就可以用数组来实现顺序栈。

顺序栈的结构声明如下:

typedef int SDataType;
typedef struct SeqStack
{
	SDataType val[MAXSIZE];
	int TOP;
}SeqStack;

栈的插入

从栈顶插入数据的操作被称为入栈(PUSH)
在这里插入图片描述

将数据插入栈顶的位置,然后栈顶的位置往上挪动一位,用于下一次入栈操作。

为空时,栈顶的位置为0.
在这里插入图片描述

还有一种空栈的表示方法,由于数组中第一个元素的下标是0,但是空栈就代表着0下标处没有元素,所以空栈时,栈顶的位置为-1.
在这里插入图片描述
如果用这个方法表示的空栈,在插入数据时应该先让栈顶往上一步,再插入数据。
在这里插入图片描述

void StackPush(SeqStack* stack, SDataType e)
{
	if (stack->TOP == MAXSIZE)
	{
		perror("stack overflow\n");
		return;
	}
	stack->val[stack->TOP] = e;
	stack->TOP++;
}

空栈的初始化

将一个新生成的栈传入函数进行初始化,初始化的方法根据入栈的形式而定(TOP为0或TOP为-1)

以前者为例,空栈的初始化的函数为

void StackInit(SeqStack* stack)
{
	stack->TOP = 0;
}

栈的删除

从栈顶删除数据的操作称为出栈(POP)
在这里插入图片描述

出栈的方式很简单,我们不用将当前栈顶的数据进行处理,只需要将TOP的位置往下移动一格就行。

要注意当栈为空栈时的特殊情况,当栈为空栈时,出栈的操作会导致TOP位于非法的位置,当下次进行入栈操作时,就会发生数组越位的错误发生。

判断空栈

判断空栈的条件需要按照初始化时,栈顶的位置为准,以前者为例

bool StackEmpty(SeqStack* stack)
{
	return stack->TOP == 0;
}

如果TOP为0,那么该函数返回值为true。反之为false。

出栈的函数需要调用判断空栈的函数,如下:

void StackPop(SeqStack* stack)
{
	if (StackEmpty(stack))
	{
		perror("stack is empty\n");
		return;
	}
	stack->top--;
}

读取栈顶元素数据

SDataType StackTop(SeqStack* stack)
{
	return stack->val[stack->top - 1];
}

实现顺序栈的所有代码

typedef int SDataType;
typedef struct SeqStack
{
	SDataType val[MAXSIZE];
	int top;
}SeqStack;

void ListStackInit(ListStack* stack)
{
	assert(stack);
	stack->top = NULL;
	stack->lenth = 0;
}

void ListStackPush(ListStack* stack, LDataType e)
{
	StackNode* newnode = malloc(sizeof(StackNode));
	assert(newnode);
	newnode->val = e;
	newnode->next = stack->top;
	stack->top = newnode;
	stack->lenth++;
}

bool ListStackEmpty(ListStack* stack)
{
	return stack->top == NULL;
}

void ListStackPop(ListStack* stack)
{
	if (!ListStackEmpty(stack))
	{
		perror("stack is empty\n");
		return;
	}
	StackNode* del = stack->top;
	stack->top = stack->top->next;
	free(del);
}

LDataType ListStackTop(ListStack* stack)
{
	assert(stack);
	return stack->top->val;
}

栈的链式存储结构

栈既然是线性表,就可以用链表的形式来实现。

栈是从表尾进行插入和删除,链表可以用尾插\尾删的方法实现出栈和入栈(?)。

在这里插入图片描述

在这里插入图片描述
可以发现,使用尾删法是不能实现出栈操作的,因为单链表不能将TOP回到上一个数据的位置。

为了解决这个问题,我们将TOP的位置变为链表头,将入栈和出栈的操作用头插\头删法来实现。

在这里插入图片描述
在这里插入图片描述
链式栈的结构类型如下:

typedef int LDataType;
typedef struct StackNode
{
	LDataType val;
	struct StackNode* next;
}StackNode;

typedef struct ListStack
{
	StackNode* top;
	int lenth;
};

链式栈的初始化

链式栈的初始化如下

void ListStackInit(ListStack* stack)
{
	assert(stack);
	stack->top = NULL;
	stack->lenth = 0;
}

链式栈的入栈操作

链式栈入栈使用头插法。代码如下:

void ListStackPush(ListStack* stack, LDataType e)
{
	StackNode* newnode = malloc(sizeof(StackNode));
	assert(newnode);
	newnode->val = e;
	newnode->next = stack->top;
	stack->top = newnode;
	stack->lenth++;
}

链式栈的出栈操作

考虑到链表空栈无法出栈,所以先定义一个判断空栈的函数

bool ListStackEmpty(ListStack* stack)
{
	return stack->top == NULL;
}

链式栈出栈使用头删法。代码如下:

void ListStackPop(ListStack* stack)
{
	if (ListStackEmpty(stack))
	{
		perror("stack is empty\n");
		return;
	}
	StackNode* del = stack->top;
	stack->top = stack->top->next;
	free(del);
}

实现链式栈的所有代码

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>

typedef int LDataType;
typedef struct StackNode
{
	LDataType val;
	struct StackNode* next;
}StackNode;

typedef struct ListStack
{
	StackNode* top;
	int lenth;
}ListStack;

void ListStackInit(ListStack* stack);
void ListStackPush(ListStack* stack,LDataType e);
void ListStackPop(ListStack* stack);
bool ListStackEmpty(ListStack* stack);
LDataType ListStackTop(ListStack* stack);

void ListStackInit(ListStack* stack)
{
	assert(stack);
	stack->top = NULL;
	stack->lenth = 0;
}

void ListStackPush(ListStack* stack, LDataType e)
{
	StackNode* newnode = malloc(sizeof(StackNode));
	assert(newnode);
	newnode->val = e;
	newnode->next = stack->top;
	stack->top = newnode;
	stack->lenth++;
}

bool ListStackEmpty(ListStack* stack)
{
	return stack->top == NULL;
}

void ListStackPop(ListStack* stack)
{
	if (ListStackEmpty(stack))
	{
		perror("stack is empty\n");
		return;
	}
	StackNode* del = stack->top;
	stack->top = stack->top->next;
	free(del);
}

LDataType ListStackTop(ListStack* stack)
{
	assert(stack);
	return stack->top->val;
}

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

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

相关文章

麒麟银河操作系统V10部署ffmpeg(也能用于Linux系统)

麒麟银河操作系统V10部署ffmpeg(也能用于Linux系统) 部署ffmpeg用来处理视频的各种操作 想使用ffmpeg&#xff0c;要先安装nasm&#xff0c;yasm&#xff0c;x264之后&#xff0c;否则会报错 nkvers 查看麒麟操作系统版本 cat /proc/version #查看linux版本信息 uname -a …

基于自定义组件实现微信小程序动态tabBar,根据不同用户角色显示不同底部tabBar,支持自由组合总数超过5个(更新版)

文章目录 背景实现步骤&#xff1a;1、我们先在utils目录中创建tab-service.js文件&#xff0c;写上全局的数据及方法&#xff1b;2、在app.json文件中配置导航信息3、根目录下创建custom-tab-bar目录4、编写custom-tab-bar组件4.1、custom-tab-bar/index.wxml4.2、custom-tab-…

NLP算法实战项目:使用 BERT 进行文本多分类

大多数研究人员将他们的研究论文提交给学术会议&#xff0c;因为这是更快地使研究结果可用的途径。寻找和选择合适的会议一直是一项具有挑战性的任务&#xff0c;特别是对于年轻的研究人员来说。基于先前会议论文集的数据&#xff0c;研究人员可以增加其论文被接受和发表的机会…

手把手教测试,全网内容最全有深度-jmeter-DBC Request

5.1.7.4.JDBC Request 具体参见数据库操作章节 5.1.7.5.jpgc - Dummy Sampler 用于模拟一个接口请求&#xff0c;效果类似于Mock。 手把手教测试&#xff0c;持续更新。学习、咨询测试技术&#xff0c;获取完整资料加V&#xff1a;SobasoTest

揭秘Java性能调优的层次 | 综合多方向提升应用程序性能与系统高可用的关键(架构层次规划)

揭秘性能调优的层次 | 综合多方向提升应用程序性能与系统的高可用 前言介绍调优层次调优 — 设计案例说明 - 操作轮询控制事件驱动 调优 — 代码案例说明 - ArrayList和LinkedList性能对比案例说明 - 文件读写实现方式的性能对比 调优 — JVMJVM架构分布JVM调优方向**JVM垃圾回…

Spring注解之处理常见的 HTTP 请求

5 种常见的请求类型: GET &#xff1a;请求从服务器获取特定资源。举个例子&#xff1a;GET /users&#xff08;获取所有学生&#xff09;POST &#xff1a;在服务器上创建一个新的资源。举个例子&#xff1a;POST /users&#xff08;创建学生&#xff09;PUT &#xff1a;更新…

铅冶炼作业VR虚拟现实互动培训平台降低实操风险

在钢铁工业中&#xff0c;焦炉作业是一个关键的环节&#xff0c;也是一项技术要求高、操作复杂的任务。传统焦炉作业的培训通常需要在实际的焦炉上进行&#xff0c;这不仅对学员的身体素质和心理素质提出了较高的要求&#xff0c;而且也存在一定的安全风险。基于VR虚拟现实制作…

Libero集成开发环境中Identify应用与提高

Libero集成开发环境中Identify应用与提高 Identify的安装

专业130+总分410+上海交通大学819信号系统与信号处理考研上交电子信息通信生医电科,真题,大纲,参考书。

今年考研顺利结束&#xff0c;我也完成了目前人生最大的逆袭&#xff0c;跨了两个层级跨入c9&#xff0c;专业课819信号系统与信息处理135&#xff0c;数一130总分410&#xff0c;考上上海交大&#xff0c;回想这一年经历了很多&#xff0c;也成长了很多。从周围朋友&#xff0…

运筹学_1.2线性规划问题的几何意义

1.2线性规划问题的几何意义 一、凸集的基本概念二、由线性规划问题的几何意义、定理得出的几点结论三、引出单纯形法的解题步骤 一、凸集的基本概念 通俗来说&#xff0c;一个图形上任意两个点的连线上的点全部存在于这个图形中 二、由线性规划问题的几何意义、定理得出的几点结…

latex报错I was expecting a `,‘ or a `}‘的解决办法

解决办法——经过检查在ref22后面缺少一个逗号 总结 当你在使用LaTeX时遇到“I was expecting a , or a }”这样的错误&#xff0c;这通常意味着LaTeX在解析你的代码时&#xff0c;预期在某个位置看到一个逗号&#xff08;,&#xff09;或一个大括号&#xff08;}&#xff09;…

AI时代来临:解锁大模型的神秘面纱!

在AI时代的黎明&#xff0c;大模型技术的发展不仅仅是科技进步的一个标志&#xff0c;更是人类文明新篇章的开启。这篇文章旨在揭开大模型的神秘面纱&#xff0c;探索其对未来社会的深远影响。 大模型&#xff0c;作为人工智能领域的一个重要分支&#xff0c;其核心在于构建能…

java List.forEach 引发的生产投诉

代码运行时直接抛异常报错&#xff0c;这个算是不幸中的万幸&#xff0c;至少可以及时发现并去解决代码运行不报错&#xff0c;但是业务逻辑莫名其妙的出现各种奇怪问题&#xff0c;这种就比较悲剧了&#xff0c;因为这个问题稍不留神的话&#xff0c;可能就会给后续业务埋下隐…

Vue3 循环渲染 v-for

v-for 指令&#xff1a;用于循环渲染列表数据。 v-for 指令&#xff1a;可以循环数组、对象、字符串【不常用】、指定次数【很少用】。 key 属性&#xff1a;用于给标签添加一个唯一的标识。 key 属性&#xff1a;推荐使用 id、手机号、身份证号、学号 等唯一值。 注&#…

ora2pg使用教程

简介 ora2pg是一个迁移工具&#xff0c;是将oracle数据库迁移到postgres的一个强大的工具 安装及使用 拉取镜像 docker pull georgmoser/ora2pg 如果拉取比较慢&#xff0c;可以使用上面绑定的镜像文件 使用加载镜像命令 docker load -i ora2gp.tar 使用镜像文件很方便&…

【C++入门】缺省参数 | 函数重载

目录 4.缺省参数 4.1缺省参数的概念 4.2缺省参数分类 4.3声明和定义分离&#xff08;声明使用缺省参数&#xff09; 4.&#x1f40d;声明和定义分离到链接 5.函数重载 5.1函数重载的概念 5.2可执行程序的形成步骤 5.3C支持函数重载的原理—名字修饰(name Mangling) 4.…

嵌入式中汇编语言的基本实现

大家好&#xff0c;今天给大家分享&#xff0c;GNU汇编的语法。 第一&#xff1a;汇编简介 GNU 汇编语法适用于所有的架构&#xff0c;并不是 ARM 独享的&#xff0c;GNU 汇编由一系列的语句组成&#xff0c; 每行一条语句&#xff0c;每条语句有三个可选部分&#xff0c;如下…

AG32 MCU 如何进入低功耗模式

默认情况下&#xff0c;微控制器(MCU)在系统复位或电源复位后处于运行模式。当CPU不需要持续运行时&#xff0c;可以使用几种低功耗模式来节省功耗。这是由用户选择的模式&#xff0c;给出了低功耗&#xff0c;短启动时间和可用的唤醒源之间的最佳妥协。 AG32VF 系列MCU具有以下…

【C++提高编程】

C提高编程 C提高编程1 模板1.1 模板的概念1.2 函数模板1.2.1 函数模板语法1.2.2 函数模板注意事项1.2.3 函数模板案例1.2.4 普通函数与函数模板的区别1.2.5 普通函数与函数模板的调用规则1.2.6 模板的局限性 1.3 类模板1.3.1 类模板语法1.3.2 类模板与函数模板区别1.3.3 类模板…

李沐动手学习深度学习——4.2练习

1. 在所有其他参数保持不变的情况下&#xff0c;更改超参数num_hiddens的值&#xff0c;并查看此超参数的变化对结果有何影响。确定此超参数的最佳值。 通过改变隐藏层的数量&#xff0c;导致就是函数拟合复杂度下降&#xff0c;隐藏层过多可能导致过拟合&#xff0c;而过少导…