栈的具体使用

  • 语言:C语言
  • 软件:Visual Studio 2022
  • 笔记书籍:数据结构——用C语言描述
  • 如有错误,感谢指正。若有侵权请联系博主

一、多栈共享技术

1、双端栈

栈的应用非常广泛,经常出现一个程序中需要多个栈的情况。若使用顺序栈,会因为对栈空间大小难以准确估计而产生有的栈溢出、有的栈空间还很空闲的情况。为了解决这个问题,可以使用多个栈共享一个足够大的数组空间,通过利用栈的动态特性来使其存储空间互相补充,这就是多栈技术。最常用的使俩个栈共享技术,即双端栈。

15e7749c16924dddb930ebfb859b9edb.jpeg

 2、双端栈代码实现

#include <iostream>
#include <stdio.h>
#define MAX_SIZE 20
#define StsckElementType int

/*双端栈的结构*/
typedef struct {
	StsckElementType stack[MAX_SIZE];
	int top[2];
}Dqstack;

/*初始化栈*/
void InitStack(Dqstack* S) {
	S->top[0] = -1;
	S->top[1] = MAX_SIZE;
}

/*置空栈*/
int ClearStack(Dqstack* S,int i) {
	if (0 == i) {
		for (; S->top[0] >= 0; S->top[0]--) {
			S->stack[S->top[0]] = NULL;
		}
		return 1;
	}
	if (1 == i) {
		for (; S->top[1] < MAX_SIZE; S->top[1]++) {
			S->stack[S->top[1]] = NULL;
		}
		return 1;
	}
	return 0;
}

/*判断栈是否为空栈*/
int IsEmpty(Dqstack* S, int i) {
	if (0 == i || 1 == i) {
		if (-1 == S->top[i] || MAX_SIZE == S->top[i])
			return 1;
	}
	return 0;
}

/*判断是否为满栈*/
int IsFull(Dqstack* S) {
	if(S->top[0] + 1 == S->top[1])
		return 1;
	return 0;
}

/*入栈*/
int Push(Dqstack* S, StsckElementType e, int i) {
	if (S->top[0] + 1 == S->top[1])
		return 0;
	if (i != 0 && i != 1) return 0;
	if (0 == i) {
		S->top[0]++;
		S->stack[S->top[0]] = e;
		return 1;
	}
	if (1 == i) {
		(S->top[1])--;
		S->stack[S->top[1]] = e;
		return 1;
	}
}

/*出栈*/
int Pop(Dqstack* S, StsckElementType* e, int i) {
	if (1 == IsEmpty(S, i)) return 0;
	if (0 == i || 1 == i) {
		*e = S->stack[S->top[i]];
		0 == i ? S->top[i]-- : S->top[i]++;
		return 1;
	}
	return 0;
}

int PrintStack(Dqstack* S,int i) {
	int num;
	if (0 == i) {
		printf("\n第一个栈的数据:");
		for (num = S->top[i]; num >= 0;num--) {
			printf("%d ", S->stack[num]);
		}
		return 1;
	}
	if (1 == i) {
		printf("\n第二个栈的数据:");
		for (num = S->top[i]; num < MAX_SIZE; num++) {
			printf("%d ", S->stack[num]);
		}
		return 1;
	}
	printf("参数输出错误,0为第一个栈,1为第二个栈");
	return 0;
}

void Stack_Text() {                               //测试函数
	Dqstack* S, DS;
	S = &DS;
	int i, e,*date;
	date = &e;
	InitStack(S);
	printf("————————入栈测试,满栈测试—————————\n\n");
	printf("请输入你要操作的栈(0或1),非数字结束:");
	while (1 == scanf_s("%d", &i)) {
		if (0 == i || 1 == i) {
			printf("请输入你要存入的数(遇到非数字结束):");
			while (1 == scanf_s("%d", &e)) {
				if (IsFull(S) == 1) {
					printf("栈满了");
					goto BREK;         //goto语句为了跳出循环
				}
				Push(S, e, i);
			}
			char em;
			scanf_s("%c", &em);
		}
		printf("请输入你要操作的栈(0或1),非数字结束:");
	}
BREK:
	PrintStack(S, 0);
	PrintStack(S, 1);
	printf("\n\n————————出栈测试————————\n\n");
	for (i = 1; i < 3; i++) {
		Pop(S,date,0);
		printf("第一个栈出的第%d个数据为:%d\n", i,*date);
	}
	for (i = 1; i < 3; i++) {
		Pop(S, date, 1);
		printf("第二个栈出的第%d个数据为:%d\n", i, *date);
	}
	PrintStack(S, 0);
	PrintStack(S, 1);
	printf("\n\n————————置空判断,空栈判断测试————————\n\n");
	printf("第一个栈:空为1,非空为0:%d\n", IsEmpty(S,0));
	printf("第二个栈:空为1,非空为0:%d\n", IsEmpty(S, 1));
	printf("置空第一个栈:\n");
	ClearStack(S, 0);
	printf("第一个栈:空为1,非空为0:%d\n", IsEmpty(S, 0));
	printf("置空第二个栈:\n");
	ClearStack(S, 1);
	printf("第二个栈:空为1,非空为0:%d\n", IsEmpty(S, 1));
}

int main() {
	Stack_Text();
}

3、代码运行结果

 

84d951d92e234d9982b8b7d6127ccafa.png

二、典型例子

1、括号匹配问题

问题:设表达式中有三种括号:圆括号、方括号和花括号,它们可以互相嵌套,如([{}]([]))或({([][()])})等均为正确的格式,而{[]})}、{[()]均为不正确的格式。

算法思想:检验算法中可以设置一个栈,每读入一个字符,若使左括号,则直接入栈,等待匹配的同类右括号;若使右括号,且与当前栈顶的左括号同类型,则二者匹配,将栈顶的左括号出栈,否则属于不合法的情况。另外,如果输入序列已读完,而栈中仍有等待匹配的左括号,或者读入了一个右括号,而栈中已无等待匹配的同类型左括号,均属于不合法的情况。当输入序列和栈同时变空时,说明所有括号完全匹配。

代码实现

/*导入之前写好的栈文件*/
/*括号匹配代码,需导入之前写的顺序栈的代码*/
int Mach(char x, char y) {
	if (x == '{' && y == '}') return 1;
	if (x == '[' && y == ']') return 1;
	if (x == '(' && y == ')') return 1;
	return 0;
}
void BracketMatch() {
	SeqStack S, * Seq;
	Seq = &S;
	char* s, x;
	s = &x;
	InitStack(Seq);
	char str[40];
	int i = 0;
	printf("请输入需要检验的数据:");
	scanf_s("%s", str, sizeof(str));
	for (i = 0; str[i] != '\0'; i++) {
		switch (str[i]) {
		case '{':
		case '[':
		case '(':
			Push(Seq, str[i]);
			break;
		case '}':
		case ']':
		case ')':
			if (IsEmpty(S) == 1) {
				printf("\n右边的括号多余!");
				return;
			}
			else {
				GetTop(Seq, s);
				if (Mach(x, str[i])) {
					Pop(Seq, s);
				}
				else {
					printf("\n对应的左右括号不同类!");
					return;
				}
			}
		}
	}
	if (IsEmpty(S) == 1)
		printf("\n括号匹配!");
	else
		printf("\n左括号多余!");
}

int main() {
	BracketMatch();
}

2、代码运行结果

86011f5e3c7a46ea94abd98690ab3dc6.png

 

  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值