【两栈共享空间】------一种特殊的顺序栈

前言:

  • 虽然顺序栈的存储已经十分方便,但是它有一个非常致命的缺陷:
    必须事先确定数组存储空间的大小,万一不够用就需要动态扩容
  • 但对于两个相同类型的栈,我们可以做到最大限度的利用其事先开辟的存储空间,既让两栈共享空间

1.共享栈的定义

两个栈共享同一个存储空间,这片空间不单独属于任何一个栈,某个栈需要的多一点,它就可能得到更多的存储空间
在这里插入图片描述

2.共享栈的情况分析

注意

  • 这里所说的栈顶指针为int 下标模拟出来的指针功能
  • 这里栈顶指针指向栈顶元素

2.1栈为空的情况:

top1等于-1: 一号栈为空栈
top2等于数组长度: 二号栈为空栈

2.3栈满的情况:

极端情况1一号栈为空栈,二号栈为满栈;此时 top2=0,top1=-1
在这里插入图片描述
极端情况2一号栈为满栈,二号栈为空栈;此时 top2=数组长度,top1=数组长度
在这里插入图片描述
最多出现的情况:
两个栈顶指针见面的时候:
在这里插入图片描述
而不管是极端情况还是最多出现的情况,都可以总结成一种情况:
两个指针之差结果等于1这种情况

3.共享栈的相关核心操作

3.1共享栈的结构定义:

包括了一号栈 与 二号栈的栈顶指针,以及容纳两个栈中元素的数组

//1.共享栈的结构定义
typedef struct StackNode
{
	SElemType data[MAXSIZE];
	int top1;//栈1的栈顶指针(从数组的0开始)
	int top2;//栈2的栈顶指针(从数组的n-1开始)
}DoubleStack;
//DoubleStack:用来定义栈的结构

3.2共享栈的入栈操作

注意:要传入栈的结构体指针,即&s,以及要入栈的元素要入栈的栈号

Push(DoubleStack * s, SElemType e,int stacknumber)
3.2.1算法步骤:

(1判断两个栈是否栈满
(2)若给一号栈入栈,进行一号栈的入栈操作
<1>栈顶指针后移
<2>为当前栈顶空间赋值
两步可以合并为一步:s->data[++s->top1]; 先移动栈顶指针,再赋值
(3)若给二号栈入栈,进行二号栈的入栈操作
<1>栈顶指针前移
<2>为当前栈顶空间赋值
两步可以合并为一步:s->data[–s->top2]; 先移动栈顶指针,再赋值

  • 一号栈的入栈图解:

在这里插入图片描述
2.先后移栈顶指针
在这里插入图片描述
3.再赋值
在这里插入图片描述

  • 二号栈的入栈图解:

在这里插入图片描述

2.先前移栈顶指针
在这里插入图片描述

3.再赋值
在这里插入图片描述

//2.共享栈的入栈操作
//注意:要传入栈的结构体指针,即&s,以及要入栈的元素,要入栈的栈号
bool Push(DoubleStack * s, SElemType e,int stacknumber)
{
	//[1]判断两个栈是否栈满
	if (s->top1 + 1 == s->top2)
	{
		printf("栈满!\n");
		return false;
	}

	//[2]若给一号栈入栈,进行一号栈的入栈操作
	if(stacknumber == 1)
	{
		//<1>栈顶指针后移
		s->top1++;
		//<2>为当前栈顶空间赋值
		s->data[s->top1] = e;

		//两步可以合并为一步:
		//s->data[++s->top1];先移动栈顶指针,再赋值
		return true;
	}
	//[3]若给二号栈入栈,进行二号栈的入栈操作
	else if (stacknumber == 2)
	{
		//<1>栈顶指针前移
		s->top2--;
		//<2>为当前栈顶空间赋值
		s->data[s->top2] = e;

		//两步可以合并为一步:
		//s->data[--s->top2];先移动栈顶指针,再赋值
		return true;
	}
	else
	{
		return false;//错误的栈编号!
	}
}

3.3共享栈的出栈操作:

注意:要传入栈的结构体指针,即&s,以及接收栈顶元素的变量要出栈的栈号

Pop(DoubleStack* s, SElemType* e, int stacknumber)
3.3.1算法步骤:

(1)若给一号栈出栈,进行一号栈的出栈操作
<1>若栈空,则返回false
<2>将当前栈顶元素赋值给e
<3>栈顶指针前移
2,3步可以合并为一步:*e = s->data[s->top1- -]; 先将栈顶元素出栈,再将栈顶指针前移
(2)若给二号栈出栈,进行二号栈的出栈操作
<1>若栈空,则返回false
<2>将当前栈顶元素赋值给e
<3>栈顶指针后移
2,3步可以合并为一步:*e = s->data[s->top1++]; 先将栈顶元素出栈,再将栈顶指针前移
(3) 若栈编号不正确,则返回false

  • 一号栈的出栈图解:

在这里插入图片描述

2.先将当前栈顶元素赋值给e
在这里插入图片描述

3.再前移栈顶指针
在这里插入图片描述

  • 二号栈的出栈图解:

在这里插入图片描述

2.先将当前栈顶元素赋值给e
在这里插入图片描述

3.再后移栈顶指针
在这里插入图片描述

//3.共享栈的出栈操作
bool Pop(DoubleStack* s, SElemType* e, int stacknumber)
{

	//[1]若给一号栈出栈,进行一号栈的出栈操作
	if (stacknumber == 1)
	{
		//<1>若栈空,则返回false
		if (s->top1 == -1)
		{
			printf("栈空!\n");
			return false;
		}

		//<2>将当前栈顶元素赋值给e
		*e = s->data[s->top1];
		//<3>栈顶指针前移
		s->top1--;

		//两步可以合并为一步:
		//*e = s->data[s->top1--];先将栈顶元素出栈,再将栈顶指针前移
	}

	//[2]若给二号栈出栈,进行二号栈的出栈操作
	else if (stacknumber == 2)
	{
		//<1>若栈空,则返回false
		if (s->top2 == MAXSIZE)
		{
			printf("栈空!\n");
			return false;
		}

		//<2>将当前栈顶元素赋值给e
		*e = s->data[s->top2];
		//<3>栈顶指针后移
		s->top2++;

		//两步可以合并为一步:
		//*e = s->data[s->top1++];先将栈顶元素出栈,再将栈顶指针前移
	}
	else
	{
		return false;//错误的栈编号!
	}
	return true;
}

4.核心操作的整体实现

//共享栈
//为了最大限度的节省空间,让两个同类型的栈共享同一快存储空间
#include<stdio.h>
#include<stdlib.h>

#define MAXSIZE 100//两栈的最大容量


typedef int SElemType;//栈中元素的类型

#define bool int
#define true 1
#define false 0


//1.共享栈的结构定义
typedef struct StackNode
{
	SElemType data[MAXSIZE];
	int top1;//栈1的栈顶指针(从数组的0开始)
	int top2;//栈2的栈顶指针(从数组的n-1开始)
}DoubleStack;
//DoubleStack:用来定义栈的结构

//共享栈的初始化操作
void InitStack(DoubleStack* s)
{
	s->top1 = -1; // 初始化一号栈的栈顶指针
	s->top2 = MAXSIZE; // 初始化二号栈的栈顶指针
}


//2.共享栈的入栈操作
//注意:要传入栈的结构体指针,即&s,以及要入栈的元素,要入栈的栈号
bool Push(DoubleStack * s, SElemType e,int stacknumber)
{
	//[1]判断两个栈是否栈满
	if (s->top1 + 1 == s->top2)
	{
		printf("栈满!\n");
		return false;
	}

	//[2]若给一号栈入栈,进行一号栈的入栈操作
	if(stacknumber == 1)
	{
		//<1>栈顶指针后移
		s->top1++;
		//<2>为当前栈顶空间赋值
		s->data[s->top1] = e;

		//两步可以合并为一步:
		//s->data[++s->top1];先移动栈顶指针,再赋值
		return true;
	}
	//[3]若给二号栈入栈,进行二号栈的入栈操作
	else if (stacknumber == 2)
	{
		//<1>栈顶指针前移
		s->top2--;
		//<2>为当前栈顶空间赋值
		s->data[s->top2] = e;

		//两步可以合并为一步:
		//s->data[--s->top2];先移动栈顶指针,再赋值
		return true;
	}
	else
	{
		return false;//错误的栈编号!
	}
}


//3.共享栈的出栈操作
bool Pop(DoubleStack* s, SElemType* e, int stacknumber)
{

	//[1]若给一号栈出栈,进行一号栈的出栈操作
	if (stacknumber == 1)
	{
		//<1>若栈空,则返回false
		if (s->top1 == -1)
		{
			printf("栈空!\n");
			return false;
		}

		//<2>将当前栈顶元素赋值给e
		*e = s->data[s->top1];
		//<2>栈顶指针前移
		s->top1--;

		//两步可以合并为一步:
		//*e = s->data[s->top1--];先将栈顶元素出栈,再将栈顶指针前移
	}

	//[2]若给二号栈出栈,进行二号栈的出栈操作
	else if (stacknumber == 2)
	{
		//<1>若栈空,则返回false
		if (s->top2 == MAXSIZE)
		{
			printf("栈空!\n");
			return false;
		}

		//<2>将当前栈顶元素赋值给e
		*e = s->data[s->top2];
		//<2>栈顶指针后移
		s->top2++;

		//两步可以合并为一步:
		//*e = s->data[s->top1++];先将栈顶元素出栈,再将栈顶指针前移
	}
	else
	{
		return false;//错误的栈编号!
	}
	return true;
}





int main()
{
	DoubleStack s1; // 声明一个共享栈
	InitStack(&s1); // 初始化共享栈

	// 测试用例
	Push(&s1, 10, 1);
	Push(&s1, 20, 2);
	SElemType e;
	Pop(&s1, &e, 1);
	printf("栈1出栈元素:%d\n", e);
	Pop(&s1, &e, 2);
	printf("栈2出栈元素:%d\n", e);

	return 0;
}

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值