UVa 727 - Equation

本文详细介绍了使用递归和栈解决表达式后缀转换的方法,并通过线段树优化寻找运算优先级最低的点。讨论了数据读入错误可能导致的运行时错误(RE)和递归深度过大导致的栈溢出问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目:求表达式的后缀式。

分析:递归、栈。利用递归或栈求解即可。本人采用递归求解,每次找到运算优先级最低的点,然后递归两端即可。寻找优先级最低的点利用线段树优化。

注意:数据读入出错会RE;如果数据过大递归会暴栈。

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <cstring>
#include <stack> 

using namespace std;

char str[ 51 ];
int  mat[ 51 ];

//segment_tree__begin
typedef struct tnode
{
	tnode* Lchild;
	tnode* Rchild;
	int	   Lvalue;
	int    Rvalue;
	int    Min;
	int	   Spa;
}tnode;
tnode Node[ 105 ];

tnode* Root;
int    Count;
tnode* madetree( int a, int b ) {
	tnode* np  = &Node[ Count ++ ];
	np->Lvalue = a;
	np->Rvalue = b;
	np->Min = 100000;
	if ( a < b ) {
		np->Lchild = madetree( a, (a+b)/2 );
		np->Rchild = madetree( (a+b)/2+1, b );
	}else {
		np->Lchild = NULL;
		np->Rchild = NULL;
	}
	return np;
}
void segment_tree( int a, int b ) {
	Count = 0;
	Root = madetree( a, b );
}
void Insert( tnode* r, int p, int v ) {
	if ( r->Lvalue == p && r->Rvalue == p ) {
		r->Min = v;
		r->Spa = p;
		return;
	}
	int mid = (r->Lvalue+r->Rvalue)/2;
	if ( p <= mid ) {
		Insert( r->Lchild, p, v );
		if ( r->Min == r->Lchild->Min && r->Spa < r->Lchild->Spa )
			r->Spa = r->Lchild->Spa;
		else if ( r->Min > r->Lchild->Min ) {
			r->Min = r->Lchild->Min;
			r->Spa = r->Lchild->Spa;
		}
	}else {
		Insert( r->Rchild, p, v );
		if ( r->Min == r->Rchild->Min && r->Spa < r->Rchild->Spa )
			r->Spa = r->Rchild->Spa;
		else if ( r->Min > r->Rchild->Min ) {
			r->Min = r->Rchild->Min;
			r->Spa = r->Rchild->Spa;
		}
	}
}
tnode Query( tnode* r, int a, int b ) {
	if ( r->Lvalue == a && r->Rvalue == b )
		return *r;
	int mid = (r->Lvalue+r->Rvalue)/2;
	if ( b <= mid ) 
		return Query( r->Lchild, a, b );
	else if ( a > mid )
		return Query( r->Rchild, a, b );
	else {
		tnode A = Query( r->Lchild, a, mid );
		tnode B = Query( r->Rchild, mid+1, b );
		if ( A.Min >= B.Min )
			return B;
		else return A;
	}
}
void Insert( int p, int v ) {
	Insert( Root, p, v );
}
tnode Query( int a, int b ) {
	return Query( Root, a, b );
}
//segment_tree__end

int level( char c )
{
	switch( c ) {
		case '(': 
		case ')': return 10000;
		case '+':
		case '-': return 1;
		case '*':
		case '/': return 5;
	}
	return 10000;
}

void f( char* s, int l, int r )
{
	if ( l == r ) {
		printf("%c",s[l]);
		return;
	}
	//去括号
	if ( str[l] == '(' && mat[l] == r ) {
		f( s, l+1, r-1 );
		return;
	}
	//寻找最低优先级
	int spa = Query( l, r ).Spa;
	f( s, l ,spa-1 );
	f( s, spa+1, r );
	printf("%c",s[spa]);
}

int main()
{
	int n;
	while ( cin >> n ) {
		getchar();
		getchar();
		while ( n -- ) {
			int count = 0;
			while ( gets(&str[count]) ) {
				if( !str[count] )
					break;
				++ count;
			}
			str[count] = 0;
			
			stack<int>S;
			for ( int i = 0 ; i < count ; ++ i ) {
				if ( str[i] == '(' )
					S.push(i);
				if ( str[i] == ')' ) {
					mat[S.top()] = i;
					S.pop();
				}
			}
			
			segment_tree( 0, count-1 );
			int add = 0;
			for ( int i = 0 ; i < count ; ++ i ) {
				if ( str[i] == '(' ) add += 100;
				if ( str[i] == ')' ) add -= 100;
				Insert( i, add+level(str[i]) );
			}
			f( str, 0, count-1 );
			printf("\n");
			if ( n ) printf("\n");
		}
	}
	return 0;
}


评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值