- 语言:C语言
- 软件:Visual Studio 2022
- 笔记书籍:数据结构——用C语言描述
- 如有错误,感谢指正。若有侵权请联系博主
一、多栈共享技术
1、双端栈
栈的应用非常广泛,经常出现一个程序中需要多个栈的情况。若使用顺序栈,会因为对栈空间大小难以准确估计而产生有的栈溢出、有的栈空间还很空闲的情况。为了解决这个问题,可以使用多个栈共享一个足够大的数组空间,通过利用栈的动态特性来使其存储空间互相补充,这就是多栈技术。最常用的使俩个栈共享技术,即双端栈。
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、代码运行结果
二、典型例子
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、代码运行结果