数据结构——栈的详解_晴空๓的博客-程序员秘密_数据结构栈

技术标签: 算法  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,(s.StackSize + 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<stdio.h>
#include<malloc.h>

#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,(s.StackSize + 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-10入栈
	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个头文件:<algorithm >、<deque >、<functional>、<iterator>、<vector>、<list>、<map>、<memory>、<numeric>、<queue>、<set>、<stack>和<utility>。其中的<stack>就是栈。

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

C++中栈的基本操作

初始化

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

判断是否为空栈

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

入栈

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

出栈

使用pop()函数实现出栈
pop()函数详解

返回栈顶元素

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

返回栈中元素数目

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


以上就是C语言和C++中栈的基本用法了,如果你觉得我的文章对你有用请点个赞支持一下吧,如果喜欢我写的文章那么请点个关注再走。
嘿嘿
下一篇将继续写数据结构的队列,后续将会再写一些有关栈和队列的具体应用。我是ACfun:一个成长中的程序猿,感谢大家的支持。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_41575507/article/details/105619109

智能推荐

搜索_torrentkitty_银河落九天之上的博客-程序员秘密

搜索基本概念搜索(search)是各种数据结构中的一种常见运算.搜索是在给定的数据集合中,寻找符合特定条件的数据,用来搜索的这个特定条件称之为键值.按数据集合所含数据量的大小来分,搜索可分内部搜索和外部搜索.当数据量较小,可以直接将它载入内存中进行搜索,称这种搜索为内部搜索.当数据量较大,无法一次将它载入内存进行搜索,需要使用辅助存储器来分批次处理,称这种搜索为外部搜索 搜索表:由同一类型数据所组成的集合.关键字:可唯一标识数据的数据项.搜索:在搜索表查找关键字值与键值相同的数据.成

ad19pcb设置恢复默认_太重要,你想要的电脑BIOS全面解读与设置(下)_weixin_39642687的博客-程序员秘密

设置意外断电后恢复状态通常在电脑意外断电后,需要重新启动电脑,但在 BIOS 中可以对断电恢 复进行设置,一旦电源恢复,电脑将自动启动。下面就在 UEFIBIOS 中设置电 脑的自动断电后重启,具体操作步骤如下。 STEP 1 选择高级选项 1 进入UEFIBIOS设置主界面,单击上面的 “高级”按钮; 2 打开“高级”界面,在“高 级”栏中选择“电源管理设置”选项,如图5-24所示。STEP 2...

【LeetCode力扣题库】14. 最长公共前缀(简单)_最长公共前缀力扣_小胖java攻城狮的博客-程序员秘密

原题目链接:14. 最长公共前缀题目描述:编写一个函数来查找字符串数组中的最长公共前缀。如果不存在公共前缀,返回空字符串""。示例 1:输入:strs = ["flower","flow","flight"]输出:"fl"示例 2:输入:strs = ["dog","racecar","car"]输出:""解释:输入不存在公共前缀。提示:0 &lt;= strs.length &lt;= 2000 &lt;= strs[i].length &lt;= ...

编写高质量iOS与OS X代码的52个有效的方法 之协议与分类_beiyangguangsumiao的博客-程序员秘密

1.通过委托与数据源协议进行对象间通信委托模式:(Delegate patten) ,该模式的主旨是:定义一套接口,某对象若想接受另一个对象的委托,则需遵从此接口,以便成为其”委托对象(delegate)”为了指明可选方法,委托协议经常使用@optional 关键字来标注其大部分或全部的方法;如果是委托对象的可选方法,NSData *data = /*data obtained f

数据库系统_吃青椒的小新的博客-程序员秘密

第一、数据库系统前言1、综合知识和案例分析都有考到,主要是以下八个方面:数据库模式、ER模型、关系代数与元组演算、规范化理论、并发控制、数据库完整性约束、分布式数据库、数据仓库与数据挖掘。第二、数据库三级模式两级映射三级模式:外模式(也称用户模式、子模式),概念模式(数据库表,也叫模式),内模式(索引的建立,修改了数据库的物理结构)。两级映射:外模式-概念模式映射(保证数据的逻辑独立性),概念模式-内模式映射(保证数据的物理独立性)第三、数据库设计过程说明设计过程:需求分析(数据流图,数据

如何解决KEIL报错 error in include chain (cmsis_armcc.h): expected identfieror_丁林夕的博客-程序员秘密

经过一番寻找终于找到了这个令人心烦的解决方法,首先说明这个错误是编译器的错误,也就是它抽风不正常工作了。原因In the most common case, the syntax checker was not able to open an include file, which is referenced by the currently edited source module. In ...

随便推点

在linux下搭建MySQL5.6和MySQL5.7_JustDoDT的博客-程序员秘密

MySQL5.6与MySQL5.7的搭建有一些不一样。请读者仔细阅读笔者搭建的过程,如发现错误,请反馈给我,让我们共同学习和进步,共同在DT这一条道路上越走越远。向每一位读者执意诚挚的敬意。(*).OS环境:Red Hat  Enterprise Linux 7.4 (*).数据库版本:MySQL 5.6.37 和MySQL5.7.19一、MySQL5.6的单实例搭建新建softw...

利用canvas,把多张图合并成一张图片_u013239233的博客-程序员秘密

Html5 Canvas 实现图片合成 |img{ border:solid 1px #ddd;}    function hecheng(){draw(function(){document.getElementById('imgBox').innerHTML='合成图片成功!可以鼠标另存图片查看我是否是一张图片~~!'

php数字运算符号,php运算符号_砚遇书的博客-程序员秘密

php新手入门之PHP常用特殊运算符号php新手入门之PHP常用特殊运算符号,尖锋网站长发布分享。尖锋网常发布一些技术分享资料和文章。欢迎大家提供高质量的旅游生活养生问答。注解符号:// 单行注解多行注解引号的使用' ' 单引号,简单字符串,不经任何处理直接拿过来;" "双引号,php动态处理然后输出,一般用于处理$变...文章技术小胖子2017-11-14942浏览量运算符 - PHP手册笔记原...

vue cli3.x 项目中引入 vux(一):手动配置[email protected]的博客-程序员秘密

最近做的一个项目,是使用vux组件库开发的,使用的时候发现vux在使用的时候需要做一些相应的配置,记录如下:建议 node.js 版本在7.6.0以上。1、引入vux# npm install vux --save2、vux2必须配合vux-loader使用,所以需要引入vux-loader# npm install vux-loader --sava--dev...

CentOS 6.4图文安装教程_weixin_34352449的博客-程序员秘密

1.出现引导界面,选择安装或升级现有系统Install or upgrade anexisting system 安装或升级现有的系统 install system with basicvideo driver 安装过程中采用基本的显卡驱动 Rescue installed system 进入系统修复模式Boot from local drive 退出安装从硬盘启动Mem...

【codevs1079】回家 解题报告_Clove_unique的博客-程序员秘密

【codevs1079】回家  解题报告题目描述 Description现在是晚餐时间,而母牛们在外面分散的牧场中。 农民约翰按响了电铃,所以她们开始向谷仓走去。 你的工作是要指出哪只母牛会最先到达谷仓(在给出的测试数据中,总会有且只有一只最快的母牛)。 在挤奶的时候(晚餐前),每只母牛都在她自己的牧场上,一些牧场上可能没有母牛。 每个牧场由一条条道路和一个或多个牧场连接(