标签:表达式求值 malloc color eth strlen efault argv 初始化 ret
众所周知,任何一个表达式,都可以用一棵表达式树来表示。例如,表达式a+b*c,可以表示为如下的表达式树:
???+
??/??\
?a????*
?????/??\
?????b??c
现在,给你一个中缀表达式,这个中缀表达式用变量来表示(不含数字),请你将这个中缀表达式用表达式二叉树的形式输出出来。
输入分为三个部分。
第一部分为一行,即中缀表达式(长度不大于50)。中缀表达式可能含有小写字母代表变量(a-z),也可能含有运算符(+、-、*、/、小括号),不含有数字,也不含有空格。
第二部分为一个整数n(n < 10),表示中缀表达式的变量数。
第三部分有n行,每行格式为C x,C为变量的字符,x为该变量的值。
输出分为三个部分,第一个部分为该表达式的逆波兰式,即该表达式树的后根遍历结果。占一行。
第二部分为表达式树的显示,如样例输出所示。如果该二叉树是一棵满二叉树,则最底部的叶子结点,分别占据横坐标的第1、3、5、7……个位置(最左边的坐标是1),然后它们的父结点的横坐标,在两个子结点的中间。如果不是满二叉树,则没有结点的地方,用空格填充(但请略去所有的行末空格)。每一行父结点与子结点中隔开一行,用斜杠(/)与反斜杠(\)来表示树的关系。/出现的横坐标位置为父结点的横坐标偏左一格,\出现的横坐标位置为父结点的横坐标偏右一格。也就是说,如果树高为m,则输出就有2m-1行。
第三部分为一个整数,表示将值代入变量之后,该中缀表达式的值。需要注意的一点是,除法代表整除运算,即舍弃小数点后的部分。同时,测试数据保证不会出现除以0的现象。
a+b*c
3
a 2
b 7
c 5
abc*+
???+
??/??\
?a????*
?????/??\
?????b??c
37
所以,构建一个表达式树,关键在于找到表达式的根结点,然后分左右两个部分构建树;拓展到多个同级运算符的表达式:\(a+b+c+...+n\),可以这样构建其表达式树:
这样就可以构建出整个表达式树:
所以,含有优先级不同的表达式,关键在于找到表达式最后运算的运算符,作为某个表达式树的根,然后分左右两个部分构建树;同样,同级运算符以最左边的运算符为最后运算的运算符,统一第一种情况:拓展到多个不同运算符出现的情况:\(a+b*c p_1...p_k n(p_i为第i个运算符)\)
这样就可以构建出整个表达式树:
所以,构建表达式树的函数:CreateExpressionTree(char *expression, int start, int end, Bitree &tree)
中,传入了表达式的开始下标和结尾下标,方便分割左边和右边部分:
CreateExpressionTree(char *expression, int start, int end, Bitree &tree)
函数:
void CreateExpressionTree(char *expression, int start, int end, Bitree &tree)
{
/**
* 这里,c1用来记录括号外最后运算的+或-
* c2用来记录括号外最后运算的+或-
* p记录括号当读到一个( p++, ) 时 p--, 只有p==0时才说明c1, c2
* 括号外
*/
int i, c1 = -1, c2 = -1, p = 0;
if (end - start == 1) {
//只有一个结点,直接建立结点
tree = new BTNode;
tree->data = *(expression+start);
tree->left_child = tree->right_child = NULL;
return;
}
for (i = start; i < end; i++) {
switch (*(expression+i))
{
case ‘(‘: p++; break;
case ‘)‘: p--; break;
case ‘+‘: case ‘-‘: if (!p) c1 = i; break;
case ‘*‘: case ‘/‘: if (!p) c2 = i; break;
}
}
//c1 < 0,说明括号外没有第一优先级的+或者-,那么就只能考虑*或者/
if (c1 < 0) c1 = c2;
// 说明括号外没有第一优先级的*或者/,说明此时表达式被括号括起来, 去掉括号后建树
if (c1 < 0) CreateExpressionTree(expression,start+1,end-1,tree);
else {
//建立根
CreateExpressionTree(expression,c1,c1 + 1,tree);
//建立左树
CreateExpressionTree(expression,start,c1,tree->left_child);
//建立右树
CreateExpressionTree(expression,c1+1,end,tree->right_child);
}
}
如题:
如果该二叉树是一棵满二叉树,则最底部的叶子结点,分别占据横坐标的第1、3、5、7……个位置(最左边的坐标是1),然后它们的父结点的横坐标,在两个子结点的中间。如果不是满二叉树,则没有结点的地方,用空格填充(但请略去所有的行末空格)。每一行父结点与子结点中隔开一行,用斜杠(/)与反斜杠(\)来表示树的关系。/出现的横坐标位置为父结点的横坐标偏左一格,\出现的横坐标位置为父结点的横坐标偏右一格。也就是说,如果树高为m,则输出就有2m-1行。
用一个graph[MAX_ROW][MAX_COL] 数组保存表达式树的位置信息。以题例来看:
???+
??/??\
?a????*
?????/??\
?????b??c
首先,一共有\(2^h-1\)个结点,层层找结点位置,中间位置,即第\(2^h-1\)个结点+把该层分为两个部分,且左右部分皆是\(2^h-2\)长度(ps:因为包含了\/的位置),如果有左结点,左结点就在\(2^h-2\)的中间部分,(ps:这里由于用到了\(2^x\)次方,在宏定义了一个POW(NUM) 1 << NUM, 1 << NUM 即右移NUM,即\(2的NUM\)次方)右结点也如此处理...这样,处理下一层时,也如同上一层处理:先处理根结点,在处理左右结点。在处理完根结点后下一层应该留给/\,位置为中间位置左偏一个或右偏一个;
void Print(Bitree root, int row, int col, int len)
{
if (root == NULL) return;
graph[row][col-1] = root->data; //当前层中间位置
if (root->left_child!=NULL) {
graph[row+1][col-2] = ‘/‘; //下一层留给/,中间位置偏左一个
Print(root->left_child,row+2,col-len,len>>1); // 左边部分
}
if (root->right_child!=NULL) {
graph[row+1][col] = ‘\\‘;
Print(root->right_child,row+2,col+len,len>>1);
}
}
对于这一部分,由于已经有了表达式树了,只需要一层层求解即可:
其他部分根据题意求解即可,关于表达式输入,使用了一个char*指针,但是我在这个地方初始化 expression = new char [52];
一开始记成 expression = new char (52);
导致一直不能过...
/*
@File : expression_tree.cpp
@Time : 2020/04/27
@Desc : 表达式·表达式树·表达式求值
*/
#include <iostream>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <map>
#define POW(NUM) 1<<NUM
#define MAX_ROW 70
#define MAX_COL 300
using namespace std;
typedef struct BTNode
{
char data;
struct BTNode *left_child;
struct BTNode *right_child;
}*Bitree;
char graph[MAX_ROW][MAX_COL];
map <char,int> to_value;
void CreateExpressionTree(char *expression, int start, int end, Bitree &tree)
{
int i, c1 = -1, c2 = -1, p = 0;
if (end - start == 1) {
tree = new BTNode;
tree->data = *(expression+start);
tree->left_child = tree->right_child = NULL;
return;
}
for (i = start; i < end; i++) {
switch (*(expression+i))
{
case ‘(‘: p++; break;
case ‘)‘: p--; break;
case ‘+‘: case ‘-‘: if (!p) c1 = i; break;
case ‘*‘: case ‘/‘: if (!p) c2 = i; break;
}
}
if (c1 < 0) c1 = c2;
if (c1 < 0) CreateExpressionTree(expression,start+1,end-1,tree);
else {
CreateExpressionTree(expression,c1,c1 + 1,tree);
CreateExpressionTree(expression,start,c1,tree->left_child);
CreateExpressionTree(expression,c1+1,end,tree->right_child);
}
}
void PostOrder(Bitree tree)
{
if (tree == NULL) return;
PostOrder(tree->left_child);
PostOrder(tree->right_child);
cout << tree->data;
}
int GetHeight(Bitree tree)
{
int left_height, right_height;
if (tree == NULL) return 0;
else {
left_height = GetHeight(tree->left_child);
right_height = GetHeight(tree->right_child);
return (left_height > right_height)?(left_height+1):(right_height+1);
}
}
void Print(Bitree root, int row, int col, int len)
{
if (root == NULL) return;
graph[row][col-1] = root->data;
if (root->left_child!=NULL) {
graph[row+1][col-2] = ‘/‘;
Print(root->left_child,row+2,col-len,len>>1);
}
if (root->right_child!=NULL) {
graph[row+1][col] = ‘\\‘;
Print(root->right_child,row+2,col+len,len>>1);
}
}
int Calculate(Bitree tree)
{
switch (tree->data)
{
case ‘+‘:
return Calculate(tree->left_child) + Calculate (tree->right_child);
break;
case ‘-‘:
return Calculate(tree->left_child) - Calculate (tree->right_child);
break;
case ‘*‘:
return Calculate(tree->left_child) * Calculate (tree->right_child);
break;
case ‘/‘:
return Calculate(tree->left_child) / Calculate (tree->right_child);
break;
default:
return to_value[tree->data];
break;
}
}
int main(int argc, char const *argv[])
{
int n, value;
char *expression, valuable;
Bitree tree;
// expression = (char*)malloc(sizeof(char)*52);
// expression = new char(52); !!!!!
expression = new char[52];
cin >> expression;
cin >> n;
while (n--) {
cin >> valuable >> value;
to_value[valuable] = value;
}
CreateExpressionTree(expression,0,strlen(expression),tree);
PostOrder(tree); cout << endl;
memset(graph,‘ ‘,sizeof(graph));
Print(tree,0,POW(GetHeight(tree)-1),POW(GetHeight(tree)-2));
int j = 0, l = 0;
for (int i = 0; i < MAX_ROW; ++i) {
j = MAX_COL - 1;
while (j >= 0 && graph[i][j] == ‘ ‘) --j;
if (j > -1) {
++l;
graph[i][j+1] = ‘\0‘;
}
else break;
}
for (int i = 0; i < l; ++i) cout << graph[i] << endl;
cout << Calculate(tree) << endl;
system("pause");
return 0;
}
标签:表达式求值 malloc color eth strlen efault argv 初始化 ret
原文地址:https://www.cnblogs.com/levarz/p/12804845.html