数据结构-栈详解(大概)
栈
- I 栈的概念
- I.I 栈
- I.II 压栈
- I.III 出栈
- II.栈的实现
- II.I图解
- II.II代码的实现
- II.II.I 大体框架
- II.II.II 栈的初始化
- II.II.III 入栈
- II.II.IV 栈的销毁
- II.II.V判断栈是否为空
- II.II.VI出栈
- II.II.VII获取栈顶元素
- II.II.VIII获取栈中有效元素个数
- III 全部代码
- IV 总结
I 栈的概念
I.I 栈
一种特殊的线性表,其只允许在固定的一段进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。栈中的元素遵守后进先出(先进后出也可以)LIFO(Last in First Out)的原则。
I.II 压栈
栈的插入操作叫做进栈/压栈/入栈,入数据再栈顶。
I.III 出栈
栈的说着拿出操作叫做出栈。出数据也在栈顶。
II.栈的实现
II.I图解
栈的实现一般可以使用数组或者链表实现,相对而言数组的结构实现更优一些。因为数组在尾上插入数据的代价比较小。数组的实现我们可以画个图理解理解,如图所示:
链表指针稍微复杂了些。
进栈出栈的示意图为:
II.II代码的实现
下面我们就用数组的形式来实现栈
II.II.I 大体框架
当我们对于链表的学习已经完成后,我们感受到数组的书写相对简单一些,和顺序表的书写一样,我们先创建三个test.c,Stack.c,Stack.h的文件。再头文件中创建结构体,代码如下:
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>typedef int STDataType;
typedef struct Stack
{STDataType* a;int capacity;int top;
}ST;
接着书写我们要实现的接口函数:
void StackInit(ST* ps);
void StackPush(ST* ps, STDataType x);
void StackDestroy(ST* ps);
void StackPop(ST* ps);
STDataType StackTop(ST* ps);
int StackSize(ST* ps);// size指向栈顶的下一个
bool StackEmpty(ST* ps); //判断栈是否为空
注意:我们在使用boll这个函数的时候需要引入一个头文件stdbool.h。这样才能正常使用。
II.II.II 栈的初始化
代码如下:
void StackInit(ST* ps)
{assert(ps);ps->a = NULL;ps->capacity = 0;ps->top = 0;
}
简洁明了,一目了然。先断言,后变空,最后两个指向0.(顺口溜)然后我们就嘎嘎写完了。
在这里ps->top可以有两种写法。一种是上面代码将其变为0,另外一种就是将其变为-1。
II.II.III 入栈
和上上期我们说的顺序表一样,断言以后。我们首先考虑的是空间是否足够满不满的问题。满了,咱就给它扩容。一顿操作之后。我们通过指针指向了新的空间,最后实现入栈的操作,代码如下:
void StackPush(ST* ps, STDataType x)
{assert(ps);//考虑空间是否已满的情况if (ps->top == ps->capacity){int newCapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;STDataType* tmp = realloc(ps->a, sizeof(STDataType) * newCapacity);if (tmp == NULL){printf("realloc fail\n");exit(-1);}elseps->a = tmp;ps->capacity = newCapacity;}ps->a[ps->top] = x;ps->top++;
}
II.II.IV 栈的销毁
我们直接将ps->a给free掉,剩下照常,代码如下:
void StackDestroy(ST* ps)
{assert(ps);free(ps->a);ps->a = NULL;ps->capacity = ps->top = 0;
}
II.II.V判断栈是否为空
第一种方法,如果我们ps指向的top为真,那我们就返回真值否则返回假。
if (ps -> top == 0){return true;}else{return false;}
事实上我们可以只用一行代码搞定这上面的内容
bool StackEmpty(ST* ps) //判断栈是否为空
{assert(ps);/** if (ps -> top == 0){return true;}else{return false;}*/return ps->top == 0;
}
咱直接return 。
II.II.VI出栈
出栈我们首先要用到上面判断栈是否为空,判断后直接top–就完啦。
void StackPop(ST* ps)
{assert(ps);assert(!StackEmpty(ps));ps->top--;
}
II.II.VII获取栈顶元素
同上判断栈是否为空,判断后我们注意由于我们初始化栈的时候ps->top=0因此我们的top指向的是后面一个元素,获取的时候就要减减来找到。
STDataType StackTop(ST* ps)
{assert(ps);assert(!StackEmpty(ps));return ps->a[ps->top - 1];
}
II.II.VIII获取栈中有效元素个数
int StackSize(ST* ps)
{assert(ps);return ps->top;// size指向栈顶的下一个,
}
额,依然不复杂。写道这里我们所有关于栈的书写就写完了。
III 全部代码
Stack.h
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>typedef int STDataType;
typedef struct Stack
{STDataType* a;int capacity;int top;
}ST;void StackInit(ST* ps);// 初始化栈
void StackPush(ST* ps, STDataType x);// 入栈
void StackDestroy(ST* ps);// 销毁栈
void StackPop(ST* ps);// 出栈
STDataType StackTop(ST* ps);// 获取栈顶元素
int StackSize(ST* ps);// 获取栈中有效元素个数
bool StackEmpty(ST* ps); //判断栈是否为空
Stack.c
#include "Stack.h"void StackInit(ST* ps)
{assert(ps);ps->a = NULL;ps->capacity = 0;ps->top = 0;
}void StackPush(ST* ps, STDataType x)
{assert(ps);//考虑空间是否已满的情况if (ps->top == ps->capacity){int newCapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;STDataType* tmp = realloc(ps->a, sizeof(STDataType) * newCapacity);if (tmp == NULL){printf("realloc fail\n");exit(-1);}elseps->a = tmp;ps->capacity = newCapacity;}ps->a[ps->top] = x;ps->top++;
}void StackDestroy(ST* ps)
{assert(ps);free(ps->a);ps->a = NULL;ps->capacity = ps->top = 0;
}void StackPop(ST* ps)
{assert(ps);assert(!StackEmpty(ps));ps->top--;
}STDataType StackTop(ST* ps)
{assert(ps);assert(!StackEmpty(ps));return ps->a[ps->top - 1];
}int StackSize(ST* ps)
{assert(ps);return ps->top;// size指向栈顶的下一个,
}bool StackEmpty(ST* ps) //判断栈是否为空
{assert(ps);/** if (ps -> top == 0){return true;}else{return false;}*/return ps->top == 0;
}
test.c
#include "Stack.h"void TestStack1()
{ST st;StackInit(&st);StackPush(&st, 1);StackPush(&st, 2);StackPush(&st, 3);StackPush(&st, 4);StackPop(&st);StackPop(&st);StackPop(&st);StackPop(&st);//printf("%d", StackTop(&st));StackDestroy(&st);
}void TestStack2()
{ST st;StackInit(&st);StackPush(&st, 1);StackPush(&st, 2);StackPush(&st, 3);StackPush(&st, 4);printf("%d ", StackTop(&st));StackPop(&st); // 3 和 4出栈了printf("%d ", StackTop(&st));StackPop(&st); StackPush(&st, 5);StackPush(&st, 6);while (!StackEmpty(&st)) // 我们要先取栈顶的数据{printf("%d ", StackTop(&st));StackPop(&st);}StackDestroy(&st);
}int main()
{TestStack1();TestStack2();return 0;}
运行结果完美的实现了先进后出,后进先出的原则
在main函数中我们已经先将3和4先出栈了,所以他们先打印出来,然后才是6521。
IV 总结
经过开始的顺序表的书写以及链表的学习应用,我们发现栈的书写还是相对容易的。要想学好数据结构还是要多多练习,多刷OJ题,希望我的文章对你能有所帮助,欢迎各位大佬在评论区纠正我的错误。期待的话,请多多给我点赞吧
数据结构-栈详解(大概)相关推荐
- 数据结构-栈详解(类C语言版)
目录 栈的定义 概念 栈的抽象数据类型定义 顺序栈的基本操作 存储方式 顺序栈的表示 顺序栈的初始化 顺序栈判断是否为空 清空顺序栈 销毁顺序栈 顺序栈的入栈 顺序栈的出栈 取顺序栈的栈顶元素 链栈的 ...
- 数据结构-链栈详解(很朴实的那种)
链栈的设计与运行 1.链栈 提起链栈,很容易就想到单链表,不过链栈确实可以看做是受限的单链表,因为只能在链表头部进行操作,所以在链栈中也不再附加头结点,栈顶指针就是链表的头指针. 老话一句,实践一遍, ...
- java数据结构-链表详解
文章目录 1.数据结构-链表详解 1.1单链表 1.1.1单链表节点的尾部添加 1.1.2单链表节点的自动排序添加 1.1.3单链表节点的修改 1.1.4单链表节点的删除 1.2单链表面试题 1.2. ...
- ceph存储原理_赠书 | Linux 开源存储全栈详解——从Ceph到容器存储
// 留言点赞赠书我有书,你有故事么?留言说出你的存储故事留言点赞前两名,免费送此书截止日期12.27号12.30号公布名单 // 内容简介 本书致力于帮助读者形成有关Linux开源存储世界的细致的拓 ...
- openstack架构详解图_英特尔顶级技术专家合力缔造精品:Linux开源网络全栈详解...
日常水开篇 自1991年诞生起,Linux已经走过了接近三十年.Linux早已没有了问世时的稚气,正在各个领域展示自己成熟的魅力. 以Linux为基础,也衍生出了各种开源生态,例如网络和存储.而生态离 ...
- Struts2值栈详解
Struts2值栈详解 基本介绍 ValueStack是Struts2的一个接口,字面意义为值栈,OgnlValueStack是 ValueStack的实现类,客 户端发起一个请求,struts2架构 ...
- Linux开源存储全栈详解
最近和同事一起整了本书<Linux开源存储全栈详解:从Ceph到容器存储>,把Linux开源存储相关的项目做了个梳理,对于想了解或参与存储相关项目开发的人来说,应该会是个不错的参考.这里把 ...
- 【数据结构】共享栈详解 判断共享栈满条件栈顶指针变化详解记忆方法例题
摘要:简单易懂,详细地介绍共享栈概念,指针,判断共享栈栈满条件以及记忆方法等 目录 共享栈概念 栈顶指针&变化详解 栈顶指针种类的记忆方法 判断栈满条件 判断栈满条件的记忆方法 例题 解题思路 ...
- 【数据结构】栈详解——压栈/入栈 | 弹栈/出栈 | 获取栈顶元素
栈 顺序栈 栈的定义 栈(stack)又名堆栈,它是一种运算受限的线性表.限定仅在表尾进行插入和删除操作的线性表.这一端被称为栈顶,相对地,把另一端称为栈底.向一个栈插入新元素又称作进栈.入栈或压栈, ...
最新文章
- solidity 编程练习_学习Solidity编程语言并开始为区块链开发
- 网络推广外包——网络推广外包指出网站优化首先考虑关键词分类
- 【python之路14】发送邮件实例
- 程序员面试金典 - 面试题 17.07. 婴儿名字(并查集)
- AWS还是Firebase?在移动应用后端应该使用哪个?
- 正则表达式中的开头和结尾
- 快递送不上门,谁的锅?
- mybatis学习笔记(五):mybatis 逆向工程
- 龙芯2f灵珑一体机debian6系统重装
- Unity 与 UE4 双引擎版本四叉树的创建与可视化
- 【STC15】串行口1的相关寄存器解读
- HEVC之CU、PU、TU分析
- Overloaded operators
- 1 is not JSON serializable的解决方案
- 关于python教学
- android 接口sign,[原创]小米APP登录接口env、envkey、sign、hash算法
- 中国加油!武汉加油!
- 【JavaWeb学习】—iframe标签(四)
- 飞机行李托运java代码_CSS3 飞机行李托运单(含条形码)
- windows10驱动 x64--- 3环代码加载驱动(二)
热门文章
- fuzzy仿真 MATLAB,基于MATLAB的FUZZY控制器的设计和仿真
- win10系统截图快捷键
- Unity游戏安卓和苹果游戏中植入广告增加收入
- 小米机器人 尘盒配件_小米机器人怎么取出尘盒
- 兔子繁殖 c语言编程,c语言写的兔子繁殖- 斐波那契数列.每次只显示前两个.
- 一个30岁工控人的自白
- 机器学习中的Encoder和Decoder到底是什么
- android然后让list刷新到底部,Android笔记之:App列表之下拉刷新的使用
- python查找元素在列表中位置
- 带通滤波器幅频特性曲线图_滤波器和对讲机技术解析!