【C语言之数据结构(栈)】

C语言之数据结构(栈)


一、栈的定义

栈:是限定仅在表尾进行插入和删除操作的线性表。
允许插入和删除的一端为栈顶(top),另一端称为栈底(bottom),不含任何数据元素的栈称为空栈。栈又称为后进先出(Last In First Out)的线性表,简称LIFO结构。
理解栈的定义需要注意:
首先是个线性表,栈元素具有线性关系,即前驱后继关系。定义中说是在线性表的表尾进行插入和删除操作,这里的表尾是指栈顶,而不是栈底。
特殊之处:限定了这个线性表的插入和删除位置,它始终只在栈顶进行操作。这也就使得:栈底是固定的,最先进栈的只能在栈底。
栈的插入操作,叫作进栈,类似子弹入弹夹。
栈的删除操作,叫作出栈,类似弹夹中子弹出夹。
在这里插入图片描述

二、进栈出栈的变化形式

有个问题,这个最新先进栈的元素,是不是就只能是最后一个出栈呢?
答案:不一定,要看具体情况。栈对线性表的插入和删除的位置,进行了限制,并没有对元素的进出的时间进行限制,也就是说,在不是所有元素都进栈的情况下,事先进去的元素也可以出栈,只要保证是栈顶元素出栈就可以了。
举例说明:如果我们现在是有3个整型数据元素1、2、3依此进栈,会有哪些出栈次序呢?
第一种:1、2、3进,再3、2、1出。这是最简单的最好理解的一种,出栈次序为321.
第二种:1进,1出,2进,2出,3进,3出。也就是进一个,出一个,出栈栈次序为123.
第三种:1进,2进,2出,1出,3进,3出。出栈次序为213.
第四种:1进,1出,2进,3进,3出,2出。出栈次序132.
第五种:1进,2进,2出,3进,3出,1出。出栈次序为231.
从这个简单的例子能看出,只有3个元素,就有5种可能的出栈次序,如果元素数量多,其实出栈的变化将会更多。这个知识点一定要弄明白。

三、栈的顺序存储结构及实现

栈是线性表的特例,那么栈的顺序存储结构其实也就是线性表顺序存储的简化,简称为顺序栈。线性表是用数组来实现的,想想看,对于栈这个只能一头插入删除的线性表来说,用数组的哪一端来作为栈顶和栈底比较好。
对,没错,下标为0的一端作为栈底比较好,因为首元素都在栈底,变化小,所以让它作栈底。
我们定义一个top变量来指示栈顶元素在数组中的位置,它可以来回移动,若存储栈的长度为StackSize,则栈顶位置top必须小于StackSize。当栈存在一个元素时,top等于0,因此通常把空栈的判定条件定为top等于-1.
栈的结构定义

typedef int SElemType;SElemType 类型根据实际情况而定,这里假设为int
typedef struct
{
	SElemType data[MAXSIZE]存储栈的长度
	int top;
}SqStack;

若现在有一个栈,StackSize是5,则栈的普通情况,空栈和栈满的情况示意图如下:
在这里插入图片描述

1.进栈操作

对于栈的插入,即进栈操作
在这里插入图片描述
对进栈操作push,代码如下:

Status Push(SqStack *S,SElemType e)
{
	if(S->top==MAXSIZE-1)栈满
	{
		return ERROR;
	}
	S->top++;栈顶指针上移
	S->data[S->top]=e;将新插入元素赋值给栈顶空间
	return OK;
}

2.出栈操作

代码如下(示例):

Status Pop(SqStack *S,SElemType *e)
{
	if(S->top==-1)
	{
		return ERROR;
	}
	*e=S->data[S->top];将要删除的栈顶元素赋值给e指针
	S->top--;指针下移
	return OK;
}

三、两栈的空间空闲(顺序存储结构及实现)

使用一个数组存储两个栈
图形展示:数组有两个端点,两个栈有两个栈底,让一个栈的栈底为数组的始端,即下标为0处,另一个栈为栈的末端,即下标为数组长度n-1处,两个栈如果增加元素就是两端点向中间延续。
在这里插入图片描述
从上图可以分析出:
空栈:栈1的top1为-1,栈2的top2为n
在这里插入图片描述
栈满:
若栈2是空栈,栈1的top1等于n-1,就是栈1满了。
若栈1是空栈,栈2的top2等于0,就是栈2满了。
但多数情况是两个栈见面时,也就两个指针之间相差1时,top1+1=top2时,为栈满。
两栈共享空间的结构体代码如下:

typedef struct
{
	SElemtype data[MAXSIZE];
	int *top1;1栈顶指针
	int *top2;2栈顶指针
}sqDoubleStack;

两栈共享空间的push方法:除了要插入元素值参数外,还需要一个判断是进入栈1 还是栈2的判断参数stackNumber,无需关系栈是否是空栈,秩序判断是否满栈即可

State Push(sqDoubuleStack *S,SElemtype e,int stackNumber)
{
	if(S->top1+1==S->top2)
	{
		return ERROR;
	}
	if(stackNumber==1)
	{
		S->top1++;
		S->data[S->top1]=e;//S->data[++S->top1]=e
	}
		if(stackNumber==2)
	{
		S->top2++;
		S->data[S->top2]=e;
	}
	return OK;
}

两栈共享空间的pop方法:只需判断要从哪个栈出栈即可(stackNumber),无需关系栈是否满栈,只判断是否为空栈即可

State Pop(sqDoubleStack *S,SElemtype *e,int stackNumber)
{
	if(stackNumber==1)
	{
		if(S->top1==-1)
		return ERROR;
		*e=S->data[S->top1--];
	}
	if(stackNumber==2)
	{
		if(S->top2==MAXSIZE)
		return ERROR;
		*e=S->data[S->top1++];
	}
	return OK;
}

总结

栈的应用:通常都是当两个栈空间需求有相反关系时,也就是说一个栈增长时另一个栈在缩短的情况下,就像买股票,你买的时候,就有人在卖。
要注意在进出栈的时候,是先移动指针,还是取出栈的值:
入栈:先移动指针,后赋值。
出栈:先取出值,后移动指针。

  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值