首页 > 其他分享 >深入理解数据结构——栈

深入理解数据结构——栈

时间:2024-04-08 20:58:25浏览次数:22  
标签:top 元素 ST 理解 深入 STDataType 数据结构 void pst

前言:

在学习完数据结构顺序表和链表之后,其实我们就可以做很多事情了,后面的栈和队列,其实就是对前面的顺序表和链表的灵活运用,今天我们就来学习一下栈的原理和应用。

准备工作:本人习惯将文件放在test.c、SeqList.c、SeqList.h三个文件中来实现,其中test.c用来放主函数,SeqList.c用来放调用的函数,SeqList.h用来放头文件和函数声明

目录

什么是队列?

栈的节点结构

栈的基本操作

1、初始化

2、销毁

3、插入元素

4、判断栈顶元素是否为空

5、删除元素

6、返回栈顶元素

7、栈中元素个数

完整的栈实例

总结


什么是队列?

队列中的数据是按照先进后出的顺序的,也就是说先进去的数字后出来

因为栈的这种性质,所以栈我们用顺序表来实现比链表方便很多,顺序表就可以实现尾插尾出,所以我们一般就采用顺序表来实现

栈的节点结构

队列采用的顺序表的结构,所以与顺序表差异不大

typedef int STDataType;
typedef struct stack
{
	STDataType* a;
	int top;         //指向栈元素下一位
	int capacity;
}ST;

栈的结构很简单,定义一个整形指针,一个表示容量和一个表示尾部元素的整形变量即可

栈的基本操作

//初始化
void STInit(ST* pst);
//销毁
void STDestroy(ST* pst);
//插入元素
void STPush(ST* pst, STDataType x);
//删除元素
void STPop(ST* pst);
//判断栈顶元素是否为空
bool STEmpty(ST* pst);
//找栈顶元素
STDataType STTop(ST* pst);
//栈中元素个数
STDataType STSize(ST* pst);

看上面的函数声明部分我们就可以看到我们每一步要实现的内容,接下来,我们就来一步一步进行实现

1、初始化

//初始化
void STInit(ST* pst)
{
	pst->a = NULL;
	pst->capacity = 0;
	pst->top = 0;
}

2、销毁

//销毁
void STDestroy(ST* pst)
{
	assert(pst);
	free(pst->a);
	pst->capacity = pst->top = 0;
}

3、插入元素

插入元素时要先检查空间是否够用,如果不够用要先进行扩容

//插入元素
void STPush(ST* pst, STDataType x)
{
	if (pst->top == pst->capacity)
	{
		int newcapacity = pst->capacity == 0 ? 4 : pst->capacity * 2;
		STDataType* newnode = (STDataType*)realloc(pst->a, sizeof(STDataType) * newcapacity);
		if (newnode == NULL)
		{
			perror("STPush");
			return;
		}
		pst->a = newnode;
		pst->capacity = newcapacity;
	}
	pst->a[pst->top] = x;
	pst->top++;
}

4、判断栈顶元素是否为空

这一步在下面有用到,例如当删除栈顶元素时,如果栈顶元素为空就无法操作,所以需要判断栈顶元素是否为空

//判断栈顶元素是否为空
bool STEmpty(ST* pst)
{
	assert(pst);
	return pst->top == 0;
}

5、删除元素

这里删除元素是删除栈顶元素,因为栈的特性是即出即删

//删除元素
void STPop(ST* pst)
{
	assert(pst);
	assert(!STEmpty(pst));
	pst->top--;
}

6、返回栈顶元素

//找栈顶元素
STDataType STTop(ST* pst)
{
	assert(pst);
	assert(!STEmpty(pst));
	return pst->a[pst->top - 1];
}

7、栈中元素个数

//栈中元素个数
STDataType STSize(ST* pst)
{
	assert(pst);
	return pst->capacity;
}

完整的栈实例

SeqList.h

//实现栈
typedef int STDataType;
typedef struct stack
{
	STDataType* a;
	int top;         //指向栈元素下一位
	int capacity;
}ST;

//初始化
void STInit(ST* pst);
//销毁
void STDestroy(ST* pst);
//插入元素
void STPush(ST* pst, STDataType x);
//删除元素
void STPop(ST* pst);
//判断栈顶元素是否为空
bool STEmpty(ST* pst);
//找栈顶元素
STDataType STTop(ST* pst);
//栈中元素个数
STDataType STSize(ST* pst);

test.c

//实现栈
void test()
{
	ST st;
	STInit(&st);
	STPush(&st,1);
	STPush(&st, 2);
	STPush(&st, 3);
	STPush(&st, 4);
	while (!STEmpty(&st))
	{
		printf("%d ", STTop(&st));
		STPop(&st);
	}
	STDestroy(&st);
}
int main()
{
	test();
	return 0;
}

SeqList.c

//实现栈
//初始化
void STInit(ST* pst)
{
	pst->a = NULL;
	pst->capacity = 0;
	pst->top = 0;
}
//销毁
void STDestroy(ST* pst)
{
	assert(pst);
	free(pst->a);
	pst->capacity = pst->top = 0;
}
//插入元素
void STPush(ST* pst, STDataType x)
{
	if (pst->top == pst->capacity)
	{
		int newcapacity = pst->capacity == 0 ? 4 : pst->capacity * 2;
		STDataType* newnode = (STDataType*)realloc(pst->a, sizeof(STDataType) * newcapacity);
		if (newnode == NULL)
		{
			perror("STPush");
			return;
		}
		pst->a = newnode;
		pst->capacity = newcapacity;
	}
	pst->a[pst->top] = x;
	pst->top++;
}
//判断栈顶元素是否为空
bool STEmpty(ST* pst)
{
	assert(pst);
	return pst->top == 0;
}
//删除元素
void STPop(ST* pst)
{
	assert(pst);
	assert(!STEmpty(pst));
	pst->top--;
}
//找栈顶元素
STDataType STTop(ST* pst)
{
	assert(pst);
	assert(!STEmpty(pst));
	return pst->a[pst->top - 1];
}
//栈中元素个数
STDataType STSize(ST* pst)
{
	assert(pst);
	return pst->capacity;
}

总结

总之,其实栈就是对顺序表的应用,熟练栈和队列,对我们巩固顺序表和链表帮助很大,当然,栈在一些场景下很实用,后面我会出一个专门的习题讲解篇章,讲数据结构的一些经典题型,感兴趣的可以点赞关注一下

创作不易,还请各位大佬点赞支持一下!!!

标签:top,元素,ST,理解,深入,STDataType,数据结构,void,pst
From: https://blog.csdn.net/2301_80220607/article/details/137523622

相关文章

  • 【数据结构与算法】:堆排序和选择排序
    1.堆排序堆排序是一种比较复杂的排序算法,因为它的流程比较多,理解起来不会像冒泡排序和选择排序那样直观。1.1堆的结构要理解堆排序,首先要理解堆。堆的逻辑结构是一棵完全二叉树,物理结构是一个数组。(如果不知道什么是二叉树,请前往我的主页查看)。所以堆是一个用数组表......
  • 说说对WebSocket的理解?应用场景?
    一、是什么WebSocket,是一种网络传输协议,位于OSI模型的应用层。可在单个TCP连接上进行全双工通信,能更好的节省服务器资源和带宽并达到实时通迅客户端和服务器只需要完成一次握手,两者之间就可以创建持久性的连接,并进行双向数据传输从上图可见,websocket服务器与客户端通过握手连......
  • 关于雨滴谱数浓度的理解
    采样面积为:54cm2或0.0054m2时间间隔:60s这个公式如何理解?答:此公式是雨滴谱的数浓度公式,算出此公式才能进行后面的gamma分布首先,这个公式计算的是某1分钟32×32数据的N(Di)情况,比如从i=3开始计算,那么就是D3对应的所有速度档求和的情况。ΔDi如何理解?......
  • 突破编程_C++_网络编程(Windows 套接字(常用数据结构))
    1WSADATAWSADATA结构体包含了关于Winsock实现的一些详细信息,定义如下:structWSAData{WORDwVersion;//Winsock版本号WORDwHighVersion;//Winsock动态库支持的最高版本号charszDescription[WSADESCRIPTION_LEN+1];//Winsock描......
  • unordered_map的理解和应用
    1、介绍unordered_map,它是一个关联容器,内部采用的是hash表结构,拥有快速检索的功能。1.1、特性关联性:通过key去检索value,而不是通过绝对地址(和顺序容器不同)无序性:使用hash表存储,内部无序Map:每个值对应一个键值键唯一性:不存在两个元素的键一样动态内存管理:使用内存管理......
  • MySQL 底层数据结构 聚簇索引以及二级索引 Explain的使用
    数据结构我们知道MySQL的存储引擎Innodb默认底层是使用B+树的变种来存储数据的下面我们来复习一下B树存储+B树存储 +哈希存储的区别哈希存储,只能使用等值查询B树与B+树存储我们知道B+树实际上就是B树的变种那么为啥使用B+树而不是使用B树呢?我们知道效率的高低......
  • 用node读取Excel指定sheet并输出想要的数据结构
    数据部门维护了一个Excel表格,前端显示需要其中一个sheet的数据,这个表老是更新,想着用node写一个程序,每次数据部门更新直接跑一遍。直接上代码:constXLSX=require('xlsx');constpath=require('path');constfs=require('fs');//读取Excel文件constexcelFile='要读......
  • (译) 理解 Elixir 中的宏 Macro, 第六部分:原地代码生成
    ElixirMacros系列文章译文[1](译)UnderstandingElixirMacros,Part1Basics[2](译)UnderstandingElixirMacros,Part2-MacroTheory[3](译)UnderstandingElixirMacros,Part3-GettingintotheAST[4](译)UnderstandingElixirMacros,Part4-Div......
  • 数据结构——树
    树结构的基础部分引出————我们都知道,数组、链表都可以存储数据,但是其存在缺点。对于数组来说,其优点是可以通过下标快速访问元素,但是若要检索某个具体值、或者插入值时,数组要整体移动,效率很低。下图给出了数组的插入过程,由于数组的空间不能动态变化,因此,需要创建新的数组,并......
  • 高级数据结构-并查集plus(更新中。。。
    格子游戏题目链接:格子游戏思路:首先围成一个闭环的时候,两个点一定有边相连,那么可以把这两个点通过并查集连在一个连通块里面,如果两个点的父亲相同,那么就形成闭环。同时,为了方便可以将二维的图转化成一维的进行计算,k=x*n+y,x,y要从0开始统计。代码附上:#include<bits/stdc++.h......