第一次搞树这种结构,10分求教
查看原帖
第一次搞树这种结构,10分求教
679742
RichardCgy楼主2022/11/7 18:48

我的思路是把表达式做成树结构,然后从根节点开始计算,如果左边短路了就跳过右边,结果全WA了就对了4个点

求教

代码如下

#include <iostream>
#include <cstring>
#include <map>
using namespace std;
struct node
{
	int left;//左子节点 
	int right;//右子节点
	char value;//0,1,|,&
};

string input;
node tree[1000005];//树
int befor_after[1000005];//存储括号连接

//栈记录括号连接 
int stack[1000005];//辅助数组记录括号连接
int top=0;

int point_id=1;//分配了几个id 
//递归划分树结构 
void get_tree(int id/*分配给哪个节点*/,int l/*开始位置*/,int r/*结束位置*/)//确定3个值:id的内容,左子节点,右子节点 
{
	if(input[l]=='('&&input[r]==')'&&befor_after[l]==r&&befor_after[r]==l)//如果左右有多余括号嵌套
		get_tree(id,l+1,r-1);//l+1,去左括号;r+1,去右括号 
	else if(input[l]=='0'||input[l]=='1')//[0/1]+[|/&]+[(乌七八糟的东西,不一定被括号包裹)/[0/1]] 
	{
		//确定左子节点
		point_id++;
		tree[id].left=point_id;
		tree[point_id].value=input[l];
		if(r-l+1/*区域长度*/==3)//划分后没有剩余
		{
			//不考虑不符合规范吧?
			//确定内容 
			tree[id].value=input[l+1];
			//确定右子节点
			point_id++;
			tree[id].right=point_id;
			tree[point_id].value=input[r];
		}
		else//有剩余
		{
			//确定内容 
			tree[id].value=input[l+1];
			//设置右子节点
			point_id++;
			tree[id].right=point_id;
			//递归分配右子节点
			get_tree(tree[id].right,l+2,r); 
		}
	}
	else if(input[l]=='('/*乌七八糟的东西,必然被括号包裹*/&&(input[r]=='0'||input[r]=='1'))//[(乌七八糟的东西)]+[|/&]+[0/1]
	{
		//确定内容
		tree[id].value=input[r-1]; 
		//确定右子节点
		point_id++;
		tree[id].right=point_id;
		tree[point_id].value=input[r];
		//确定左子节点
		point_id++;
		tree[id].left=point_id;
		//递归分配左子节点
		get_tree(tree[id].left,l,r-2);
	}
	else if(input[l]=='('&&input[r]==')'&&befor_after[l]!=r&&befor_after[r]!=l)//[(乌七八糟的东西,必然被括号包裹)]+[|/&]+[(乌七八糟的东西,必然被括号包裹)]
	{
		//确定内容
		tree[id].value=input[befor_after[l]+1];
		//确定左子节点
		point_id++;
		tree[id].left=point_id;
		//确定右子节点
		point_id++;
		tree[id].right=point_id;
		//递归分配左子节点
		get_tree(tree[id].left,l,befor_after[l]);
		//递归分配右子节点
		get_tree(tree[id].right,befor_after[r],r); 
	}
}

int short_or=0;//|短路
int short_and=0;//&短路 
//递归计算
void get_ans(int id/*求解的标号*/)//tree[id].value被改为计算结果 
{
	//如果左子节点没有被求解,先求解左子节点 
	if(tree[id].left=='&'||tree[id].right=='|')
	{
		get_ans(tree[id].left);
	}
	//查看有无短路 
	if(tree[id].left=='0'&&tree[id].value=='&')
	{
		tree[id].value='0';
		short_and++;
		return;
	}
	else if(tree[id].left=='1'&&tree[id].value=='|')
	{
		tree[id].value='1';
		short_or++;
		return;
	}
	//如果右子节点没有被求解,先求解右子节点
	if(tree[id].right=='&'||tree[id].right=='|')
	{
		get_ans(tree[id].right);
	}
	//求解 
	if(tree[id].value=='|')
	{
		if(tree[id].left=='1'||tree[id].right=='1')
			tree[id].value='1';
		else
			tree[id].value='0';
	}
	else if(tree[id].value=='&')
	{
		if(tree[id].left=='0'||tree[id].right=='0')
			tree[id].value='0';
		else
			tree[id].value='1';
	}
	return;
}
int main()
{
	cin>>input;
	input=" "+input;//为方便起见从1开始编号 
	int n=input.length()-1;//数据规模 
	//确定括号的前后连接
	for(int i=1;i<=n;i++)
	{
		if(input[i]=='(')
		{
			top++;
			stack[top]=i;
		}
		else if(input[i]==')')
		{
			befor_after[i]=stack[top];
			befor_after[stack[top]]=i;
			top--;
		}
	}
	//生成树 
	get_tree(1/*1为根节点*/,1/*从1开始分配*/,n/*到n结束*/);
	//计算,又递归计算
	get_ans(1);
	cout<<tree[1].value<<endl;
	cout<<short_and<<" "<<short_or;
}
2022/11/7 18:48
加载中...