3.5讲栈的应用

3.5讲栈的应用

栈的应用举例

栈结构所具有的“ 后进先出”特性,使得栈成为程序设计中的有用工具。本节将讨论栈应用的两个典型例子:

1、括号匹配问题

假设表达式中包含三种括号:
圆括号、方括号和花括号,它们可互相嵌套,如 ( [ { } ] ( [ ] ) )或( { ( [ ] [ ( ) ] ) } )等均为正确的格式,而 { [ ] } ) }或 { [ ( ) ] 或 ( [ ] }均为不正确的格式。

在检验算法中可设置一个栈,每读入一个括号,若是左括号,则直接入栈,等待相匹配的同类右括号;若读入的是右括号,且与当前栈顶的左括号同类型,则二者匹配,将栈顶的左括号出栈,否则属于不合法的情况。

另外,如果输入序列已读尽,而栈中仍有等待匹 的左括号,或者读入了一个右括号,而栈中已无等待匹配的左括号,均属不合法的情况。当输入序列和栈同时变为空时,说明所有括号完全匹配。

括号匹配算法

void BracketMatch(char *str) /* str[]中为输入的字符串,利用堆栈技术来检查该字符串中的括号是否匹配*/ 
{ 
	Stack 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}: 
				if(IsEmpty(&S))               
				{ 
					printf("\n 右括号多余!"); 
				return;
				} 
				else 
				{                     
					GetTop (&S,&ch); 
					if(Match(ch,str[i]))  /*用 Match 判断两个括号是否匹配*/                    
						Pop(&S,&ch);      /*已匹配的左括号出栈*/                    
					else                   
					{ 
						printf("\n 对应的左右括号不同类!");  
						return;
					} 
				} 
		}/*switch*/ 
	}/*for*/ 
	if(IsEmpty(&S))  
		printf("\n 括号匹配!"); 
	else  
		printf("\n 左括号多余!"); 
} 

表达式求值

表达式求值是高级语言编译的一个基本问题,是栈的典型应用实例。

任何一个表达式都是由运算数(operand)、运算符(operator)和界限符(delimiter)组成的。

运算数既可以是常数, 也可以是被说明为变量或常量的标识符;运算符可以分为算术运算符、关系运算符和逻辑运 算符三类;基本界限符有左右括号和表达式结束符等。

仅讨论无括号算术表达式求值的求值问题。 由于某些运算符可能具有比别的运算符更高的优先级,因此表达式求值不可能严格地从左到右进行,如下图 所示,其中↑为幂运算,#是表达式结束符,这是为运算方便引入的一个特殊符号。
在这里插入图片描述
为了正确的处理表达式,使用栈来实现正确的指令序列是一个重要的技术。下面以无括号表达式为例进行说明。

算法思想
(1)规定运算符的优先级表
(2)设置两个栈:OVS(运算数栈)、OPTR(运算符栈)
(3)自左向右扫描,进行如下处理:

①遇到运算数则进 OVS 栈;
②遇到运算符则与 OPTR 栈的栈顶运算符进行优先级比较:

  • 如果当前运算符>OPTR 栈顶运算符,则当前运算符进 OPTR 栈;
  • 如果当前运算符≤OPTR 栈顶运算符,则 OPTR退栈一次,得到栈顶运算符θ,OVS 连续退栈两次,得到运算数 a、运算数 b,对 a,b 执行θ运算,得到结果 T(i),将 T(i) 进OVS 栈。
    在这里插入图片描述

例 3-1 在实现 A/B↑C+DE 的运算过程中,栈区变化情况如图 3.9 所示。为运算方便,在表达式后面加上一个结束符#,并将其视为一个优先级最低的特殊运算符,所以实际输入 的表达式为:A/B↑C+DE#。

在这里插入图片描述
算法描述】无括号算术表达式处理算法

int ExpEvaluation() 
/*读入一个简单算术表达式并计算其值。operator 和 operand 分别为运算符栈和运算数栈, OPS 为运算符集合*/ 
{  
	InitStack(&operand);  
	InitStack(&operator);  
	Push(&operator,'#');  
	printf("\n\nPlease input an expression (Ending with #) :"); 
	ch=getchar();  
	while(ch!='#'||GetTop(operator)!='#') /* GetTop()通过函数值返回栈顶元素*/    
	{        
		if(!In(ch,OPS))                   
			/*不是操作符,是操作数*/    
		{  
			n=GetNumber(ch);    
			push(&operand,n); 
		} 
		else           
			switch(Compare(ch, GetTop(operator)))     
			{     
				case '>':  
					Push(&operator,ch);                       
					ch=getchar();  
					break;  
				case '=':     
				case '<':    
					Pop(&operator,&op);         
					Pop(&operand,&b);          
					Pop(&operand,&a);         
					v=Execute(a,op,b);  /* 对 a 和 b 进行 op 运算 */         
					Push(&operand,v);        
					break;  
			}    
	} 
	v=GetTop(operand); 
	return (v); 
} 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值