STL应用-使用后缀表达式求表达式的值

2 篇文章 0 订阅
1.关于中缀表达式和后缀表达式
  我们常见的表达式是中缀表达式形式,即二元运算符在两个操作数的中间,如“3+4*5”
  而后缀表达式则是运算符位于两个操作数之后。 如“3+4*5”转化为后缀表达式为“3 4 5 * +”

2.基本思路
 1.我们首先将中缀表达式转化为后缀表达式
 2.对后缀表达式求值


3.具体实现

   3.1  将中缀表达式转化为后缀表达式
      3.1.1 数据结构:
        源表达式使用字符串的形式存储,为了简便起见,这里操作数限制为1个数字,运算符限制为+,-,*,/,(和)总共6个符号
        目标表达式(后缀表达式)用链表形式存储。链表的每个节点为2个字段,第1个字段表示类型,可能的取值有2种,表示是操作符还是数字。 第2个字段是一个union,存储操作符或者操作数。       
      除此之外,在转换过程中需要使用一个栈来存储中间过程用到的运算符。
 
   3.1.2 算法
     遍历中缀表达式中的数字和符号。
     对于数字直接,将这个数字字符转化为一个整数,插入到链表尾部。
     对于左括号,进栈。
     对于运算符,将其与栈顶符号的优先级比较,若栈顶符号优先级低,此符号进栈。否则将栈顶符号弹出,并插入到链表尾部,之后将此运算符进栈。
       我们定义左括号的优先级最低,值为0,+和-优先级为1,*和/优先级最高,值为2.
       对于右括号,将栈顶符号弹出并插入到链表,直到遇到左括号为止,左括号不插入到链表.
      最后,将栈中所有符号弹出并插入到链表。
    
   3.2 对后缀表达式求值。
    3.2.1 数据结构,此过程仅作用于链表,输入和输出都是链表
    3.2.2 算法
      当链表长度大于2时,反复应用下列过程  
      从链表头开始遍历,直到找到一个包含运算符的节点。

      将这个节点以及这个节点之前的2个节点做运算,如3个节点为"3,5,*", 则计算"3*5",结果为15,存入第三个节点,然后将运算符节点前面的2个节点删除,这个操作的实质是将3个节点合并为1个节点。

以下为源代码

#include <stack>
#include <list>
#include <iostream>

using namespace std;

enum e_type { is_num,is_op};

typedef struct _lsItem
{
	e_type type;
	union 
	{
		int n;
		char op;
	}u;
}LS_ITEM;

bool is_number(char c)
{
	return c>='0' && c<='9';
}

int get_priority(char c)
{
	if (c=='*' || c=='/')
		return 2;
	else if ( c=='+' || c=='-')
		return 1;
	else 
		return 0;
}

void operator_handle( stack<char> &stack, char c, list<LS_ITEM> &ls  )
{
	char top;
	LS_ITEM item;
	while (1)
	{
		if ( stack.empty() )
		{	stack.push(c); break; }
	
		top= stack.top();
		if ( get_priority(c) > get_priority(top))
		{	stack.push(c); break;	}
		else
		{
			top= stack.top();	stack.pop();
			
			item.type = is_op;	item.u.op = top;
			ls.push_back(item);
		}
	}
}

void right_handle( stack<char> &stack, list<LS_ITEM> &list)
{
	char top;
	LS_ITEM item;
	while ( !stack.empty() )
	{
		top=stack.top();
		stack.pop();
		if ( top== '(' )
			break;
		
		item.type= is_op;
		item.u.op= top;
		list.push_back(item);
	}
}

int calc( int x, int y, char method)
{
	switch (method)
	{
	case '+': return x + y;
	case '-': return x - y;
	case '*': return x * y;
	case '/': return x / y;	
	}
	return 0;
}

void print_list(list<LS_ITEM> &ls)
{
	for ( list<LS_ITEM>::iterator it=ls.begin(); it != ls.end(); it++)
	{
		if  ( it->type== is_op)
			cout << it->u.op << " ";
		else
			cout << it->u.n << " " ;
	}
}

//计算后缀表达式的值,输入参数和输出参数都是ls
void calc_on_list( list<LS_ITEM> &ls)
{
	int n1,n2,r;
	list<LS_ITEM>::iterator pre;			// previous node

	list<LS_ITEM>::iterator op=ls.begin();  // for point to operator
	while (ls.size()>1 )
	{
		while ( op != ls.end() )
		{
			if  ( op->type== is_op )
				break;
			op++;
		}
		
		pre=op;
		pre--;	n2= pre->u.n;
		pre--;	n1= pre->u.n;
		
		r= calc( n1, n2, op->u.op);
		op->type= is_num;
		op->u.n = r;

		pre=op; pre--;	ls.erase(pre);
		pre=op; pre--;	ls.erase(pre);
	}
}

// 将中缀表达式src,转化为后缀表达式,存入ls
void convert(const char *src, stack<char> &stack, list<LS_ITEM> &ls)
{
	const char *p;
	char c,top;
	LS_ITEM item;

	p=src;
	while (*p!=0)
	{
		c=*p++;
		if ( is_number(c) )
		{	
			item.type= is_num;
			item.u.n = c-'0';
			ls.push_back(item);
		}
		else
		{
			switch (c)
			{
			case '+':	case '-':	case '*':	case '/':
				operator_handle(stack,c,ls);	break;
			case '(':
				stack.push(c);		break;
			case ')':
				right_handle(stack,ls); break;
			default:
				printf("wrong char"); break;
			}
		}
	}
	
	while (!stack.empty() )
	{
		top= stack.top();
		item.type= is_op;
		item.u.op= top;
		ls.push_back(item);
		stack.pop();
	}
}

void test_convert_suffix_expression()
{
	char *string="8+(3-1)*5";	 // result is :8 3 1 - 5 * + 
	//char *string="3+(2-5)*6/3";  // result is "3 2 5 - 6 *3 /+"

	stack<char> stack;
	list<LS_ITEM> ls;	
	
	convert(string,stack,ls);

	cout << "source=\"" << string << "\"" << endl ;
	cout << "suffix form is \"" ;
	print_list(ls);
	cout << "\"" << endl ;

	calc_on_list( ls);
	cout << "result=";
	print_list(ls);
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是使用 C++ 实现带有括号的后缀表达式的示例代码: ```c++ #include <iostream> #include <stack> #include <string> using namespace std; int eval_suffix_expression_with_parenthesis(const string& expression) { stack<int> nums; for (char c : expression) { if (isdigit(c)) { nums.push(c - '0'); } else if (c == '+' || c == '-' || c == '*' || c == '/') { int operand2 = nums.top(); nums.pop(); int operand1 = nums.top(); nums.pop(); int result; switch (c) { case '+': result = operand1 + operand2; break; case '-': result = operand1 - operand2; break; case '*': result = operand1 * operand2; break; case '/': result = operand1 / operand2; break; } nums.push(result); } else if (c == '(') { nums.push(c); } else if (c == ')') { // Pop out elements until '(' is encountered stack<int> sub_expression; while (nums.top() != '(') { sub_expression.push(nums.top()); nums.pop(); } nums.pop(); // Pop out the '(' int sub_expression_result = eval_suffix_expression_with_parenthesis(sub_expression); nums.push(sub_expression_result); } } return nums.top(); } int main() { string expression = "23 34 + ( 45 56 * - ) 2 /"; int result = eval_suffix_expression_with_parenthesis(expression); cout << "Result: " << result << endl; // Expected output: -95 return 0; } ``` 这里使用STL 中的 `stack` 类来实现栈的功能。函数接收一个字符串表示的后缀表达式作为输入,返回表达式的计算结果。在处理运算符时使用了 `switch` 语句来进行不同操作数之间的运算。当遇到左括号时,将其压入栈中;当遇到右括号时,不断弹出栈顶元素直到遇到左括号,将弹出的元素作为一个整体压入栈中,表示括号内的表达式

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值