数据结构:线性表(栈的实现)
文章目录
- 1. 栈(Stack)
- 1.1 栈的概念
- 1.2 栈的结构
- 链表栈
- 数组栈
- 2. 栈的定义
- 3. 栈的实现
- 3.1 初始化栈 (StackInit)
- 3.2 入栈 (StackPush)
- 3.3 出栈 (StackPop)
- 3.4 检测栈是否为空 (StackEmpty)
- 3.5 获取栈顶元素 (StackTop)
- 3.6 获取栈中有效元素个数 (StackSize)
- 3.7 销毁栈 (StackDestroy)
- 3.8 完整代码
1. 栈(Stack)
1.1 栈的概念
- 栈(Stack)是只允许在一端进行插入或删除操作的线性表.首先栈是一种线性表,但限定这种线性表只能在某一端进行插入和删除操作.
- 进行数据插入和删除操作的一端叫栈顶,另一端称为栈底.
- 栈中的元素遵循后进先出LIFO(Last In First Out)的原则
压栈:栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶.
出栈:栈的删除操作叫做出栈,出数据也在栈顶.
1.2 栈的结构
栈的元素,遵循后进先出原则
栈采用什么逻辑结构呢?
通常栈可以用链表和数组实现.
当然我们调用的时候不需要知道,使用的是什么方法实现.
链表栈
通过在表前端插入来实现 push ,通过删除表前端元素实现 pop.
可以使用之前实现的单链表来实现栈,单链表实现详见.只用注意,栈只有插入删除操作,需要头删和头插.
虽然操作都是花费常数时间,但是对malloc
和free
的调用是十分昂贵的.
数组栈
更为流行的是使用数组来实现栈.虽然数组的大小需要提前说明或者临时开辟,但是,在典型的应用程序中,栈元素的实际个数一般不会太大,使用数组是更加高效的方法.
总结:
- 推荐使用数组结构实现栈
- 若使用链表实现栈
用尾做栈顶,尾删尾插,要设计成双向链表
用头做栈顶,头删头插,要设计成单链表
2. 栈的定义
一般来说,使用动态栈而非静态栈,需要扩容的时候,可以进行适当扩容,增加了程序的适用性.
动态栈实现的数据结构
typedef int STDataType;typedef struct Stack
{STDataType* a; //指向栈空间int top; //栈顶int capacity; //容量
}Stack;
接口函数
// 初始化栈
void StackInit(Stack* ps);
// 入栈
void StackPush(Stack* ps, STDataType data);
// 出栈
void StackPop(Stack* ps);
// 获取栈顶元素
STDataType StackTop(Stack* ps);
// 获取栈中有效元素个数
int StackSize(Stack* ps);
// 检测栈是否为空, 如果为空返回非零结果, 如果不为空返回 0
int StackEmpty(Stack* ps);
// 销毁栈
void StackDestroy(Stack* ps);
3. 栈的实现
3.1 初始化栈 (StackInit)
// 初始化栈
void StackInit(Stack* ps)
{assert(ps);ps->a = NULL; ps->top = 0;ps->capacity = 0;
}
- 和创建顺序表的操作是一致的,通过结构体指针
ps
修改主函数中的结构体的成员变量,将ps
指向的数组指针指向NULL
,同时将容量capacity
和栈顶元素top
置为 0.
- 注意,在这里,
top
所指向的是栈顶元素后一个空间,此时没有元素,自然就指向了数组的第一个空间
3.2 入栈 (StackPush)
//入栈
void StackPush(Stack* ps, STDataType data)
{assert(ps); //确保ps合法//如果容量不够则扩容if (ps->capacity == ps->top){int newCapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity; //定义新的容量STDataType* tmp = (STDataType*)realloc(ps->a, sizeof(STDataType) * newCapacity); //开辟新的空间if (tmp == NULL){perror("malloc error");exit(-1);}else {ps->a = tmp;ps->capacity = newCapacity;}}//将数据入栈ps->a[ps->top] = data;ps->top++;
}
- 首先确保
ps
合法- 因为是动态栈,会出现空间不够的情况,在入栈之前首先确保容量充足,如果容量不够,则进行扩容
- 将数据入栈,同时
top++
3.3 出栈 (StackPop)
// 出栈
void StackPop(Stack* ps)
{assert(ps); //确保ps合法assert(!StackEmpty(ps)); //确保栈不为空ps->top--;}
- 确保 ps 合法
- 确保栈不为空
- 直接将
top--
即可
3.4 检测栈是否为空 (StackEmpty)
// 检测栈是否为空, 如果为空返回非零结果, 如果不为空返回 0
int StackEmpty(Stack* ps)
{assert(ps); //确保ps合法if (ps->top > 0){return 0;}else {return 1;}
}
- 确保ps合法
- 如果
top
大于0,说明栈不为空,反之则为空
3.5 获取栈顶元素 (StackTop)
// 获取栈顶元素
STDataType StackTop(Stack* ps)
{assert(ps); //确保ps合法assert(!StackEmpty(ps)); //确保栈不为空return ps->a[ps->top - 1];
}
- 确保ps合法
- 确保栈不为空
- 直接返回
top - 1
位置的元素
3.6 获取栈中有效元素个数 (StackSize)
// 获取栈中有效元素个数
int StackSize(Stack* ps)
{assert(ps); //确保ps合法return ps->top;
}
- 确保ps合法
- 直接将
top
返回即可
3.7 销毁栈 (StackDestroy)
// 销毁栈
void StackDestroy(Stack* ps)
{assert(ps); //确保ps合法free(ps->a);ps->a = NULL;ps->capacity = 0;ps->top = 0;
}
- 确保ps合法
- 将ps指向的数组空间归还给操作系统,同时将
top
和capacity
置为0
3.8 完整代码
Stack.h
#pragma once #include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <stdbool.h>typedef int STDataType;typedef struct Stack
{STDataType* a; //指向栈空间int top; //栈顶int capacity; //容量
}Stack;// 初始化栈
void StackInit(Stack* ps);
// 入栈
void StackPush(Stack* ps, STDataType data);
// 出栈
void StackPop(Stack* ps);
// 获取栈顶元素
STDataType StackTop(Stack* ps);
// 获取栈中有效元素个数
int StackSize(Stack* ps);
// 检测栈是否为空, 如果为空返回非零结果, 如果不为空返回 0
int StackEmpty(Stack* ps);
// 销毁栈
void StackDestroy(Stack* ps);
Stack.c
#include "Stack.h"// 初始化栈
void StackInit(Stack* ps)
{assert(ps);ps->a = NULL; ps->top = 0;ps->capacity = 0;
}//入栈
void StackPush(Stack* ps, STDataType data)
{assert(ps); //确保ps合法//如果容量不够则扩容if (ps->capacity == ps->top){int newCapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity; //定义新的容量STDataType* tmp = (STDataType*)realloc(ps->a, sizeof(STDataType) * newCapacity); //开辟新的空间if (tmp == NULL){perror("malloc error");exit(-1);}else {ps->a = tmp;ps->capacity = newCapacity;}}//将数据入栈ps->a[ps->top] = data;ps->top++;
}// 出栈
void StackPop(Stack* ps)
{assert(ps); //确保ps合法assert(!StackEmpty(ps)); //确保栈不为空ps->top--;}// 检测栈是否为空, 如果为空返回非零结果, 如果不为空返回 0
int StackEmpty(Stack* ps)
{assert(ps); //确保ps合法if (ps->top > 0){return 0;}else {return 1;}
}// 获取栈顶元素
STDataType StackTop(Stack* ps)
{assert(ps); //确保ps合法assert(!StackEmpty(ps)); //确保栈不为空return ps->a[ps->top - 1];
}// 获取栈中有效元素个数
int StackSize(Stack* ps)
{assert(ps); //确保ps合法return ps->top;
}// 销毁栈
void StackDestroy(Stack* ps)
{assert(ps); //确保ps合法free(ps->a);ps->a = NULL;ps->capacity = 0;ps->top = 0;
}
Test.c
#include "Stack.h"void StackTest1()
{Stack st;StackInit(&st);StackPush(&st, 1);printf("%d\n", StackSize(&st));printf("%d\n", StackTop(&st));StackPush(&st, 2);printf("%d\n", StackSize(&st));printf("%d\n", StackTop(&st));StackPush(&st, 3);printf("%d\n", StackSize(&st));printf("%d\n", StackTop(&st));StackPush(&st, 4);printf("%d\n", StackSize(&st));printf("%d\n", StackTop(&st));StackPush(&st, 5);printf("%d\n", StackSize(&st));printf("%d\n", StackTop(&st));StackPop(&st);printf("%d\n", StackSize(&st));printf("%d\n", StackTop(&st));StackPop(&st);printf("%d\n", StackSize(&st));printf("%d\n", StackTop(&st));StackPop(&st);printf("%d\n", StackSize(&st));printf("%d\n", StackTop(&st));StackPop(&st);printf("%d\n", StackSize(&st));printf("%d\n", StackTop(&st));StackPop(&st);printf("%d\n", StackSize(&st));printf("%d\n", StackTop(&st));StackPop(&st);
}int main(void)
{StackTest1();return 0;
}printf("%d\n", StackTop(&st));StackPop(&st);printf("%d\n", StackSize(&st));printf("%d\n", StackTop(&st));StackPop(&st);printf("%d\n", StackSize(&st));printf("%d\n", StackTop(&st));StackPop(&st);printf("%d\n", StackSize(&st));printf("%d\n", StackTop(&st));StackPop(&st);
}int main(void)
{StackTest1();return 0;
}
相关文章:

数据结构:线性表(栈的实现)
文章目录 1. 栈(Stack)1.1 栈的概念1.2 栈的结构链表栈数组栈 2. 栈的定义3. 栈的实现3.1 初始化栈 (StackInit)3.2 入栈 (StackPush)3.3 出栈 (StackPop)3.4 检测栈是否为空 (StackEmpty)3.5 获取栈顶元素 (StackTop)3.6 获取栈中有效元素个数 (StackSize)3.7 销毁栈 (StackDe…...

python如何将一个dataframe快速写入clickhouse
目录 前言思路与核心代码优缺点分析 前言 dataframe是用python做数据分析最场景的数据结构了,如何将dataframe数据快速写入到clickhouse数据库呢?这里介绍几种方法,各有优劣势,可以结合自己的使用场景挑用。 思路与核心代码 假…...

Tiny Player Mac:小而美,音乐播放的极致体验
对于追求音质和操作简便的Mac用户来说,Tiny Player Mac是一款不可多得的音乐播放器。它以简洁的界面、强大的功能和优异的性能,吸引了无数用户的目光。接下来,让我们一起了解这款小而美的音乐播放器。 Tiny Player Mac支持多种音频格式&#…...

2022年12月 C/C++(五级)真题解析#中国电子学会#全国青少年软件编程等级考试
C/C++编程(1~8级)全部真题・点这里 第1题:漫漫回国路 2020年5月,国际航班机票难求。一位在美国华盛顿的中国留学生,因为一些原因必须在本周内回到北京。现在已知各个机场之间的航班情况,求问他回不回得来(不考虑转机次数和机票价格)。 时间限制:1000 内存限制:65536 …...

C语言学习:7、break与continue的用法
前面讲到的循环体,貌似能解决生活中的很多问题,毕竟生活中很多事情是在重复的。但有时候也会有些小插曲,比如你在日复一日的上班,但某一天又特殊的事情你失业了,不就没班上了吗,那就得跳出那个上班的循环了…...

Ubuntu中安装clion并把clion添加到桌面快捷方式
Clion的安装: CLion是由大名鼎鼎的JetBrains公司出品的一款面向C和C的集成开发工具。下载地址。 下载后解压出来,然后进入到解压后的文件夹里面,执行 ./clion.sh 便可以运行软件: cd bin/ ./clion.sh 激活使用的话&…...

如何利用python来提取SQL语句中的表名称
1.介绍 在某些场景下,我们可能需要从一个复杂的SQL语句中提取对应的表名称,在这样的场景下,我们如果在python中处理的话,就需要用到SQLparse这个库。 SQLparse 是一个用于解析 SQL 查询语句的 Python 库。它可以将复杂的 SQL 查询…...

linux通用时钟框架(CCF)
目录 前言CCF 介绍提供者和消费者的概念CCF 框架组成关系CCF 程序关键结构体 CCF 重要组成注册时钟未使用设备树的时钟注册操作使用设备树的时钟注册操作 从使用的角度看CCF 前言 linux 内核版本 v4.19 嵌入式平台rv1109 , 文中代码出处。 CCF 介绍 提供者和消费者的概念 C…...

基于AERMOD模型在大气环境影响评价中的实践技术应用
随着我国经济快速发展,我国面临着日益严重的大气污染问题。近年来,严重的大气污染问题已经明显影响国计民生,引起政府、学界和人们越来越多的关注。大气污染是工农业生产、生活、交通、城市化等方面人为活动的综合结果,同时气象因…...

企业内训课程、在线教育平台付费课程加密防下载的10种方式
企业内训课程、在线教育平台付费课程加密防下载的10种方式: 实例演示:课程视频-第1课状语从句,VRM演示应用 企业内训课程、在线教育平台付费课程,他们的这种视频课程的加密是如何做的?整理了10种思路,供大家参考&…...

公关世界杂志公关世界杂志社公关世界编辑部2023年第14期目录
封面印象 画里有大美 笔下有乾坤——品读吴建潮的绘画艺术和诗文创作 赵铁信; 4-9 专题报道 “安济欣看千年济,李春赢得万口春”——赵州桥诗词楹联文化鉴赏暨沈鹏书法艺术研讨会举行 刘占行; 10-14 中国书协第二三届理事、河北省书协原副主席兼秘书长、…...

Linux常用(实用)命令大全
pwd 显示当前工作路径 shutdown 关闭系统 /halt 关闭系统 shutdown -r now 重启 /reboot 重启 systemctl stop firewalld 关闭防火墙 ip addr 查看ip地址. 1、cd命令:用于切换当前目录(可以是绝对路径,也可以是相对路径)如&#x…...

2023-09-07力扣每日一题
链接: [2594. 修车的最少时间](https://leetcode.cn/problems/form-smallest-number-from-two-digit-arrays/) 题意: 一个能力R的人R*N*N分钟修N辆车,求最快多久修完(多人多车) 解: 二分很好想&#x…...

从C语言到C++_39(C++笔试面试题)next_permutation刷力扣
这篇就一直更新一些C的选择题和编程题了。 目录 笔试题1 答案及解析1 笔试题2 答案及解析2 力扣编程题 88. 合并两个有序数组 解析代码 349. 两个数组的交集 解析代码 60. 排列序列 解析代码 46. 全排列 解析代码 本篇完。 笔试题1 1. 以下哪种STL容器中的对象…...

适用于Linux的Windows子系统(系统安装步骤)
目录 前言 一、WSL2安装 1.Microsoft参考文档(推荐选择旧版 WSL 的手动安装步骤) 2.开启子系统 二、Ubuntu安装 1.在Microsoft Store中获取ubuntu 2.运行ubuntu配置管理信息 3.ubuntu换源 三、WSL 与 Ubuntu的一些基础使用命令 四、Windows Terminal终端…...

HarmonyOS/OpenHarmony(Stage模型)应用开发组合手势(二)并行识别
并行识别组合手势对应的GestureMode为Parallel。并行识别组合手势中注册的手势将同时进行识别,直到所有手势识别结束。并行识别手势组合中的手势进行识别时互不影响。 以在一个Column组件上绑定点击手势和双击手势组成的并行识别手势为例,由于单击手势和…...

如何使用GPT引领前沿与应用突破之GPT4科研实践技术与AI绘图
GPT对于每个科研人员已经成为不可或缺的辅助工具,不同的研究领域和项目具有不同的需求。例如在科研编程、绘图领域: 1、编程建议和示例代码: 无论你使用的编程语言是Python、R、MATLAB还是其他语言,都可以为你提供相关的代码示例。 2、数据可…...

Blender中的高级边缘控制和纹理映射
推荐:使用 NSDT场景编辑器 快速搭建3D应用场景 步骤 1 首先,您需要创建一组无阴影材质,每种材质具有不同的颜色,确保您有足够的材质来覆盖模型,而不会有相同的颜色相互重叠。然后,切换到“着色”ÿ…...

从0开始学go第四天
模板继承 继承根模板,重新定义“块模板” 【Go Web开发系列教程】07-Go模板继承_哔哩哔哩_bilibili 解析模板时,base模板要在前 渲染模板时: 要用ExecuteTemplate,而不是Excute 模板补充:Go语言标准库之http/templ…...

【飞书ChatGPT机器人】飞书接入ChatGPT,打造智能问答助手
文章目录 前言环境列表1.飞书设置2.克隆feishu-chatgpt项目3.配置config.yaml文件4.运行feishu-chatgpt项目5.安装cpolar内网穿透6.固定公网地址7.机器人权限配置8.创建版本9.创建测试企业10. 机器人测试 前言 在飞书中创建chatGPT机器人并且对话,在下面操作步骤中…...

vue3集成jsoneditor
一、背景 之前在做录制回放平台的时候,需要前端展示子调用信息,子调用是一个请求列表数组结构,jsoneditor对数组的默认展示结构是[0].[1].[2]..的方式,为了达到如下的效果,必须用到 onNodeName的钩子函数,…...

自然语言处理 中文停用词词典
我整合了4个常用的中文停用词词典(https://gitcode.net/mirrors/goto456/stopwords/-/tree/master),剔除了其中的非中文词汇,得到停用词词典如下,可直接取用。 看见 并不是 有著 岂非 毫无保留地 这样 么 哎呀 互相 通…...

CocosCreator3.8研究笔记(十)CocosCreator 图像资源的理解
一、图像资源导入 Cocos Creator 可使用图像文件格式,支持 JPG、PNG、BMP、TGA、HDR、WEBBP、PSD、TIFF 等。 将图像资源直接拖拽到 资源管理器 即可将其导入 二、图像资源的类型 在 属性检查器 面板中便可根据需要设置图像资源的使用类型:raw 、 textu…...

计算机使用中常用截图与标注方法
一、截图常用方法 1.windows自带快捷键 Print Screen SysPq 截取全屏,可以粘到word文档中,可以粘贴到"画图"程序中,命名一个文件名,另存为图片,或.jpg后缀,或.png后缀 alt Print S…...

Elasticsearch,Logstash和Kibana安装部署(ELK Stack)
前言 当今数字化时代,信息的快速增长使得各类组织和企业面临着海量数据的处理和分析挑战。在这样的背景下,ELK Stack(Elasticsearch、Logstash 和 Kibana)作为一套强大的开源工具组合,成为了解决数据管理、搜索和可视…...

MATLAB中movmean函数用法
目录 语法 说明 示例 向量的中心移动平均值 向量的尾部移动平均值 矩阵的移动平均值 包含缺失值的向量的移动平均值 基于样本点计算移动平均值 仅返回满窗口平均值 movmean函数的功能是对数据进行移动求平均值。 语法 M movmean(A,k) M movmean(A,[kb kf]) M mov…...

IIS短文件名泄露漏洞复现
IIS短文件名泄露漏洞复现 前言一、漏洞描述二、漏洞原理1.什么是短文件2.短文件特征 三、漏洞验证三、漏洞防御总结 前言 IIS短文件名泄露漏洞比较老了,而且只适合于windowsiisasp的网络结构,所有如下的复现步骤看下就行了,关键是要弄懂原理…...

万字解读 Android 车机核心 :CarService 的构成和链路~
前言 关于 Android 车机,之前分析过方控上自定义按键的输入机制和中控上旋钮输入的原理,但都局限于 Car Service 内 Input 相关模块。 一文了解 Android 车机如何处理中控的旋钮输入从实体按键看 Android 车载的自定义事件机制 本文将结合 Android 系…...

C#使用Panel
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System...

Jabbi的Rust学习日记(一)
Rust环境安装 Windows:Install Rust - Rust Programming Language (rust-lang.org) 访问网页,下载64bit | 32bit 版本 下载完成后打开,直接enter即可 Linux:输入指令 curl https://sh.rustup.rs-sSf | sh 我会报错,好像是链接不到这个网址&a…...