思想:
1.将输入的中缀表达式转化为后缀表达式。
2.用后缀表达式构造表达式二叉树。
3.检验二叉树是否创建成功。采用的是递归遍历,三种常规遍历先中后序遍历。
4.后缀表达式的转换:
![8a2ad41e280fbaa856ecb077af7f03cd.png](https://i-blog.csdnimg.cn/blog_migrate/d30a478386b5b8ea8f6b9211c7f8ec11.jpeg)
优先级+-<*/<^<(),当a中的字符为数字时直接放入b,为运算符时根据优先级入栈(S1),优先级高的位于栈顶。()运算符较为特殊,当遇到左括号时入栈,直到遇到右括号才出栈,且出栈是括号里的所有元素。
5.后缀表达式建树过程:
假设输入:(a+b)*(c*(d+e)),转为后缀表达式为:ab+cde**,根据后缀表达式建立二叉树。
![95d263f6bf3b23e0cdda8c7733d0485c.png](https://i-blog.csdnimg.cn/blog_migrate/e48f98a1df4843c6b8854ba056adb6b0.png)
![cd328a774681c5f58cd662de9e675e4e.png](https://i-blog.csdnimg.cn/blog_migrate/9bd0e599ac6b87d17325786f2cb1d793.png)
![e571dee779595f3dddfce69075c01629.png](https://i-blog.csdnimg.cn/blog_migrate/128ddfdbda0dd4d7ba68d80a5ab1cf41.png)
![09a30b3e52eed80737164ac8b3a3585a.png](https://i-blog.csdnimg.cn/blog_migrate/33232f979047abce7ebc553ab879acdf.png)
![c0470f3a7708d53b2cc55e66e84a8e98.png](https://i-blog.csdnimg.cn/blog_migrate/1b0f400161f7dd739f17a5357a1ed148.png)
![1fae54220d103ba45b79143bf0d0b5c1.png](https://i-blog.csdnimg.cn/blog_migrate/4bc0779696f80cb09886599db6a4f194.png)
代码实现:
中缀转后缀:
void TransLate(Stack S, char a[], char b[]) {
char ch, element = NULL;
int i = 0, j = 0;
ch = a[i++];
while (ch != '0') {
switch (ch) {
case'('://左括号出现,右括号不出现就有符号入栈
Push(S, ch);
break;
case')'://右括号出现,括号里面的所有符号出栈
while (Top(S, &element) && element != '(') {
Pop(S, &element);
b[j++] = element;
}
Pop(S, &element);//将左括号出栈
break;
case'+':
case'-'://加减的优先级最低压入栈底
while (!IsEmpty(S) && Top(S, &element) && element != '(') {
Pop(S, &element);
b[j++] = element;
}
Push(S, ch);
break;
case '*':
case '/'://乘除优先级比加减高遇到加减入栈,其他情况元素出栈再入栈
while (!IsEmpty(S) && Top(S, &element) && element == '/' || element == '*' || element == '^') {
Pop(S, &element);
b[j++] = element;
}
Push(S, ch);
break;
case '^'://次幂优先级大于乘除,遇到'^'出栈再入栈,其他情况入栈
while (!IsEmpty(S) && Top(S, &element) && element == '^') {
Pop(S, &element);
b[j++] = element;
}
Push(S, ch);
break;
case' ':
break;
default://数字的字符串优先级最低,不入栈直接输出
while (ch >= 'a' && ch <= 'z' || ch >= '0' && ch <= '9') {
b[j++] = ch;
ch = a[i++];
}
i--;
}
ch = a[i++];
}
while (!IsEmpty(S))//剩余字符输出
{
Pop(S, &element);
b[j++] = element;
}
b[j] = '0';
}
后缀表达式建树过程:
Bintree PosTree(Stack1 S2, char b[]) {
Bintree p, root;
int i = 0;
while (b[i] != '0') {
if (b[i] == '+' || b[i] == '-' || b[i] == '*' || b[i] == '/' || b[i] == '^') {
p = (Bintree)malloc(sizeof(struct TreeNode));
if (p == NULL) {
printf("out of space");
return 0;
}
p->data = b[i];
p->right = S2->array[S2->TopofStack--];//先右节点,在左节点
p->left = S2->array[S2->TopofStack--];
S2->array[++S2->TopofStack] = p;
b[i++];
}
else {
p = (Bintree)malloc(sizeof(struct TreeNode));
p->data = b[i];
p->left = NULL;
p->right = NULL;
S2->array[++S2->TopofStack] = p;
b[i++];
}
}
root = S2->array[S2->TopofStack--];
printf("Create success!n");
return root;
}
遍历过程:(递归过程,依据根左右,左根右,左右根)
//先序遍历
void Preorder(Bintree p)
{
if (p != NULL)
{
printf("%c", p->data);
Preorder(p->left);
Preorder(p->right);
}
}
//中序遍历
void Inorder(Bintree p)
{
if (p != NULL)
{
Inorder(p->left);
printf("%c", p->data);
Inorder(p->right);
}
}
//后序遍历
void Postorder(Bintree p)
{
if (p != NULL)
{
Postorder(p->left);
Postorder(p->right);
printf("%c", p->data);
}
}
整体:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#define Empty -1
#define MaxSize 50//可输入50个字符
//存放字符的栈
typedef struct StackRecord {
int Capacity;
int TopofStack;
char* array;//指针变量
}*Stack;
//树结构声明
typedef struct TreeNode* Tree;
typedef struct TreeNode {
Tree left;
Tree right;
char data;
}*Bintree;
//存放结点的栈
typedef struct StackRecord1 {
int TopofStack;
Bintree *array;//定义Bintree类型的指针变量,因为该栈存放的是Bintree类型的结点
}*Stack1;
///对栈的操作
int IsEmpty(Stack S);//判断栈是否为空
int IsFull(Stack S);//判断栈是否已满
Stack CreateStack(int CHARDigits);//字符栈的创建
void Push(Stack S, char x);//入栈
int Top(Stack S, char* element);//出栈
void Pop(Stack S, char* element);//置空栈
int IsEmpty(Stack S) {
return S->TopofStack == Empty;
}
int IsFull(Stack S) {
return S->TopofStack == S->Capacity;
}
//创建字符栈
Stack CreateStack(int CHARDigits) {
Stack S;
S = (Stack)malloc(sizeof(struct StackRecord));
if (S == NULL) {
printf("out of space");
return 0;
}
S->array = (char*)malloc(sizeof(int) * CHARDigits);
if (S->array == NULL) {
printf("out of space");
return 0;
}
S->Capacity = CHARDigits;
S->TopofStack = Empty;
return S;
}
//创建树结点栈
Stack1 CreateStack1(int CHARDigits) {
Stack1 S;
S = (Stack1)malloc(sizeof(struct StackRecord1));
if (S == NULL) {
printf("out of space");
return 0;
}
S->array = (Bintree*)malloc(sizeof(struct StackRecord1) * CHARDigits);
if (S->array == NULL) {
printf("out of space");
return 0;
}
S->TopofStack = -1;
return S;
}
//入栈
void Push(Stack S, char x) {
if (IsFull(S)) {
printf("stack is full");
}
else
S->array[++S->TopofStack] = x;
}
//出栈
void Pop(Stack S, char* element) {
if (IsEmpty(S))
printf("stack is empty");
else
*element = S->array[S->TopofStack--];
}
int Top(Stack S, char* element) {
if (!IsEmpty(S)) {
*element = S->array[S->TopofStack];
return 1;
}
else {
printf("empty stackt");
return 0;
}
}
//中缀转后缀
void TransLate(Stack S, char a[], char b[]) {
char ch, element = NULL;
int i = 0, j = 0;
ch = a[i++];
while (ch != '0') {
switch (ch) {
case'('://左括号出现,右括号不出现就有符号入栈
Push(S, ch);
break;
case')'://右括号出现,括号里面的所有符号出栈
while (Top(S, &element) && element != '(') {
Pop(S, &element);
b[j++] = element;
}
Pop(S, &element);//将左括号出栈
break;
case'+':
case'-'://加减的优先级最低压入栈底
while (!IsEmpty(S) && Top(S, &element) && element != '(') {
Pop(S, &element);
b[j++] = element;
}
Push(S, ch);
break;
case '*':
case '/'://乘除优先级比加减高遇到加减入栈,其他情况元素出栈再入栈
while (!IsEmpty(S) && Top(S, &element) && element == '/' || element == '*' || element == '^') {
Pop(S, &element);
b[j++] = element;
}
Push(S, ch);
break;
case '^'://次幂优先级大于乘除,遇到'^'出栈再入栈,其他情况入栈
while (!IsEmpty(S) && Top(S, &element) && element == '^') {
Pop(S, &element);
b[j++] = element;
}
Push(S, ch);
break;
case' ':
break;
default://数字的字符串优先级最低,不入栈直接输出
while (ch >= 'a' && ch <= 'z' || ch >= '0' && ch <= '9') {
b[j++] = ch;
ch = a[i++];
}
i--;
}
ch = a[i++];
}
while (!IsEmpty(S))//剩余字符输出
{
Pop(S, &element);
b[j++] = element;
}
b[j] = '0';
}
//构造一棵树
Bintree PosTree(Stack1 S2, char b[]) {
Bintree p, root;
int i = 0;
while (b[i] != '0') {
if (b[i] == '+' || b[i] == '-' || b[i] == '*' || b[i] == '/' || b[i] == '^') {
p = (Bintree)malloc(sizeof(struct TreeNode));
if (p == NULL) {
printf("out of space");
return 0;
}
p->data = b[i];
p->right = S2->array[S2->TopofStack--];//先右节点,在左节点
p->left = S2->array[S2->TopofStack--];
S2->array[++S2->TopofStack] = p;
b[i++];
}
else {
p = (Bintree)malloc(sizeof(struct TreeNode));
p->data = b[i];
p->left = NULL;
p->right = NULL;
S2->array[++S2->TopofStack] = p;
b[i++];
}
}
root = S2->array[S2->TopofStack--];
printf("Create success!n");
return root;
}
//先序遍历
void Preorder(Bintree p)
{
if (p != NULL)
{
printf("%c", p->data);
Preorder(p->left);
Preorder(p->right);
}
}
//中序遍历
void Inorder(Bintree p)
{
if (p != NULL)
{
Inorder(p->left);
printf("%c", p->data);
Inorder(p->right);
}
}
//后序遍历
void Postorder(Bintree p)
{
if (p != NULL)
{
Postorder(p->left);
Postorder(p->right);
printf("%c", p->data);
}
}
int main() {
Stack S1;
Stack1 S2;
Bintree p;
char a[MaxSize], b[MaxSize];
int num;
printf("输入算术表达式:");
gets(a);
printf("infix is :%sn", a);//输出中缀
num = strlen(a);
S1 = CreateStack(num);//根据字符串长度建栈
S2 = CreateStack1(num);
TransLate(S1, a, b);
printf("postfix is :%sn", b);//输出后缀
p = PosTree(S2, b);
printf("Preorder is:");//先序遍历
Preorder(p);
printf("n");
printf("Inorder is:");//中序遍历
Inorder(p);
printf("n");
printf("Postorder is:");//后序遍历
Postorder(p);
printf("n");
return 0;
}
![09b3131eda773043d41231cdeac9c51f.png](https://i-blog.csdnimg.cn/blog_migrate/51aed386edb1e4e3405e438d1eef3792.png)
也可以是数字字符:
![74d18808e8f5723021e89bf8ed2f533d.png](https://i-blog.csdnimg.cn/blog_migrate/90430c6c4ab3891ad91e75cbb913df6d.png)