【数据结构】顺序栈和链式栈解决字符串括号匹配问题

【前言】题目示例:

编写一程序判断从键盘输入的子符串括号是否匹配。假设需判断的括号只有“(”,“)”,“[”,“]”,“{”,“}”六种。

可爱捏

目录

顺序栈编写代码

1.顺序栈存储类型

2.初始化栈,入栈,出栈操作

3.主函数

4.核心函数--判断是否匹配

5.整体代码

链式栈编写代码

1.链式栈存储类型

2.初始化栈,入栈,出栈操作

 3.主函数

4.核心函数代码段

5.整体代码


正文开始:

顺序栈编写代码

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;
}

以上便是使用两种栈来解决符号匹配的问题啦,如果帮到了大家,还请留下你的赞,毕竟创作不易,为大家呈现好的内容需要花费大把的精力和时间去整理。

再见啦,希望大家健健康康,事事顺心捏!

  • 15
    点赞
  • 43
    收藏
    觉得还不错? 一键收藏
  • 12
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值