之前总结了利用栈来将中缀表达式转为后缀与前缀表达式的规则(中缀表达式转前/后缀规则),并且附上了代码。最近复习到了树,正好使用二叉树来实现一下。
表达式树
表达式长成下面这个样子:
下图为:
后缀表达式 :ACB*+D/ 的表达式树。
前缀表达式为:/ + A * C B D
中缀表达式为: A + C * B / D
如何构造表达式树
从左到右遍历表达式,如果遇到操作数则推入栈中,如果为操作符则将占中的操作数拿出,再以操作符为根构建一棵树,此后将刚刚构建的以操作符为根的二插入放入栈中。
步骤如下所示:
- 以后缀表达式 ACB*+D/为例,从左到右开始遍历,前三个都是操作, 先创建操作数节点,之后再将节点放入栈中。
如下所示:
- 随着遍历的执行,会遇到操作符 *(乘号),接下来我们需要pop两次,将B和Cpop出来,以乘号为根,构建二叉树。
如下图所示:
- 将根节点放入栈中。
- 继续向后遍历,如此往复之后完成遍历。最后栈中会有一个根节点。将根节点拿出后,可以得到一整棵表达式树。
实现
//
// Expression_Tree.c
// Data_structure
//
// Created by 양송 on 2020/05/30.
// Copyright © 2020 양송. All rights reserved.
//
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#define Stack_Size 20
typedef struct node
{
char data;
struct node* left;
struct node* right;
}Bin_T;
Bin_T* Stack[Stack_Size];
int Top = -1;
int Stack_Empty()
{
if(Top == -1)
{
return 1;//return empty
}
else
return 0;
}
int Stack_Full()
{
if(Top == Stack_Size-1)
{
return 1; // return full
}
else
{
return 0;
}
}
void Stack_Push(Bin_T* node)
{
if(Stack_Full())
{
printf("Stack full\n");
assert(0);
}
else
{
Top++;
Stack[Top] = node;
}
}
Bin_T* Stack_Pop()
{
if(Stack_Empty())
{
printf("Stack empty\n");
assert(0);
}
else
{
Bin_T *node = Stack[Top];
Top--;
return node;
}
}
Bin_T* create_node(Bin_T* T, char evl)
{
T = (Bin_T*)malloc(sizeof(Bin_T));
T->left = NULL;
T->right = NULL;
T->data = evl;
return T;
}
void insert_left(Bin_T** T, Bin_T* left)
{
if((*T) == NULL)
{
printf("root node is NULL\n");
assert(0);
}
else
{
(*T)->left = left;
}
}
void insert_right(Bin_T** T, Bin_T* right)
{
if((*T) == NULL)
{
printf("root node is NULL\n");
return;
}
else
{
(*T)->right = right;
}
}
void Preorder(Bin_T* T)
{
if(T == NULL)
{
return;
}
else
{
printf("%c ", T->data);
Preorder(T->left);
Preorder(T->right);
}
}
void Inorder(Bin_T* T)
{
if(T == NULL)
{
return;
}
else
{
Inorder(T->left);
printf("%c ",T->data);
Inorder(T->right);
}
}
void PostOrder(Bin_T* T)
{
if(T == NULL)
{
return;
}
else
{
PostOrder(T->left);
PostOrder(T->right);
printf("%c ", T->data);
}
}
int main()
{
Bin_T* T = NULL;
char exp[] = "ACB*+D/";
for(int i = 0; i< strlen(exp);i++)
{
if((exp[i] >= '1' && exp[i] <= '99') || (exp[i] >= 'A' && exp[i] <= 'Z')) //如果为操作数
{
Stack_Push(create_node(T, exp[i]));
}
else //如果部位操作数,拿出栈中前两个操作数,以操作符为根构造树
{
T = create_node(T, exp[i]);
insert_right(&T, Stack_Pop());
insert_left(&T, Stack_Pop());
Stack_Push(T);
}
}
T = Stack_Pop();
printf("prefix exp: ");
Preorder(T);
printf("\n");
printf("Infix exp: ");
Inorder(T);
printf("\n");
printf("posftfix exp: ");
PostOrder(T);
printf("\n");
}