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;
}

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

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

相关文章

学习网络编程No.11【传输层协议之UDP】

引言&#xff1a; 北京时间&#xff1a;2023/11/20/9:17&#xff0c;昨天成功更文&#xff0c;上周实现了更文两篇&#xff0c;所以这周再接再厉。当然做题任在继续&#xff0c;而目前做题给我的感觉以套路和技巧偏多&#xff0c;还是那句话很多东西不经历你就是不懂&#xff…

【Python】2. 基础语法

常量和表达式 我们可以把 Python 当成一个计算器, 来进行一些算术运算. 注意: print 是一个 Python 内置的 函数, 这个稍后详细介绍. 可以使用 - * / ( ) 等运算符进行算术运算. 先算乘除, 后算加减. 运算符和数字之间, 可以没有空格, 也可以有多个空格. 但是一般习惯上写一…

LDR6328芯片:智能家居时代的小家电充电革新者

在当今的智能家居时代&#xff0c;小家电的供电方式正变得越来越智能化和高效化。 利用PD&#xff08;Power Delivery&#xff09;芯片进行诱骗取电&#xff0c;为后端小家电提供稳定电压的技术&#xff0c;正逐渐成为行业的新宠。在这一领域&#xff0c;LDR6328芯片以其出色的…

Qt下使用modbus-c库实现PLC线圈/保持寄存器的读写

系列文章目录 提示&#xff1a;这里是该系列文章的所有文章的目录 第一章&#xff1a;Qt下使用ModbusTcp通信协议进行PLC线圈/保持寄存器的读写&#xff08;32位有符号数&#xff09; 第二章&#xff1a;Qt下使用modbus-c库实现PLC线圈/保持寄存器的读写 文章目录 系列文章目录…

前端Vue3项目如何打包成Docker镜像运行

将前端Vue3项目打包成Docker镜像并运行包括几个主要步骤&#xff1a;项目打包、编写Dockerfile、构建镜像和运行容器。下面是一个基本的流程&#xff1a; 1. 项目打包 首先&#xff0c;确保你的Vue3项目可以正常运行和打包。在项目根目录下执行以下命令来打包你的Vue3项目&am…

nest.js使用nest-winston日志一

nest-winston文档 nest-winston - npm 参考&#xff1a;nestjs中winston日志模块使用 - 浮的blog - SegmentFault 思否 安装 cnpm install --save nest-winston winstoncnpm install winston-daily-rotate-file 在main.ts中 import { NestFactory } from nestjs/core; im…

【5G 接口协议】GTP-U协议介绍

博主未授权任何人或组织机构转载博主任何原创文章&#xff0c;感谢各位对原创的支持&#xff01; 博主链接 本人就职于国际知名终端厂商&#xff0c;负责modem芯片研发。 在5G早期负责终端数据业务层、核心网相关的开发工作&#xff0c;目前牵头6G算力网络技术标准研究。 博客…

基础小白快速入门Python------>模块的作用和意义

模块&#xff0c; 这个词听起来是如此的高大威猛&#xff0c;以至于萌新小白见了瑟瑟发抖&#xff0c;本草履虫见了都直摇头&#xff0c;好像听上去很难的样子&#xff0c;但是但是&#xff0c;年轻人&#xff0c;请听本少年细细讲述&#xff0c;他只是看起来很难&#xff0c;实…

GO-接口

1. 接口 在Go语言中接口&#xff08;interface&#xff09;是一种类型&#xff0c;一种抽象的类型。 interface是一组method的集合&#xff0c;接口做的事情就像是定义一个协议&#xff08;规则&#xff09;&#xff0c;只要一台机器有洗衣服和甩干的功能&#xff0c;我就称它…

【go语言开发】swagger安装和使用

本文主要介绍go-swagger的安装和使用&#xff0c;首先介绍如何安装swagger&#xff0c;测试是否成功&#xff1b;然后列出常用的注释和给出使用例子&#xff1b;最后生成接口文档&#xff0c;并在浏览器上测试 文章目录 安装注释说明常用注释参考例子 文档生成格式化文档生成do…

大模型生成,Open API调用

大模型是怎么生成结果的 通俗原理 其实&#xff0c;它只是根据上文&#xff0c;猜下一个词&#xff08;的概率&#xff09;…… OpenAI 的接口名就叫【completion】&#xff0c;也证明了其只会【生成】的本质。 下面用程序演示【生成下一个字】。你可以自己修改 prompt 试试…

【C++】类的转换函数

使用场景 C中当你创建了一个类&#xff0c;你想把这个类对象转换成基本类型的函数。类对象->基本类型对象 原理 如下实例&#xff0c;设计一个分数类&#xff0c;实现分数转换成double 浮点数的转换函数。并在mian函数隐式调用。 #include<iostream> class Fractio…

Python爬虫Cookies 池的搭建

Cookies 池的搭建 很多时候&#xff0c;在爬取没有登录的情况下&#xff0c;我们也可以访问一部分页面或请求一些接口&#xff0c;因为毕竟网站本身需要做 SEO&#xff0c;不会对所有页面都设置登录限制。 但是&#xff0c;不登录直接爬取会有一些弊端&#xff0c;弊端主要有…

南京师范大学计电院数据结构课设——排序算法

1 排序算法 1.1 题目要求 编程实现希尔、快速、堆排序、归并排序算法。要求首先随机产生10000个数据存入磁盘文件&#xff0c;然后读入数据文件&#xff0c;分别采用不同的排序方法进行排序并将结果存入文件中。 1.2 算法思想描述 1.2.1 随机数生成 当需要生成一系列随机数…

windows 11 前后端项目部署

目录 1.准备环境&#xff1a; 2.安装jdk 测试&#xff1a;winr 输入cmd 3.安装tomcat 4.安装mysql 远程导入数据&#xff1a; 外部后台访问&#xff1a;192.168.232.1:8080/crm/sys/loginAction.action?usernamezs&password123 5.安装nginx 前后端部署&#xff1…

qsort函数的模拟实现(冒泡排序模拟)

冒泡排序&#xff1a; 从第一个元素开始&#xff0c;依次比较相邻的两个元素&#xff0c;如果顺序不对就交换它们。 经过一轮遍历后&#xff0c;最大&#xff08;或最小&#xff09;的元素会排在最后。 重复进行上述步骤&#xff0c;直到没有任何元素需要交换&#xff0c;即…

爬虫入门到精通_实战篇8(分析Ajax请求并抓取今日头条美食美图)_界面上抓取Ajax方式

1 目标 目标&#xff1a; 抓取今日头条美食美图&#xff0c;如下&#xff1a; 一些网页直接请求得到的HTML代码并没有在网页中看到的内容&#xff0c;因为一些信息是通过Ajax加载&#xff0c;并通过js渲染生成的&#xff0c;这时就需要通过分析网页的请求来获取想要爬取的内容…

CSS 盒子模型(box model)

概念 所有HTML元素可以看作盒子&#xff0c;在CSS中&#xff0c;"box model"这一术语是用来设计和布局时使用CSS盒模型本质上是一个盒子&#xff0c;封装周围的HTML元素&#xff0c;它包括&#xff1a;外边距(margin)&#xff0c;边框(border)&#xff0c;内边距(pad…

关于 HTTP 协议,你了解多少

HTTP协议 FastAPI 是建立在 HTTP 协议之上&#xff0c;所以为了更好的掌握 FastAPI。我们需要先简单的了解一下 HTTP协议 简介 HTTP&#xff08;Hypertext Transfer Protocol&#xff09;遵循经典的客户端-服务器模型&#xff0c;客户端打开连接以发出请求&#xff0c;然后等…

【Go语言】Go语言中的流程控制

Go语言中的流程控制 流程控制主要用于设定计算执行的顺序&#xff0c;简历程序的逻辑结果&#xff0c;Go语言的流程控制语句与其他语言类似&#xff0c;支持如下几种流程控制语句&#xff1a; 条件语句&#xff1a;用于条件判断&#xff0c;对应的关键字有if、else和else if&a…