【前言】题目示例:
编写一程序判断从键盘输入的子符串括号是否匹配。假设需判断的括号只有“(”,“)”,“[”,“]”,“{”,“}”六种。
可爱捏
目录
正文开始:
顺序栈编写代码
1.顺序栈存储类型
顺序栈采用的是顺序存储,利用的是一组地址连续的存储单元存放自栈底到栈顶的数据元素,并且附加一个指针top来指向当前栈顶元素位置。
那么第一步就是建立顺序栈的存储类型。我们将这组连续的存储单元命名为zifuchuan的字符数组,同时定义宏stack_size=30,以此来限制字符串的长度。
typedef struct {
int top;//栈顶指针
char zifuchuan[STACK_SIZE]; //最大容量30
}seqStack;
2.初始化栈,入栈,出栈操作
我们对顺序栈进行初始化,也就是将top置为了-1,方便之后的操作。加1即可得到0,成为字符串数组的第一个下标。
//初始化栈
int InitStack(seqStack* s) {
s->top = -1; //初始化栈顶指针
return 1;
下一步则是建立入栈和出栈函数。
入栈函数如下,参数需要传入的是建立的栈的指针和需要入栈的元素。
//入栈函数
int Push(seqStack* s, char x) {
//判断栈满
if (s->top == (STACK_SIZE - 1))
{
return 0;
}
s->zifuchuan[++(s->top)] = x;
return 1;
}
注意在入栈前一定要先判断是否栈满,顺序栈的判定如上,top的值如果等于了stack _size-1,那就说明顺序栈已经满了。因为我们给的top是从-1开始的。可以将其与数组的最大长度类比一下,长度为30个数字的数组最多只有arr[29]
当栈判定不是满的那就意味着可以入栈元素了。要注意的是,顺序栈采用的是先将指针加1,再加入元素, 所以我们代码写的是++(元素)。代表着先自加再使用。
那么到这里入栈操作就完成了,接下来就是出栈操作。
//出栈函数
int Pop(seqStack* s) {
//判断栈空
if (s->top == -1)
{
return 0;
}
s->top--;
return 1;
}
出栈也是同样道理,需要先判定栈是不是空的,毕竟如果是空的,就没有元素可以出来了。
判断条件也十分简单,top等于-1就说明没有元素入栈了。判断完成后只需要将top--即可,将top指向了栈顶的下一个元素,那么上面那个元素也就出栈了。
那么顺序栈的构建就基本完成了。
3.主函数
下面先来写主函数
int main()
{
char ch[30];//创建字符数组
char* ptr = ch;
scanf("%s", ch);
printf("%d\n", BracketMatch(ptr));
return 0;
}
主函数非常简单,也就是输入一个数组,将其放入接下来要写的bracketmatch函数中,如果符号匹配,那么返回1,如果不匹配则返回0了。
4.核心函数--判断是否匹配
int BracketMatch(char* str) {
seqStack s;
int i;
char ch;//接收弹出的字符
InitStack(&s);
for (i = 0; str[i] != 0; i++) {
switch (str[i])
{
case '(':
case '[':
case '{':Push(&s, str[i]); //让(和[,{进栈
break;
case ')':
case ']':
case '}': ch = s.zifuchuan[s.top];
if (Match(ch, str[i]))
{
Pop(&s);//匹配的字符出栈
}
else {
return 0;
}
}
}
return 1;
}
上面就是程序的核心代码了。
首先建立栈,用以存放(和{。记得还要对其进行初始化。
再将str的整个字符串数组放入for循环,搭配switch寻找其中的(和{。
这里需要注意的是for循环的终止条件,当字符串数组不满我们所填的30个后,剩下的会以0填充。
所以终止条件如上。当遇到了(和{就将其放进栈中。
如果遇到了)和},则要用到ch啦,专门建立用来接收从栈里弹出的字符。此时,ch就会等于栈顶的那个元素。那么现在就可以将ch与现在的str[i](也就是)或者{)进行一个比较,查看是否匹配。
需要用到的match函数如下
int Match(char ch1, char ch2)
{
if ((ch1 == '{' && ch2 == '}') || (ch1 == '[' && ch2 == ']') || (ch1 == '(' && ch2 == ')'))
return 1;
else return 0;
}
如果匹配则返回1,进入if循环,将那个匹配的(或者{进行出栈。如果不匹配那么就直接进入了braketmatch的return 0,也就是返回了0,程序结束。如果第一对匹配成功,将会继续循环寻找下一对,直到遍历完数组到0这个数字。
5.整体代码
#include <stdio.h>
#include <stdlib.h>
#define STACK_SIZE 30
//使用顺序栈来完成。
typedef struct {
int top;//栈顶指针
char zifuchuan[STACK_SIZE]; //最大容量30
}seqStack;
//初始化栈
int InitStack(seqStack* s) {
s->top = -1; //初始化栈顶指针
return 1;
}
//入栈函数
int Push(seqStack* s, char x) {
//判断栈满
if (s->top == (STACK_SIZE - 1))
{
return 0;
}
s->zifuchuan[++(s->top)] = x;
return 1;
}
//出栈函数
int Pop(seqStack* s) {
//判断栈空
if (s->top == -1)
{
return 0;
}
s->top--;
return 1;
}
int Match(char ch1, char ch2)
{
if ((ch1 == '{' && ch2 == '}') || (ch1 == '[' && ch2 == ']') || (ch1 == '(' && ch2 == ')'))
return 1;
else return 0;
}
int BracketMatch(char* str) {
seqStack s;
int i;
char ch;//接收弹出的字符
InitStack(&s);
for (i = 0; str[i] != 0; i++) {
switch (str[i])
{
case '(':
case '[':
case '{':Push(&s, str[i]); //让(和[,{进栈
break;
case ')':
case ']':
case '}': ch = s.zifuchuan[s.top];
if (Match(ch, str[i]))
{
Pop(&s);//匹配的字符出栈
}
else {
return 0;
}
}
}
return 1;
}
int main()
{
char ch[30];//创建字符数组
char* ptr = ch;
scanf("%s", ch);
printf("%d\n", BracketMatch(ptr));
return 0;
}
运行示例
问题解决啦。其实链式栈也差不多,只是入栈出栈有些许区别罢了。想要了解的小伙伴接着往下看吧。
链式栈编写代码
1.链式栈存储类型
建立指针(下一个节点元素的地址)与存储栈的元素值。
typedef struct node
{
struct node *next;
char ch;
}stack;
2.初始化栈,入栈,出栈操作
//建立栈初始化函数,其实就是创建一个头结点
stack* initstack(stack* s)
{
s = (stack*)malloc(sizeof(stack));
s->next = NULL; //记得将next记为空
return s;
}
第一步仍然是对栈的初始化,这里和顺序栈就有很大差别了。本质上就是创建一个头节点。
需要注意的四点:
1.栈空条件:s->next==NULL
2.栈满条件:一般不考虑栈满情况
3.进栈操作: 新建一个结点,让指针p指向它,将结点p插入到头结点之后
4.出栈操作: 取出首结点存放的值并进行删除
进行入栈操作
//入栈函数
int push(stack* s, char x)
{
stack* t;//构造t这个节点用以存储e
t = (stack*)malloc(sizeof(stack));
t->ch = x;
//2.把t节点添加到头节点的后面
t->next = s->next;
s->next = t;
}
进行出栈操作
int pop(stack* s, char* x)
{
stack* t;
if (s->next != NULL)//判断栈是否为空
{
//让t指向栈顶元素节点
t = s->next;
//把栈顶元素值存储到*x中
*x = t->ch;
//删除
s->next = t->next;
//释放存储空间
free(t);
return 1;
}
else
{
printf("栈空,不能出栈!\n");
return 0;
}
}
3.主函数
int main()
{
char str[30];
printf("input the string:"); //输入需要测试的字符串
scanf("%s", str);
char* ptr = str; //为其创建指针变量
printf("%d\n", match2(ptr)); //使用自定义math2函数判断是否匹配
return 0;
}
4.核心函数代码段
//创建两个匹配函数
int match(char ch1, char ch2)
{
if (ch1 == '[' && ch2 == ']' || ch1 == '(' && ch2 == ')' || ch1 == '{' && ch2 =='}')
return 1;
else
return 0;
}
int match2(char* str)
{
stack s;
int i;
char ch;
initstack(&s); //创建栈
for (i = 0; str[i] != 0; i++) //不满30,后续所填皆为0
{
switch (str[i]) //循环找到符号进行入栈操作
{
case '(':
case '[':
case '{': push(&s, str[i]);
break;
case ')':
case ']':
case '}':ch = s.next->ch;
if (match(ch, str[i])) //判断是否匹配
{
pop(&s, &ch);
}
else {
return 0;
}
}
}
return 1;
}
和顺序栈不同的地方也就是弹出的元素赋给ch那里有一点差别。
其他基本相同。运行结果也相同。
5.整体代码
#include<stdio.h>
#include<stdlib.h>
//要求:查看符号是否前后匹配。匹配输出1,不匹配输出0.
//设计一个链式栈
typedef struct node
{
struct node *next;
char ch;
}stack;
//建立栈初始化函数,其实就是创建一个头结点
stack* initstack(stack* s)
{
s = (stack*)malloc(sizeof(stack));
s->next = NULL; //记得将next记为空
return s;
}
//入栈函数
int push(stack* s, char x)
{
stack* t;//构造t这个节点用以存储e
t = (stack*)malloc(sizeof(stack));
t->ch = x;
//2.把t节点添加到头节点的后面
t->next = s->next;
s->next = t;
}
//出栈函数
int pop(stack* s, char* x)
{
stack* t;
if (s->next != NULL)//判断栈是否为空
{
//让t指向栈顶元素节点
t = s->next;
//把栈顶元素值存储到*x中
*x = t->ch;
//删除
s->next = t->next;
//释放存储空间
free(t);
return 1;
}
else
{
printf("栈空,不能出栈!\n");
return 0;
}
}
//创建两个匹配函数
int match(char ch1, char ch2)
{
if (ch1 == '[' && ch2 == ']' || ch1 == '(' && ch2 == ')' || ch1 == '{' && ch2 =='}')
return 1;
else
return 0;
}
int match2(char* str)
{
stack s;
int i;
char ch;
initstack(&s); //创建栈
for (i = 0; str[i] != 0; i++) //不满30,后续所填皆为0
{
switch (str[i]) //循环找到符号进行入栈操作
{
case '(':
case '[':
case '{': push(&s, str[i]);
break;
case ')':
case ']':
case '}':ch = s.next->ch;
if (match(ch, str[i])) //判断是否匹配
{
pop(&s, &ch);
}
else {
return 0;
}
}
}
return 1;
}
int main()
{
char str[30];
printf("input the string:"); //输入需要测试的字符串
scanf("%s", str);
char* ptr = str; //为其创建指针变量
printf("%d\n", match2(ptr)); //使用自定义math2函数判断是否匹配
return 0;
}
以上便是使用两种栈来解决符号匹配的问题啦,如果帮到了大家,还请留下你的赞,毕竟创作不易,为大家呈现好的内容需要花费大把的精力和时间去整理。
再见啦,希望大家健健康康,事事顺心捏!