数据结构与算法(C语言实现) 3.栈和循环队列的表示与实现 栈部分

实验三  栈和循环队列的表示与实现 栈部分

一、实验目的

掌握顺序栈和链栈的入栈、出栈基本操作,栈满、栈空的条件;

二、实验内容

假设表达式中允许包含圆括号、方括号和大括号3种括号,编写一个算法判断表达式中的括号是否正确配对。并将其用C语言实现,上机运行输出结果。

用顺序栈实现。提示:输入一串包括左右圆、方、大括号的字符,则左括号入栈,当和右括号匹配时,则出栈。


头文件及宏定义:

/*CaptainUniverse_ 2022.4.1*/
#include <stdio.h>
#include <stdlib.h>
#define LEFT 1
#define RIGHT 2
#define FALSE 0
#define STACK_INIT_SIZE 20

typedef int Status;
typedef struct
{
	char *top;
	char *base;
	int Stacksize;
}sqStack;
/*CaptainUniverse_ 2022.4.1*/

子函数声明:

/*CaptainUniverse_ 2022.4.1*/
Status isBrackets(char);//判断是否为括号
void InitStack(sqStack *);//栈初始化
void Push(sqStack *,char);//压栈
void Pop(sqStack *,char *);//弹栈
/*CaptainUniverse_ 2022.4.1*/

子函数主体:

/*CaptainUniverse_ 2022.4.1*/
void InitStack(sqStack *s)
{
	s->base=malloc(STACK_INIT_SIZE*sizeof(char));
	if(!s->base)
	{
		printf("内存分配失败!");
		exit(0);
	}
	s->Stacksize=STACK_INIT_SIZE;
	s->top=s->base;
	*s->top++='#';//栈内首元素压入#
}

void Push(sqStack *s,char ch) 
{
	if(s->top-s->base==STACK_INIT_SIZE)
	{
		printf("左括号过多!即将退出!\n");
		exit(0);
	}
	*s->top++=ch;
}

void Pop(sqStack *s,char *ch)
{
	if(s->top==s->base)
	{
		printf("栈已空!\n");
		exit(0);
	}
	*ch=*--s->top;
}

Status isBrackets(char ch)
{
	if(ch=='('||ch=='['||ch=='{')
	{
		return LEFT;
	}
	else if(ch==')'||ch==']'||ch=='}')
	{
		return RIGHT;
	}
	else
	{
		return FALSE;
	}
}
/*CaptainUniverse_ 2022.4.1*/

主函数:

/*CaptainUniverse_ 2022.4.1*/
int main()
{
	char ch,temp;
	sqStack s;
	InitStack(&s);
	printf("请输入一串括号字符以#结束!\n");
	printf("左括号上限19个!\n")
	while((ch=getchar())!='#')
	{
		if(isBrackets(ch)==LEFT)
		{
			Push(&s,ch);	
		}
		if(isBrackets(ch)==RIGHT) 
		{
			Pop(&s,&temp);
			if((ch!=(temp+1))&&(ch!=(temp+2)))
			{
NO:				printf("不匹配!\n");
				return 0;
			}
		}
		
	}
	Pop(&s,&temp);
	if(temp=='#')
	{
		printf("匹配!\n");
	}
	else
	{
		goto NO;//纯粹图方便和美观
	}
	return 0;			
}
/*CaptainUniverse_ 2022.4.1*/

分析:

1.遇到左括号压栈,遇到右括号将其与弹栈符号比较,如果符合则继续输入继续比较,直到输入'#'结束。注意:当输入'#'时已结束循环,故输入的'#'不参与比较。

2.匹配条件:左括号个数等于右括号个数,且此时栈内只有初始化时的'#'。

3.三种情况:

①左括号个数=右括号个数(包括左右括号个数都为零)。正常比较。

②左括号个数>右括号个数。假设所有右括号比较完毕,遇到'#'跳出循环,此时栈内存的不只是'#',还有多余的左括号,故不匹配。

③左括号个数<右括号个数。假设栈内所有左括号已比较完毕,下一个右括号讲与栈内'#‘元素比较,自然不匹配。

4.右括号与左括号的比较实为其ASCII码的比较。

'(' = 40
')' = 41

'[' = 91
']' = 93

'{' = 123
'}' = 125

这就是括号是否匹配的关键判断因素。


可略过部分:

我们设左括号为left,右括号为right(都为char类型),

如果left+1==right 为真 或者 left+2==right 为真 则括号匹配,转换成C语言:

if((left+1==right)||(left+2==right))
    printf("真");
else
    printf("假");

但我们此时想实现“如果不匹配则结束循环”

我们只需要将条件改为否命题,再将结果换位即可。

if((left+1!=right)&&(left+2!=right))
    printf("假");
else
    printf("真");

这是常用的“正难则反”思想。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值