数据结构--实验二--链栈实现括号匹配

题目要求:

假设表达式中允许包含两种括号:圆括号和方括号,其嵌套的顺序随意,即([]())或[([][])]等为正确的格式,[(])或([())或(()])均为不正确的格式。检验括号是否匹配的方法可用“期待的急迫程度”这个概念来描述。例如考虑下列括号序列:

[([][])]

12345678

当计算机接受了第一个括号后,它期待着与其匹配的第八个括号的出现,然而等来的却是

第二个括号,此时第一个括号“[”只能暂时靠边,而迫切等待与第二个括号相匹配的、第七个括号“)”的出现,类似地,因等来的是第三个括号“[”,其期待匹配的程度较第二个括

号更急迫,则第二个括号也只能靠边,让位于第三个括号,显然第二个括号的期待急迫性

高于第一个括号;在接受了第四个括号之后,第三个括号的期待得到满足,消解之后,第二个括号的期待匹配就成为当前最急迫的任务了,……,依次类推。可见,这个处理过程恰与栈的特点相吻合。由此,在算法中设置一个栈,每读入一个括号,若是右括号,则或者使置于栈顶的最急迫的期待得以消解,或者是不合法的情况;若是左括号,则作为一个新的更急迫的期待压入栈中,自然使原有的在栈中的所有未消解的期待的急迫性都降了一级。另外,在算法的开始和结束时,栈都应该是空的。

要求:要求:

(1) 程序要添加适当的注释,程序的书写要采用缩进格式。

(2) 程序要具在一定的健壮性,即当栈满入栈时,程序给出栈满的提示。

(3) 程序要做到界面友好,在程序运行时用户可以根据相应的提示信息进行操作。


//-----!链栈实现括号匹配-------- 
#include<iostream>
using namespace std;

#define OK 1//定义常量 
#define ERROR 0//定义常量 
#define OVERFLOW -2//定义常量 
typedef char SElemType;//定义类型别名,SELemType表示栈中元素的类型 
typedef int Status; //定义函数别名,Status表示函数的返回值类型 

typedef struct SNode{
	int data;
	struct SNode *next;
}SNode,*LinkStack;//将 struct SNode 定义的结构体类型命名为 SNode
//并通过 *LinkStack 这样的语法将该结构体类型的指针命名为 LinkStack
//在后续的代码中,可以直接使用 LinkStack 来声明链栈变量或参数

//实现了初始化栈的函数InitStack,将链栈指针置为空
Status InitStack(LinkStack &S){
	S=NULL;
	return OK;
}

//判断栈是否为空的函数StackEmpty,通过判断链栈指针是否为空来确定栈是否为空
bool StackEmpty(LinkStack S){
	if(!S)
	return true;
	return false;
}

//入栈操作的函数Push,创建一个新节点并将元素压入栈顶
/*
Status:int类型(前面定义过的) 
LinkStack引用数据类型(前面定义过的) SElemType:char类型(前面定义过的) 
Status Push(LinkStack &S, SElemType e): 这是函数的声明,说明了该函数名为 Push,
接受一个指向 LinkStack 的引用类型参数 S,和一个 SElemType 类型的参数 e,
返回一个 Status 类型的值
*/ 
Status Push(LinkStack &S,SElemType e){
	SNode *p = new SNode;//创建了一个新的结点指针 p,用 new 运算符动态分配内存来创建一个 SNode 结构体对象,并将其地址赋给 p
	if(!p) {
		return OVERFLOW;//如果p是空指针,则返回溢出错误码OVERFLOW 
	}
	p->data=e;//将传入的参数 e 的值赋给 p 所指向的结点的 data 成员,即将要入栈的元素值存储在链栈结点中。
	p->next=S;// 将链栈中当前的栈顶指针 S 赋给 p 所指向的结点的 next 成员,使新结点 p 的 next 指针指向当前的栈顶结点 
	S=p;//将链栈的栈顶指针 S 指向新的入栈结点 p,将新结点作为链栈的新的栈顶 
	return OK;//返回操作成功状态码 OK,表示入栈操作执行成功
}

//出栈操作的函数Pop,将栈顶元素弹出,并释放对应的节点空间 
Status Pop(LinkStack &S,SElemType &e){//LinkStack引用数据类型;SElemType:char的别名,以及引用参数e 
	SNode *p;//创建了一个新的指针变量p,用于临时保存栈顶结点的位置 
	if(!S)
	return ERROR;
	e=S->data;//如果栈S不为空,则将栈顶节点的数据data赋值给e,以便在函数外部可以获取到出栈的元素
	p=S;//将指针变量p指向栈顶节点即S 
	S=S->next;//更新栈顶指针S,使其指向下一个节点,实现出栈的操作 
	delete p;//释放指针变量p所指向的节点的内存空间
	return OK;//并返回OK表示出栈成功  
}

//获取栈顶元素的函数GetTop:如果栈不为空,则将栈顶元素赋值给参数e 
Status GetTop(LinkStack &S,SElemType &e){
	if(!S)
	return ERROR;//如果S为空则返回ERROR 表示获取栈顶元素失败 
	e=S->data;
	return OK;
}

//核心的函数Matching,用于检验表达式中所含括号是否正确匹配。该函数接受一个链栈作为参数 
//算法3.9 括号的匹配
Status Matching(LinkStack S){
	//检验表达式中所含括号是否正确匹配,如果匹配,则返回true,否则返回false。
	//表达式以“#”结束
	InitStack(S);//自定义函数:实现了初始化栈的函数InitStack,将链栈指针置为空 
	int flag = 1;//标记查找结果以控制循环及返回结果 
	char c;
	SElemType x;
	cin >> c;//读入第一个字符
	while(c!='#'&&flag){
		switch(c){
			case '[':
			case '('://若是左括号,则将其压入栈
				Push(S,c);//自定义函数:入栈操作的函数Push,创建一个新节点并将元素压入栈顶
				break;//若当前字符c为左括号“[”或“(”,则将其压入栈S。 
			case ')'://若当前字符c是右括号")",则根据当前栈顶元素的值分情况考虑
				GetTop(S,x);
				if(!StackEmpty(S)&&x=='(')//若栈非空且栈顶元素是"(",则匹配成功
					Pop(S,x);//出栈操作的函数Pop,将栈顶元素弹出,并释放对应的节点空间
				else
					flag=0;//若栈空或栈顶元素不是"(" ,则非法
				break;
			case ']'://若是右括号"]",则根据当前栈元素的值分情况考虑
				GetTop(S,x);//获取栈顶元素的函数GetTop:如果栈不为空,则将栈顶元素赋值给参数e 
				if(!StackEmpty(S)&&x=='[')//若栈顶元素是'[',则匹配成功,//通过判断链栈指针是否为空来确定栈是否为空 
					Pop(S,x);出栈操作
				else
					flag=0;
				break; 
		}//switch
		cin >> c;//继续读入下一个字符 
	} //while
	if(StackEmpty(S)&&flag) return 1;
	else return 0;
} //Matching

//主函数
int main(){
	LinkStack S; //直接使用 LinkStack 来声明链栈变量或参数
	cout << "请输入待匹配的表达式,以 “# ”结束" << endl;
	int flag = (int)Matching(S);
	if(flag) 
		cout << "括号匹配成功!" << endl;
	else
		cout << "括号匹配失败!" <<endl;
		return 0;
} 

记一次敲代码过程!

over! 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值