前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【线性表】之栈(C语言)

【线性表】之栈(C语言)

作者头像
半生瓜的blog
发布2023-05-12 21:21:10
6400
发布2023-05-12 21:21:10
举报
文章被收录于专栏:半生瓜のblog半生瓜のblog

回顾

顺序表和链表的区别和联系

顺序表:

​ 优点:空间连续支持随机访问。

​ 缺点:1.中间或前面的插入删除时间复杂度O(N)。

​ 2.增容的代价比较大

链表(带头双向循环):

​ 缺点:

​ 以借点为单位存储,不支持随机访问。

​ 优点:

​ 1.任意位置插入删除时间复杂度为O(1)

​ 2.没有增容消耗,按需申请结点空间,不用了直接释放。


栈也是线性表,在逻辑上还是挨着放的。

栈的概念以及结构

栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。**进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。**栈中的数据元素遵守后进先出LIFO(Last In First Out)的原则。

压栈:栈的插入操作叫做进栈/压栈/入栈, 入数据在栈顶

出栈:栈的删除操作叫做出栈。 出数据也在栈顶

在这里插入图片描述
在这里插入图片描述

实现方式:

  1. 数组实现
在这里插入图片描述
在这里插入图片描述

总结:

相当于之前顺序表的尾插尾删,用尾做栈顶,非常合适,唯一缺陷就是,空间不够需要增容(影响不大)。

(顺序表——【线性表】之顺序表_半生瓜のblog-CSDN博客)

  1. 链表实现
在这里插入图片描述
在这里插入图片描述

出数据得找到前一个,这样的话用双向链表更好一些。

(所以说数据结构并没有规定用什么方法实现,只要能实现就行,对比的就是效率而已。)

也可以将单链表反过来。

在这里插入图片描述
在这里插入图片描述

总结:

​ 如果用尾插做栈顶,用双向链表更好。

​ 如果用单链表实现,就用头去做栈顶,这样入栈和出栈效率都是O(1)。

​ 整体来说数组的效率更优一些。


结构定义

代码语言:javascript
复制
typedef int StackDataType;
typedef struct Stack
{
	StackDataType* arry;
	int top;//指向栈顶
	int capacity;//栈的容量——能放几个数据
}Stack;

初始化

如果初识的top给0,意味着top指向栈顶的元素的下一个,top给-1,top指向栈顶元素。

一定不能为空的东西,可以使用断言来处理。OJ题不可以使用断言。

代码语言:javascript
复制
void StackInit(Stack* ps)
{
	assert(ps);
	ps->arry = (StackDataType*)malloc(sizeof(StackDataType)*4);
	if (ps->arry == NULL)
	{
		printf("malloc fail");
		exit(-1);
	}
	ps->capacity = 4;
	ps->top = 0;
}

销毁

代码语言:javascript
复制
void StackDestory(Stack* ps)
{
	assert(ps);
	free(ps->arry);
	ps->arry = NULL;
	ps->top = ps->capacity =0 ;
}

入栈

代码语言:javascript
复制
void StackPush(Stack* ps, StackDataType x)
{
	assert(ps);
	//满了
	if (ps->top == ps->capacity)
	{
		StackDataType* tmp = (StackDataType*)realloc(ps->arry, ps->capacity * 2 * sizeof(StackDataType));
		if (tmp == NULL)
		{
			printf("realloc fail");
			exit(-1);
		}
		else
		{
			ps->arry = tmp;
			ps->capacity *= 2;
		}
	}
	ps->arry[ps->top] = x;
	ps->top++;
} 

出栈

代码语言:javascript
复制
void StackPop(Stack* ps)
{
	assert(ps);
	//如果栈空了调用top,直接终止程序报错
	assert(ps->top > 0);
	ps->top--;
}

返回栈顶元素

代码语言:javascript
复制
StackDataType StackTop(Stack* ps)
{
	assert(ps);
	assert(ps->top > 0);
	return ps->arry[ps->top - 1];
}

返回栈中元素个数

代码语言:javascript
复制
int StackSize(Stack* ps)
{
	assert(ps);
	return ps->top;
}

判断栈是否为空

代码语言:javascript
复制
bool StackEmpty(Stack* ps)
{
	assert(ps);
	return ps->top == 0;//真为空,假为非空。
}

小提示:

上面有的函数只有两行代码,如果直接用里面的那句代码,可以吗? 可以,但是不好,通过那句代码访问到,但严格来说你不应该去访问,这是一种耦合,耦合就是一种强关联, 调用函数,无需去想top在0还是在-1,只管用就完事了。(有点软件工程的思想)


调用

代码语言:javascript
复制
int main(void)
{	
	Stack ps;
	StackInit(&ps);
	StackPush(&ps,1);
	StackPush(&ps,2);
	StackPush(&ps,3);
	while (!StackEmpty(&ps))
	{
		printf("%d ", StackTop(&ps));
		//取完栈顶的数据,想取下一个,那就得删一下
		StackPop(&ps);
	}
	printf("\n");
	StackDestory(&ps);
	return  0;
}
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2021-06-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 回顾
    • 结构定义
      • 初始化
        • 销毁
          • 入栈
            • 出栈
              • 返回栈顶元素
                • 返回栈中元素个数
                  • 判断栈是否为空
                    • 调用
                    领券
                    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档