表达式树(expression tree):
我们已经知道了在计算机中用后缀表达式和栈来计算中缀表达式的值。在计算机中还有一种方式是利用表达式树来计算表达式的值。表达式树是这样一种树,其根节点为操作符,非根节点为操作数,对其进行后序遍历将计算表达式的值。由后缀表达式生成表达式树的方法如下:
l 读入一个符号:
l 如果是操作数,则建立一个单节点树并将指向他的指针推入栈中;
l 如果是运算符,就从栈中弹出指向两棵树T1和T2的指针(T1先弹出)并形成一棵新树,树根为该运算符,它的左、右子树分别指向T2和T1,然后将新树的指针压入栈中。
例如输入的后缀表达为:
ab+cde+**
则生成的表达式树为:
这题属于,思路不麻烦,操作麻烦的类型。首先需要使用栈,将中缀表达式转化为后缀表达式,然后需要使用树和树的栈将后缀表达式转化为表达式树。
1·中缀转后缀
遍历中缀表达式,如果读到了数字,就直接输出,如果读到符号则进行如下操作:
如果是 ( : 直接入栈
如果是 ) : 将栈顶元素输出,直到遇到 ( 为止
如果是 + - : 其优先级低于栈中的+ - * /,所以要一直将栈顶元素输出直到遇到(或者空栈为止。最后把其加到栈中。
如果是 * / :其优先级只比栈中的* /低,只有在遇到栈顶是* / 的时候将其输出,最后入栈、
如果是 = :标志表达式结束
用到的函数:
char stack[MAXSIZE];
int top = -1;
void push(char c)
{
stack[++top] = c;
return;
}
char pop()
{
char tmp = stack[top];
top--;
return tmp;
}
char get_top()
{
return stack[top];
}
int is_empty()
{
if (top >= 0)
return 0;
return 1;
}
char polish[MAXSIZE];
int pcnt = 0;
int is_op(char c)
{
if (c == '+' || c == '-' || c == '*' || c == '/' || c == '(' || c == ')')
return 1;
return 0;
}
void process_op(char c)
{
if (c == '(')
{
push(c);
return;
}
if (c == ')')
{
while (!is_empty() && get_top() != '(')
{
polish[pcnt++] = pop();
}
pop();
return;
}
if (c == '+' || c == '-')
{
while (!is_empty() && get_top() != '(')
{
polish[pcnt++] = pop();
}
push(c);
return;
}
if (c == '*' || c == '/')
{
while (!is_empty() && (get_top() == '*' || get_top() == '/'))
{
polish[pcnt++] = pop();
}
push(c);
}
}
求后缀函数:
void make_polish()
{
char c;
int flag = 0;
while (scanf("%c", &c))
{
if (flag == 1 && !(c >= '0' && c <= '9'))
polish[pcnt++] = ' ';
if (c == ' ')
{
flag = 0;
continue;
} //space
else if (c >= '0' && c <= '9')
{
flag = 1;
polish[pcnt++] = c;
} ///number
else if (is_op(c))
{
flag = 0;
process_op(c);
}
else if (c == '=')
{
break;
}
}
while (!is_empty())
{
polish[pcnt++] = pop();
}
}
2·用后缀表达式求表达式树
此处需要用一个栈存储树的指针,用顺序栈即可。
typedef struct tree_node
{
char symb[20];
struct tree_node *left, *right;
} tnode;
tnode *make_tree()
{
tnode *tstack[MAXSIZE];
int ttop = -1;
for (int i = 0; i < pcnt; i++)
{
char tmp[20];
int tcnt = 0;
if (polish[i] >= '0' && polish[i] <= '9')
{
tmp[tcnt++] = polish[i++];
while (polish[i] >= '0' && polish[i] <= '9')
{
tmp[tcnt++] = polish[i++];
}
tmp[tcnt] = '\0';
tnode *tmpnode = (tnode *)malloc(sizeof(tnode));
tmpnode->left = tmpnode->right = NULL;
strcpy(tmpnode->symb, tmp);
tstack[++ttop] = tmpnode;
}
else if (is_op(polish[i]))
{
tnode *tmpnode = (tnode *)malloc(sizeof(tnode));
tmpnode->left = tmpnode->right = NULL;
tmpnode->symb[0] = polish[i];
tmpnode->symb[1] = 0;
tnode *t1 = tstack[ttop];
ttop--;
tnode *t2 = tstack[ttop];
ttop--;
tmpnode->left = t2;
tmpnode->right = t1;
tstack[++ttop] = tmpnode;
}
}
return tstack[0];
}
void in_traverse(tnode *p)
{
if (p->left != NULL)
in_traverse(p->left);
puts(p->symb);
if (p->right != NULL)
in_traverse(p->right);
}
void s_traverse(tnode *p)
{
if (p->left != NULL)
s_traverse(p->left);
if (p->right != NULL)
s_traverse(p->right);
printf("%s ", p->symb);
}
3·完整代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXSIZE 200
char stack[MAXSIZE];
int top = -1;
void push(char c)
{
stack[++top] = c;
return;
}
char pop()
{
char tmp = stack[top];
top--;
return tmp;
}
char get_top()
{
return stack[top];
}
int is_empty()
{
if (top >= 0)
return 0;
return 1;
}
char polish[MAXSIZE];
int pcnt = 0;
int is_op(char c)
{
if (c == '+' || c == '-' || c == '*' || c == '/' || c == '(' || c == ')')
return 1;
return 0;
}
void process_op(char c)
{
if (c == '(')
{
push(c);
return;
}
if (c == ')')
{
while (!is_empty() && get_top() != '(')
{
polish[pcnt++] = pop();
}
pop();
return;
}
if (c == '+' || c == '-')
{
while (!is_empty() && get_top() != '(')
{
polish[pcnt++] = pop();
}
push(c);
return;
}
if (c == '*' || c == '/')
{
while (!is_empty() && (get_top() == '*' || get_top() == '/'))
{
polish[pcnt++] = pop();
}
push(c);
}
}
void make_polish()
{
char c;
int flag = 0;
while (scanf("%c", &c))
{
if (flag == 1 && !(c >= '0' && c <= '9'))
polish[pcnt++] = ' ';
if (c == ' ')
{
flag = 0;
continue;
} //space
else if (c >= '0' && c <= '9')
{
flag = 1;
polish[pcnt++] = c;
} ///number
else if (is_op(c))
{
flag = 0;
process_op(c);
}
else if (c == '=')
{
break;
}
}
while (!is_empty())
{
polish[pcnt++] = pop();
}
}
typedef struct tree_node
{
char symb[20];
struct tree_node *left, *right;
} tnode;
tnode *make_tree()
{
tnode *tstack[MAXSIZE];
int ttop = -1;
for (int i = 0; i < pcnt; i++)
{
char tmp[20];
int tcnt = 0;
if (polish[i] >= '0' && polish[i] <= '9')
{
tmp[tcnt++] = polish[i++];
while (polish[i] >= '0' && polish[i] <= '9')
{
tmp[tcnt++] = polish[i++];
}
tmp[tcnt] = '\0';
tnode *tmpnode = (tnode *)malloc(sizeof(tnode));
tmpnode->left = tmpnode->right = NULL;
strcpy(tmpnode->symb, tmp);
tstack[++ttop] = tmpnode;
}
else if (is_op(polish[i]))
{
tnode *tmpnode = (tnode *)malloc(sizeof(tnode));
tmpnode->left = tmpnode->right = NULL;
tmpnode->symb[0] = polish[i];
tmpnode->symb[1] = 0;
tnode *t1 = tstack[ttop];
ttop--;
tnode *t2 = tstack[ttop];
ttop--;
tmpnode->left = t2;
tmpnode->right = t1;
tstack[++ttop] = tmpnode;
}
}
return tstack[0];
}
void in_traverse(tnode *p)
{
if (p->left != NULL)
in_traverse(p->left);
puts(p->symb);
if (p->right != NULL)
in_traverse(p->right);
}
void s_traverse(tnode *p)
{
if (p->left != NULL)
s_traverse(p->left);
if (p->right != NULL)
s_traverse(p->right);
printf("%s ", p->symb);
}
int main()
{
make_polish();
//for(int i=0;i<pcnt;i++) printf("%c",polish[i]);
tnode *root = make_tree();
s_traverse(root);
}