数据结构:栈(c语言描述)(代码片段)

知道什么是码怪吗? 知道什么是码怪吗?     2022-12-03     261

关键词:

这一篇文章我们谈谈栈。(以下仅代表个人观点,代码和内容有错请指正)

主要内容:动态栈的创建初始化、数据入栈、数据出栈、获取栈顶元素、清空栈内元素、获取栈内元素个数、检测栈是否为空、栈扩容和断言、栈的几个应用。

我认为栈这种数据结构要说的不是很多,主要就是先进后出这种思想。栈也是一种线性表,既然是线性表那么就有线性表的两种表达形式:顺序栈和链式栈(两者的区别在于存储的数据元素在物理结构上是否是相互紧挨着的)。顺序栈存储元素预先申请连续的存储单元;链式栈有需要才申请,数据元素不紧挨着。我们平时浏览网页返回上一个页面就是一个类似的栈结构,程序代码的执行顺序也是利用了这一种结构来执行。话不多说,我们直接步入正题。

①扩容和断言:

首先对以下代码当中出现的assert()函数和realloc()函数做一个简单的介绍。

断言介绍:字太多了我这里就放图片了,也方便保存图片。不用看完,简单知道用处就行,本篇文章我只用断言放在函数入口对参数进行合法性的检查。

报错时显示情况:assert(0); 这句代码报错情况如下

会显示错误在第几行和文件路径。

realloc()函数介绍:

该函数有两个参数:第一个为原指针的地址,第二个为分配的空间大小。如下面这一句代码举例:

stack->array=(Typement*)realloc(stack->array,sizeof(Typement)*(stack->capacity*2));

realloc()函数可以实现分配内存减小和扩大的功能,我们这里只讨论扩大的情况。

扩大有以下情况:
(1)如果当前内存段后面有足够的空闲空间供我们使用,则直接扩展这段内存空间,realloc()将返回原指针。
(2)如果当前内存段后面的空闲空间不够,那么就使用堆中的第一个能够满足这一要求的内存块,将目前的数据复制到新的位置,并将原来的数据块释放掉,返回新的内存块位置。
(3)如果申请失败,将返回NULL,此时,原来的指针仍然有效。

 

②结构体及宏定义如何定义:

写栈的方式有很多种,我这里列举几个比较经典的方式。以下所有功能均用第一种方式的代码实现。

第一种方式(顺序栈):结构体当中定义的是一个int类型的指针方便后期扩容,这种方法实质上还是利用了数组实现栈,只不过可以利用指针动态扩容。

#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
typedef int Typement;//宏定义实现简单的多态 
typedef struct Stack
	
	Typement  *array;//这里相当于定义了一个int类型的数组  
	int top;//顶部元素下标 
	int bottom;//底部元素下标
	int capacity;//表示总的栈节点 

SK; 

第二种方式(链式栈):这一种方式将栈内节点和栈的信息分开用两个结构体存放。

#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
typedef int Typement;//宏定义实现简单的多态
typedef struct Node//栈内节点
    Typement Element;
    struct Node *next;
ND;

typedef struct Stack//栈的结构体
    ND top;        
    ND bottom;
SK;

第三种方式(顺序栈):和第一种方式十分相似,只不过创建的是一个静态栈。

#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#define MAX 100;
typedef int Typement;//宏定义实现简单的多态 
typedef struct Stack
	
	Typement  stack[MAX];//静态栈定义的一个数组  
	int top;//顶部元素下标 
	int bottom;//底部元素下标
	int capacity;//表示总的栈节点 

SK; 

③栈的初始化:

初始化一个栈,即将指向顶部元素的top赋值为0,指向底部元素的bottom也赋值为0,表示栈内总节点的capacity赋值为1。值得我们注意的是,栈的top实际上指向的是栈顶元素的下一个元素(即即将入栈的元素存放的位置)。初始化的时候栈为空,不包含一个元素(只有一个可供存放的节点)。

void InitStack(SK *stack)//初始化栈 
	
	assert(stack);//断言检测地址是否合法 
	
	stack->array=(Typement*)malloc(sizeof(Typement)); //给指针分配内存 
	stack->top=0;//初始化时顶部为下标为0的节点 
	stack->bottom=0;//底部也为下标为0的节点 
	stack->capacity=1;//初始化时可以用的栈节点只有1个 
	
 

④数据入栈:

数据入栈我们要注意判断栈内是否还有可用的空间,如果没有空间可以使用我们需要对栈进行扩容,然后将数据放入栈内,top的值加1指向下一个即将存放数据的节点下标。

void PushStack(SK *stack,Typement number)//数据入栈 
	
	assert(stack);//断言检测地址是否合法 
	
	if( stack->top >= stack->capacity )/*如果指向顶部游标大于等于了总的栈节点,就表示栈满了,需要扩容 */	

		stack->array=(Typement*)realloc(stack->array,sizeof(Typement)*(stack->capacity*2)); //对栈进行扩容 

		/*扩容这点还隐藏了一个细节,如果当前指针后面的空闲内存足够多,就依旧是原来的地址 
		如果不满足会分配一个新的地址,所以需要再次检验地址是否合法*/ 

		assert(stack->array); 
		stack->capacity=stack->capacity*2;//扩大总栈节点个数 
	
	
	stack->array[stack->top++]=number; //数据入栈 
 

⑤数据出栈:

数据出栈我们要注意判断栈是否为空。

void PopStack(SK *stack)//数据出栈 
	
	assert(stack->array);
	if(stack->top<0)//如果栈的顶部元素下标小于0,栈为空,没有节点可以出栈。 
		return; 
	
	
	/*顶部节点指向顶部下方一个节点,最上面的就出栈了,但是其数据还是存在
	只不过是指向节点的游标改变了。*/ 

	stack->top--; 

⑥获取栈顶元素数据:

int GetTopStack(SK *stack)//获取栈顶元素 
	assert(stack->array);
	
	if(stack->top<0)//如果栈的顶部元素下标小于0,栈为空没有元素可以取。 
		return NULL;
	
	
	return stack->array[stack->top-1];//在这个栈当中,top指向的是栈顶节点的下一个节点,即下一个准备入栈元素的节点位置。 
 

⑦清空栈:

void EmptyStack(SK *stack)//清空栈里所有元素
	
	assert(stack->array); 
	free(stack->array);//简单的清空数据只需要把top等于bottom即可,释放内存更好。 
	InitStack(stack);//清空栈里元素所有元素相当于初始化栈,我们先释放之前栈的内存,再初始化。 

⑧获取栈内总节点个数和检测栈是否为空:

int GetSizeStack(SK *stack)//获取栈内元素个数 
	assert(stack->array);
	return stack->top; 
 

int IsEmptyStack(SK *stack)//检测栈是否为空 
	assert(stack);
	return stack->top==0? 1: 0;//三元表达式,为空返回1,不为空返回0 

⑨测试:

int main()
	//测试
	SK *TextStack=(SK*)malloc(sizeof(SK));
	//初始化 
	InitStack(TextStack); 
	printf("初始化后栈是否为空(1代表为空,0代表不为空):%d\\n",IsEmptyStack(TextStack)); 
	//数据入栈
	PushStack(TextStack,1); 
	PushStack(TextStack,2);
	PushStack(TextStack,3);
	printf("数据入栈之后栈内节点数量:%d\\n",GetSizeStack(TextStack)); 
	//数据出栈获取栈顶元素显示并输出栈内总元素个数 
	printf("数据入栈之后栈是否为空(1代表为空,0代表不为空):%d\\n",IsEmptyStack(TextStack)); 
	
	printf("当前栈顶元素为:%d   ",GetTopStack(TextStack));
	PopStack(TextStack);
	printf("出栈之后剩余元素个数:%d\\n",GetSizeStack(TextStack));
	
	printf("当前栈顶元素为:%d   ",GetTopStack(TextStack));
	PopStack(TextStack);
	printf("出栈之后剩余元素个数:%d\\n",GetSizeStack(TextStack));
	
	printf("当前栈顶元素为:%d   ",GetTopStack(TextStack));
	PopStack(TextStack);
	printf("出栈之后剩余元素个数:%d\\n",GetSizeStack(TextStack));
	
	//判断栈是否为空 
	printf("全部出栈之后栈是否为空(1代表为空,0代表不为空):%d\\n",IsEmptyStack(TextStack)); 
	
	//再次入栈
	PushStack(TextStack,98); 
	PushStack(TextStack,99);
	PushStack(TextStack,100);
	//测试清空栈 
	EmptyStack(TextStack); 
	printf("再次入栈清空栈之后栈是否为空(1代表为空,0代表不为空):%d\\n",IsEmptyStack(TextStack)); 
	
	return 0;

测试结果显示:

⑩栈的应用:

(1)用栈实现逆波兰表达式

(2)进制转换

(3)括号匹配

(4)迷宫路径搜寻

还有很多应用就不一一列举了。

数据结构与算法栈与队列c语言版(代码片段)

目录3.1栈和队列的定义和特点3.2栈、队列与一般线性表的区别3.3栈的表示和操作的实现顺序栈与顺序表=================顺序栈的表示顺序栈初始化判断顺序栈是否为空求顺序栈的... 查看详情

数据结构c语言版——栈的实现(代码片段)

文章目录栈1.基本概念2.栈的实现1)初始化栈2)栈的扩容3)判断栈是否为空4)入栈5)出栈6)获取栈顶元素7)获取栈中元素个数8)销毁栈栈1.基本概念栈(Stack):一种特殊的线性表,其只限定于在表尾进行插入或者删除操作。进行数... 查看详情

c/c++语言数据结构快速入门(代码解析+内容解析)栈(代码片段)

一、栈(Stack)1、栈的基本概念注:数据结构三要素――逻辑结构、数据的运算、存储结构(物理结构)存储结构不同运算的实现方式不同(1)栈的定义线性表是具有相同数据类型的n(n>0)个数据元素的有... 查看详情

c/c++语言数据结构快速入门(代码解析+内容解析)栈(代码片段)

一、栈(Stack)1、栈的基本概念注:数据结构三要素――逻辑结构、数据的运算、存储结构(物理结构)存储结构不同运算的实现方式不同(1)栈的定义线性表是具有相同数据类型的n(n>0)个数据元素的有... 查看详情

数据结构(c语言版)严蔚敏->顺序栈的定义利用顺序栈解决有效的括号(代码片段)

头文件SqStack.h#ifndefSQSTACK_H_INCLUDED#defineSQSTACK_H_INCLUDED//顺序栈#defineMax_Stack_Size50typedefcharElemType;typedefstructElemTypedata[Max_Stack_Size];//存放栈中的元素inttop;//栈顶指针SqStack;voidInitSqStack(Sq 查看详情

栈和队列c语言实现附加力扣题(代码片段)

目录栈的概念栈的实现栈的声明栈的实现压栈出栈队列队列声明队列实现销毁队尾入队队头出队判空获取队头数据获取队尾数据求元素个数力扣题20.有效的括号225.用队列实现栈232.用栈实现队列设计循环队列栈的概念1.栈1.1栈的... 查看详情

栈的实现(c语言)---数据结构(代码片段)

文章目录1.栈的简介1.1栈的特点1.2栈的相关概念2.栈的顺序存储2.1初始化栈2.1入栈2.3出栈2.4获取栈顶元素2.5获取栈的大小2.6判断栈是否为空2.7栈的销毁2.8测试部分3.栈的链式存储3.1链式存储的简单介绍3.2链式存储中入栈和出栈的简... 查看详情

数据结构-栈(代码片段)

目录前言一、栈的概念与结构二、C语言-栈的基本操作与实现1.栈的创建2.栈的初始化3.入栈4.出栈5.获取栈顶元素6.获取栈中有效元素个数7.检测栈是否为空8.销毁栈三、栈的经典使用1.问题叙述2.解题方法3.代码实现前言本文均基于... 查看详情

新手向c语言实现特殊的数据结构——栈(代码片段)

目录一、易错接口详解1.1栈的初始化1.2栈的销毁1.3入栈1.4出栈二、简单接口的实现2.1有效数据个数2.2返回栈顶数据三、头文件的引用,结构体和函数的定义一、易错接口详解1.1栈的初始化涉及到结构体的定义,请先跳转... 查看详情

数据结构:栈-c语言实现(有图详讲带注解,适合入门学习)(代码片段)

...码2.5Stack.c文件代码2.6main.c文件代码三.结语之前的文章1.数据结构:顺序表-C语言实现2.数据结构:链表-C语言实现栈一.栈的概念及结构栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。**进... 查看详情

数据结构(c语言版)严蔚敏->顺序栈的定义利用顺序栈解决有效的括号(代码片段)

头文件SqStack.h#ifndefSQSTACK_H_INCLUDED#defineSQSTACK_H_INCLUDED//顺序栈#defineMax_Stack_Size50typedefcharElemType;typedefstructElemTypedata[Max_Stack_Size];//存放栈中的元素inttop;//栈顶指针SqStack;voidInitSqStack(SqStack&S);//初始化一个空栈SboolSqStackEmpty(SqStackS);//... 查看详情

五种编程语言解释数据结构与算法—链式栈(代码片段)

目录五种编程语言解释数据结构与算法—链式栈1、栈的链式存储结构介绍1.1、逻辑结构示意图2、栈的应用2.1、括号匹配问题2.2、表达式求值问题3、栈和递归的关系4、C语言实现链式栈4.1、LinkStack.h文件的内容4.2、LinkStack.c文件中... 查看详情

⭐算法入门⭐《栈-单调栈》简单01——leetcode155.最小栈(代码片段)

...?先看简单题!🧡《C语言入门100例》🧡数据结构难?不存在的!🌳《画解 查看详情

java9新特性-stackwalking-当前线程栈信息(代码片段)

...每个线程启动时都有一个私有的JVM线程栈会创建。栈这种数据结构就是我们常谈到的数据结构中的栈-后进先出的数据结构。栈保存了一系列栈帧,每当一个方法执行时都会伴随着新的栈帧的创建并进栈顶,方法执行完也... 查看详情

数据结构(c语言版)严蔚敏(线性表队列栈串树图等数据结构参考代码,持续更新中。。。)(代码片段)

前言:本篇文章主要提供相关数据结构的实现的参考代码1.线性表线性表的顺序存储(顺序表)和链式存储(链表)1.1顺序表头文件:SqList.h#ifndefSQLIST_H_INCLUDED#defineSQLIST_H_INCLUDED#defineLIST_INIT_SIZE100//顺序表初... 查看详情

数据结构(c语言版)严蔚敏(线性表队列栈数组树图等数据结构参考代码,持续更新中。。。)(代码片段)

前言:本篇文章主要提供相关数据结构的实现的参考代码1.线性表线性表的顺序存储(顺序表)和链式存储(链表)1.1顺序表头文件:SqList.h#ifndefSQLIST_H_INCLUDED#defineSQLIST_H_INCLUDED#defineLIST_INIT_SIZE100//顺序表初... 查看详情

c/c++语言数据结构快速入门(代码解析+内容解析)栈的应用(代码片段)

一、括号匹配1、算法演示#include<stdio.h>#defineMaxSize10 //定义栈中元素的最大值typedefstruct chardata[MaxSize];//静态数组当中存放栈中元素 inttop; //栈顶指针SqStack;boolbracketCheck(charstr[],intlength) SqStackS; InitStack(S); 查看详情

c语言—栈(代码片段)

栈的操作:进栈和出栈1#include"stdafx.h"2#include"stack.h"3#definemaxsize204typedefintElemtype;56/*顺序存储—数组形式*/7structstack89intdata[maxsize];10inttop;11;1213voidinit(structstack*ps)1415ps->top=-1;16 查看详情