栈和队列是两种重要的线性结构,从数据结构的角度看,栈和队列也是线性表,其特殊性在于栈和队列的基本操作是线性表的子集。他们是操作受限的线性表,因此,可称为限定性的数据结构。但从数据类型角度看,他们是和线性表大不相同的两类重要的的抽象数据类型。

文章目录

C语言中的栈

栈的定义

C语言中栈的基本操作

栈的初始化

判断是否为空栈

判断是否为满栈

入栈

出栈

C语言实现栈的具体代码

C++中的栈

C++中栈的基本操作

初始化

判断是否为空栈

入栈

出栈

返回栈顶元素

返回栈中元素数目

C语言中的栈

栈的定义

栈(stack)是限定仅在表尾进行插入或者删除的线性表。对于栈来说,表尾端称为栈顶(top),表头端称为栈低(bottom)。不含元素的空表称为空栈。因为栈限定在表尾进行插入或者删除,所以栈又被称为后进先出的线性表(简称LIFO:Last in, First out.结构)。

C语言中栈的基本操作

栈的基本操作主要有:栈的初始化、判空、判满、取栈顶元素、在栈顶进行插入和删除。在栈顶插入元素称为入栈,在栈顶删除元素称为出栈。

栈的初始化

栈和线性表类似,也有两种存储表示方法顺序栈和链栈,链栈的操作是线性表操作的特例,操作比较容易实现。顺序栈即栈的顺序存储结构是利用一组地址连续的存储单元依次存放自栈底到栈顶的数据元素,同时附设指针top指示栈顶元素在顺序栈中的位置,top = 0表示空栈。由于栈在使用的过程中所需要的大小难以估计,所以通常是先为栈分配一个基本容量,然后再使用的过程中,当栈的空间不够使用的时候再继续追加存储空间。我们以下述类型说明作为顺序栈的定义:

typedef struct{

SDataType *base; //栈底指针

SDataType *top; //栈顶指针

int StackSize; //当前已经分配的存储空间,以元素为单位

}SqStack;

栈的初始化操作为:按照设定的初始分配量进行第一次存储分配,这里使用==malloc()==函数来分配存储空间。malloc()函数的详细说明请看:malloc详细说明。base作为栈底指针,它始终指向栈底,所以s.top = s.base可以作为栈空的标记。top为栈顶指针,top的初值指向栈底。每当插入一个元素时top加1,弹出一个元素时top减1,因此,非空栈中的栈顶指针始终在栈顶元素的下一个位置上。

//初始化顺序栈,构造一个空栈

Status InitStack(SqStack &S){

//分配存储空间

S.base = (SDataType *)malloc(STACK_INIT_SIZE*sizeof(SDataType));

if(!S.base){

//如果分配失败,则返回error

return OVERFLOW;

}

//S.top 始终指向栈顶元素的下一个位置

S.top = S.base; //初始状态下为空栈

S.StackSize = STACK_INIT_SIZE; //当前已经分配的存储容量为100个

return OK;

}

判断是否为空栈

当我们弹出栈顶元素时,往往需要判断一下栈是否为空来防止发生下溢。上面我们说到==base作为栈底指针,它始终指向栈底,所以s.top = s.base可以作为栈空的标记。==所以我们可以这样判断栈是否为空:

//判断是否为空栈

void judgeNull(SqStack &s){

if(s.top == s.base){

printf("此栈为空栈!\n");

}else{

printf("此栈不为空栈!\n");

}

}

判断是否为满栈

当我们使一个元素入栈的之前,我们往往需要判断一下栈是否为满栈,防止发生上溢的情况。因为我们定义了一个StackSize来表示当前已经分配的存储空间,所以我们可以用s.top - s.base 来算出当前已经使用的栈空间。所以当s.top - s.base == s.StackSize时表示已经满栈:

//判断是否为满栈

void judgeFull(SqStack &s){

if(s.top-s.base == s.StackSize){

printf("栈满!\n");

}else{

printf("栈未满!\n");

}

}

入栈

入栈时我们首先要判断栈是否为满栈,如果为满栈我们要首先追加存储空间,然后才能将元素入栈。realloc()函数详解请看realloc详解

//入栈

Status Push(SqStack &s,SDataType e){

SDataType *p;

//首先判断栈是不是满的(上溢)

if(s.top-s.base == s.StackSize){

//追加空间

p = (SDataType *)realloc(s.base,(STACK_INIT_SIZE+STACKINCREMENT)*sizeof(SDataType));

if(!p){

//如果没有找到符合条件的存储空间,则返回error

return OVERFLOW;

}

//成功找到则使s.base指向p

s.base = p;

s.top = s.base + s.StackSize;

s.StackSize += STACKINCREMENT;

}

//先插入元素,然后将栈顶指针加 1

*(s.top) = e;

s.top++;

return OK;

}

出栈

出栈时我们首先要判断栈是否为空栈。如果栈已经空了,则返回error。

//出栈

Status Pop(SqStack &s,SDataType &e){

//判断是否会发生下溢

if(s.top != s.base){

s.top--; //先将栈顶指针减 1

e = *(s.top);

}else{

return 0;

}

return e;

}

C语言实现栈的具体代码

#include

#include

#define STACK_INIT_SIZE 100//栈的初始容量

#define STACKINCREMENT 10//容量增量

#define OK 1

#define OVERFLOW -2

typedef int SDataType;

typedef int Status;

typedef struct{

SDataType *base; //栈底指针

SDataType *top; //栈顶指针

int StackSize; //当前已经分配的存储空间,以元素为单位

}SqStack;

//初始化顺序栈,构造一个空栈

Status InitStack(SqStack &S){

//分配存储空间

S.base = (SDataType *)malloc(STACK_INIT_SIZE*sizeof(SDataType));

if(!S.base){

//如果分配失败,则返回error

return OVERFLOW;

}

//S.top 始终指向栈顶元素的下一个位置

S.top = S.base; //初始状态下为空栈

S.StackSize = STACK_INIT_SIZE; //当前已经分配的存储容量为100个

return OK;

}

//入栈

Status Push(SqStack &s,SDataType e){

SDataType *p;

//首先判断栈是不是满的(上溢)

if(s.top-s.base == s.StackSize){

//追加空间

p = (SDataType *)realloc(s.base,(STACK_INIT_SIZE+STACKINCREMENT)*sizeof(SDataType));

if(!p){

//如果没有找到符合条件的存储空间,则返回error

return OVERFLOW;

}

//成功找到则使s.base指向p

s.base = p; //系统会将原来的内容复制过来

s.top = s.base + s.StackSize;

s.StackSize += STACKINCREMENT;

}

//先插入元素,然后使栈顶指针加 1

*(s.top) = e;

s.top++;

return OK;

}

//出栈

Status Pop(SqStack &s,SDataType &e){

//判断是否会发生下溢

if(s.top != s.base){

s.top--; //先将栈顶指针减 1

e = *(s.top);

}else{

return 0;

}

return e;

}

//判断是否为空栈

void judgeNull(SqStack &s){

if(s.top == s.base){

printf("此栈为空栈!\n");

}else{

printf("此栈不为空栈!\n");

}

}

//判断是否为满栈

void judgeFull(SqStack &s){

if(s.top-s.base == s.StackSize){

printf("栈满!\n");

}else{

printf("栈未满!\n");

}

}

int main(){

SqStack s;

SDataType element;

InitStack(s); //初始化栈

//将1-5入栈

for(int i=1;i<=10;i++){

Push(s,i);

}

judgeNull(s);

judgeFull(s);

printf("出栈:\n");

//只要栈不为空

while(s.top != s.base){

Pop(s,element); //出栈的元素用e接收

printf("%d ",element);

}

printf("\n");

judgeNull(s);

return 0;

}

C++中的栈

C++ 对模板(Template)支持得很好,STL 就是借助模板把常用的数据结构及其算法都实现了一遍,并且做到了数据结构和算法的分离。STL的代码从广义上讲分为三类:algorithm(算法)、container(容器)和iterator(迭代器),几乎所有的代码都采用了模板类和模版函数的方式,这相比于传统的由函数和类组成的库来说提供了更好的代码重用机会。在C++标准中,STL被组织为下面的13个头文件:、、、、、、、、、、、和。其中的就是栈。

C++的STL已经将栈的操作都封装成了函数,我们只需要引进#include头文件即可使用。

C++中栈的基本操作

初始化

我们可以直接使用stacks;来创建一个空的 stack 对象。

判断是否为空栈

使用empty()函数来判断栈是否为空。

入栈

使用push()函数来完成入栈操作。

出栈

使用pop()函数实现出栈

返回栈顶元素

使用top()函数返回栈顶元素

返回栈中元素数目

使用size()函数返回栈中元素的数目。

以上就是C语言和C++中栈的基本用法了,如果你觉得我的文章对你有用请点个赞支持一下吧,如果喜欢我写的文章那么请点个关注再走。

下一篇将继续写数据结构的队列,后续将会再写一些有关栈和队列的具体应用。我是ACfun:一个成长中的程序猿,感谢大家的支持。

c语言 栈结构存放数据类型,数据结构——栈的详解相关推荐

  1. 【C语言】结构体定义 typedef struct 用法详解和用法小结

    结构体定义 typedef struct 用法详解和用法小结 文章目录 结构体定义 typedef struct 用法详解和用法小结 0. 前言 1. 首先:在C中定义一个结构体类型要用typedef ...

  2. DBus glib 各数据类型接收与发送详解—C语言(3)

    DBus glib 各数据类型接收与发送详解-C语言(3) 动机 前置知识 正文 Python 测试服务 使用 C 实现复杂数据类型的传递 DICT_DICT ObjectPath_Dict_Stru ...

  3. 用数据结构c语言写成绩排序,C语言数据结构 快速排序实例详解

    C语言数据结构 快速排序实例详解 一.快速排序简介 快速排序采用分治的思想,第一趟先将一串数字分为两部分,第一部分的数值都比第二部分要小,然后按照这种方法,依次对两边的数据进行排序. 二.代码实现 # ...

  4. C语言结构体中定义函数指针详解

    C语言结构体中定义函数指针详解 结构体指针函数应用场景之一--驱动程序编写 结构体的一些基本用法 形式1:先定义结构体类型,再定义变量 形式2:在定义类型的同时定义变量 形式3:直接定义变量,用无名结 ...

  5. 数据结构与算法详解目录

    数据结构与算法详解是一本以实例和实践为主的图书,主要是经典的数据结构与常见算法案例,来自历年考研.软考等考题,有算法思路和完整的代码,最后提供了C语言调试技术的方法. 后续配套微课视频. 第0章  基 ...

  6. 数据结构--图(Graph)详解(四)

    数据结构–图(Graph)详解(四) 文章目录 数据结构--图(Graph)详解(四) 一.图中几个NB的算法 1.普里姆算法(Prim算法)求最小生成树 2.克鲁斯卡尔算法(Kruskal算法)求最 ...

  7. 数据结构--图(Graph)详解(二)

    数据结构–图(Graph)详解(二) 文章目录 数据结构--图(Graph)详解(二) 一.图的存储结构 1.图的顺序存储法 2.图的邻接表存储法 3.图的十字链表存储法 4.图的邻接多重表存储法 二 ...

  8. 结构体,联合体,枚举详解

    结构体,联合体,枚举详解 目录 结构体 联合体 枚举常量 1.结构体 在C语言中,系统已经提供了一些数据类型,比如float,int,double,char等,但是我们有时会需要更复杂的类型来描述一个 ...

  9. 数据结构--图(Graph)详解(三)

    数据结构–图(Graph)详解(三) 文章目录 数据结构--图(Graph)详解(三) 一.深度优先生成树和广度优先生成树 1.铺垫 2.非连通图的生成森林 3.深度优先生成森林 4.广度优先生成森林 ...

最新文章

  1. 2018 German Collegiate Programming Contest (GCPC 18)
  2. Android的init过程:init.rc解析流程
  3. SAP Spartacus基于travis的持续集成
  4. android 文件公有存储,如何将文件写入Android中的外部公共存储,以便从Windows中看到它们?...
  5. Vue中使用input简易的上传图片
  6. 找到特定ip地址 修改ip_您如何找到网站的IP地址?
  7. 使用ActionTrail Python SDK
  8. iOS学习之UItableView
  9. ROS(kinetic)报错:CMakeFiles/Makefile2:9038: recipe for target ‘XXX‘
  10. ps css html,用ps两分钟做个xhtml+css的网站首页
  11. 网站对战服务器,PVP核心精华:三大服务器对战
  12. Shell脚本参数值包含空格的处理
  13. linux 网络重组 分片 gso lro
  14. python解析库 爬虫_Python-爬虫-解析库(Beautiful Soup)的使用
  15. 【渝粤教育】国家开放大学2018年秋季 0284-21T外国文学 参考试题
  16. 服务器隐藏文件夹怎样打开,局域网文件如何设置隐藏?服务器隐藏文件夹的方法...
  17. 使用selenium实现豆瓣电影信息的自动化搜索
  18. 智慧农业: STM32F103ZE+ESP8266+腾讯云物联网平台+微信小程序设计
  19. 软考高级,考网规还是考项管?
  20. 还没搞懂正则?熬夜到虚脱整理出来的Python的正则表达式总结(Regular Expression)

热门文章

  1. VUE 动态绑定class
  2. js中函数,方法,事件对比区分,什么是方法,什么是函数
  3. 【Python】在Mac系统中安装Pygame
  4. 通过loganalyzer展示数据库中的日志
  5. 开源大数据周刊-第11期
  6. 表格中td限宽溢出以省略号代替
  7. 《深入浅出iPhone/iPad开发(第2版)》——在Xcode中建立你的界面
  8. 【ArrayList】为什么java.util.concurrent 包里没有并发的ArrayList实现?
  9. EIGRP注入默认路由
  10. 停止Password Manager Agent服务导致应用程序启动缓慢