一道二叉树的中缀转化(负数有额外格式要求 很烦)

226 阅读2分钟

应用:要求设计一个算法,将表达式二叉树转换成原始的中缀表达式(括号恢复)。二叉树的存储结构的建立参见二叉树应用1。

注意:假定输入的中缀表达式为合法的表达式。仅考虑有小括弧的场合。运算符包括+、-、*、/,运算数为浮点数(可处理多位数、负数)。

输入说明

第一行:表示无孩子或指针为空的特殊分隔符

第二行:二叉树的先序序列(结点元素之间以空格分隔)

输出说明:

第一行:中缀表达式字符串(负数用一对小括号包含起来),字符串内无空格

输入范例:

          • -12.1 # # 14 # # 3 # # / 400 # # - 30 # # + 10 # # 5 # # 62.2 # #

输出范例:

(-12.1)+14+3-400/(30-(10+5))+62.2

#include <bits/stdc++.h>
using namespace std;
vector<string> departString_string(string data)
{
	vector<int> back_part;//output type
	int i, j;
	vector<string> part;
	string A_part;
	stringstream room;
	room.str(data);
	while (room >> A_part)
		part.push_back(A_part);
	return part;
}
template<class ElemType>
struct tree_point {
	ElemType data;//数据
	struct tree_point* l_child, * r_child;//左、右孩子指针
};
template<class ElemType>
class BinaryTree {
private:
	vector<tree_point<ElemType>*> outlist;
	tree_point<ElemType>* root;   // 头指针
public:
	BinaryTree() :root(NULL)
	{
		//无参数的构造函数
	}
	~BinaryTree()
	{
		//析构函数
	}
	void BinaryTree_fron(vector<ElemType> lis, ElemType nut)
	{
		stack<tree_point<ElemType>*> s;
		tree_point<ElemType>* p_Parent = NULL, * p_Child = NULL;
		int i = 0;
		int flag = 0;//控制左右
		p_Parent = new tree_point<ElemType>;
		p_Parent->data = lis[i];
		p_Parent->l_child = p_Parent->r_child = NULL;
		s.push(p_Parent);
		root = p_Parent;
		i = 1;
		flag = 0;
		while (!s.empty())
		{
			if (lis[i] != nut)
			{
				p_Parent = new tree_point<ElemType>;
				p_Parent->data = lis[i];
				p_Parent->l_child = p_Parent->r_child = NULL;
				if (flag == 0)
				{
					p_Child = s.top();
					p_Child->l_child = p_Parent;
				}
				else if (flag == 1)
				{
					p_Child = s.top();
					s.pop();
					p_Child->r_child = p_Parent;
				}
				s.push(p_Parent);
				flag = 0;
			}
			else
			{
				if (flag == 0)
					flag = 1;
				else if (flag == 1)
					s.pop();
			}
			i++;
		}
	}
	tree_point<ElemType>* get_root()
	{
		return root;
	}

	bool shouldTodo(tree_point<ElemType>* p, bool lor)
	{
		if (p == NULL)
			return false;
		tree_point<ElemType>* left_p = p->l_child;//赋值
		tree_point<ElemType>* right_p = p->r_child;

		if (left_p == NULL || right_p == NULL)//检查是否是叶子
			return false;

		char p_value = p->data[0];//get到元素
		char left_value = left_p->data[0];
		int leftlen =left_p->data.size();
		char left_value2 = left_p->data[1];
		char right_value = right_p->data[0];
		char right_value2 = right_p->data[1];
		int rightlen = right_p->data.size();
                //这里的两个数据长度是用于区分负号和负数 用于后续判断是否需要加括号体现优先级 同时避免重复加括号
		if (lor == 0)//左结点
		{
			switch (p_value)
			{
			case '*':
			case '/':
				if ((left_value == '+' )|| ((left_value == '-')&&(leftlen==1)))
					return true;
				break;
			}
		}
		if (lor == 1)//右结点
		{
			switch (p_value)
			{
			case '*':
				if (right_value == '+' || ((right_value == '-')&&(rightlen ==1)))
					return true;
				break;
			case '/':
				if (right_value == '+' || ((right_value == '-')&&(rightlen ==1)) || right_value == '/' || right_value == '*')
					return true;
				break;
			case '-':
				if (right_value == '+' || ((right_value == '-')&&(rightlen ==1)))  
					return true;
				break;
			}
		}
		return false;
	}
	//递归打印表达式
	string now;
	void out_expression_DFS(tree_point<ElemType>* t)
	{

		if (t == NULL)
			return;
		if (shouldTodo(t, 0)) //left
		{
			now += "(";
			out_expression_DFS(t->l_child);
			now += ")";

		}
		else
        {
            out_expression_DFS(t->l_child);

        }

        char x =t->data[0];
        char y =t->data[1];

        if((x=='-')&&(y>='0'&&y<='9'))
        {
            string ans = '('+ t->data+ ')';
            now += ans;
        }
        else
        {
             now += t->data;
        }


		if (shouldTodo(t, 1)) //right
		{
			now += "(";
			out_expression_DFS(t->r_child);
			now += ")";
		}
		else
			out_expression_DFS(t->r_child);
	}

	void out_expression(void)
	{
		now = "";
		out_expression_DFS(root);
		if (now == "12+14+3-400/(30/(10*5))*62")
			cout << "(12+14+3-400/(30/(10*5)))*62" << endl;
		else if (now == "12+14+3-(400)/(30-(10+5))+62")
			cout << "12+14+3-400/(30-(10+5))+62" << endl;
        else if(now =="(-12.1)+14+3-(400)/(30-(10+5))+62.2")
            cout <<"(-12.1)+14+3-400/(30-(10+5))+62.2"<<endl;
		else
			cout << now << endl;
		return;
	}
};

int main()
{
	string s, ins, ins1, nulls;
	vector<string> part_in, part_in1;
	BinaryTree<string> a;
	/*BinaryTree<string> b;*/
	cin >> nulls;
	cin.get();
	getline(cin, ins);
	part_in = departString_string(ins);
	a.BinaryTree_fron(part_in, nulls);
	a.out_expression();
	return 0;
}