栈的应用

栈的应用

1.数制的转换
[问题描述]

    十进制数N和其他d进制数的转换时计算机实现计算的基本问题,其解决方法很多,其中一个简单算法基于下列原理:

N=(N div d)*d +N mod d (其中,div为整除运算,mod为求余运算)

例如:(1348)10=(2504)8,其运算过程如下:

   N      N div 8       N mod 8

  1348         168              4

    165           21               0

      21             2               5

      2               0               2

    假设现要编制一个满足下列要求的程序:对于输入的任意一个非负十进制整数, 打印输出与其的八进制数. 上述计算过程是从低位到高位顺序产生八进制的各个数位; 而打印输出过程, 一般来说, 应从高位到低位进行, 恰好和计算过程相反, 因而我们可以使用栈来解决这个问题.

[算法思想]

    首先将按照上述计算过程中得到的八进制的各位依次进栈, 然后将栈中的八进制依次出栈输出,输出结果就是该十进制转换得到的八进制.

[算法描述]
    void conversion()
    { /*对于输入的任意一个非负十进制数,打印输出与其等值的八进制*/
		InitStack(S);                       /*构造空栈*/
		cin>>N;
		while(N)
		{
			Push(S,N%8);
			N/=8;
		}
		while(!StackEmpty(S))            /*当栈非空时*/
		{
			Pop(S,e);
			cout<

    这是利用栈的后进先出特性的最简单的例子. 栈的引入简化了程序设计的问题, 划分了不同的关注层次, 使思考范围缩小.

2.括号的匹配
[算法思想]

    初始化一个空栈, 扫描表达式, 依次读入字符, 直到表达式扫描完或出现错误匹配. 对于读入的每个字符, 分以下几种情况处理:

1) 如果是 "[" 或 "(" , 则将其压入栈;

2) 如果是 ")" , 则根据当前栈顶元素的值分情况考虑. 若栈顶元素是"(", 则匹配成功, 否则为非法情况.

3) 如果是 "]" , 同上面的处理方法, 根据当前栈顶元素的值分情况考虑, 若栈顶元素是 "[",  则匹配成功, 否则为非法情况.

[算法描述]

Status Matching()
{ /*检验表达式中所含括号是否正确匹配,如果匹配,则返回true,否则返回false*/
  /*表达式以"#"结束*/
  int flag=1;							/*标记查找结果以控制循环及返回结果*/
  cin>>c;								/*读入第一个字符*/
  while(c!='#' && flag)
  {
	switch(c)
	{
		case '[' || '(':                /*若是左括号,则将其压入栈*/
			Push(S,c);
			break;
    		case ')':                      /*若是右括号")",则根据当前栈顶元素的值分情况考虑*/
			x=GetTop(S);
			if(x == '(')                /*若栈非空且栈顶元素是"(",则匹配成功*/
			{
				Pop(S,x);    
			}
			else                        /*若栈空或栈顶元素不是"(",则非法*/
			{
				flag=0;
			}
			break;
		case ']':                      /*若是右括号"]",则根据当前栈顶元素的值分情况考虑*/
			x=GetTop(S);
			if(x == '[')                /*若栈非空且栈顶元素是"[",则匹配成功*/
			{
				Pop(S,x);    
			}
			else                        /*若栈空或栈顶元素不是"[",则非法*/
			{
				flag=0;
			}
			break;
	}									/*switch*/
	cin>>c;                             /*继续读入下一个字符*/
  }                                     /*while*/
  if(StackEmpty(S) &&flag) 
  {
	return true;
  }
  else 
  {
	return false;
  }
}

3.表达式求值
[问题描述]
    表达式求值是程序设计语言编译中的一个最基本问题,其实现是栈应用的又一个典型例子.这里介绍一种简单直观、广义使用的算法,通常称为"算法优先法".
    要把一个表达式翻译成正确求值的一个机器指令序列,或者直接对表达式求值,首先要能够正确解释表达式.例如,要对下面的算术表达式求值: 4+2*3-10/5
    首先要了解算术四则运算的规则.即:
1)先乘除,后加减;
2)从左算到右;
3)先括号内,后括号外.
    由此,这个算术表达式的计算顺序应为 4+2*3-10/5 = 4+6-10/5 = 10-2=8

    为实现算符优先算法, 可以使用两个工作栈, 一个称作OPTR, 用以寄存运算符; 另一个称作OPND, 用以寄存操作数或运算结果.

[算法思想]

1)建立并初始化OPTR栈和OPND栈, 将表达式起始符" #" 压入OPTR栈.

2)依次读入表达式中每个字符ch, 循环执行(3)至)(5), 直至求出整个表达式的值为止.

3)取出OPTR的栈顶元素, 当OPTR的栈顶元素和当前读入的字符ch均为 "#" 时, 整个表达式求值完毕, 这时OPND的栈顶元素为表达式的值.

4)若ch不是运算符, 则压入OPND栈, 读入下一字符ch.

5)若ch是运算符, 则根据OPTR的栈顶元素和ch的优先权比较结果, 做不同的处理.

①若是小于栈顶元素, 则ch压入OPTR栈, 读入下一字符ch.

②若是大于栈顶元素, 则弹出OPTR栈顶的运算符, 从OPND栈弹出两个数, 进行相应运算,结果压入OPND栈.

③若是等于, 则OPTR的栈顶元素是 "(" 且ch是 ")" , 这时弹出OPTR栈顶的 "(" ,相当于去掉括号, 然后读入下一字符ch.
[算法描述]
OperandType EvaluateExpression()
{   /*算术表达式求值的算符优先算法.设OPTR和OPND分别为运算符栈和操作数栈*/
    /*OP为运算符集合*/
	InitStack(OPTR);
	Push(OPTR,'#');
	InitStack(OPND);
	cin>>ch;
	while(ch != '#' || GetTop(OPTR)!= '#')
	{
		if(!In(ch,OP))                             /*ch不是运算符则进栈*/
		{
			Push(OPND,ch);
			cin>>ch;
		}
		else
		{
			switch(Precede(GetTop(OPTR), ch) )     /*比较OPTR的栈顶元素和ch的优先权*/
			{
				case'<' :                          /*当前字符ch压入OPTR栈,读入下字符ch*/
					Push(OPTR,ch);
					cin>>ch;
					break;
				case '>':                          /*弹出OPTR栈顶的运算符进行相应运算,并将运算结果入栈*/
					Pop(OPTR,theta);
					Pop(OPND,b);
					Pop(OPND,a);
					Push(OPND,Operate(a,theta,b));
					break;
				case '=':                         /*脱括号并接收下一字符*/
					Pop(OPTR,x);
					cin>>ch;
					break;
			}
		}
	}
	return GetTop(OPND);
}

    算法调用的三个函数需要读者自行补充完成,其中函数In是判定读入的字符ch是否为运算符,Precede是判定运算符栈的栈顶元素与读入的运算符之间优先关系的函数,Operate为进行二元运算的函数.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值