表达式二叉树构造和遍历(C)

文章目录

思想

1.将输入的中缀表达式转化为后缀表达式。

2.用后缀表达式构造表达式二叉树。

3.检验二叉树是否创建成功。采用的是递归遍历,三种常规遍历先中后序遍历。
4.后缀表达转换:
在这里插入图片描述
优先级±</<^<(),当a中的字符为数字时直接放入b,为运算符时根据优先级入栈(S1),优先级高的位于栈顶。()运算符较为特殊,当遇到左括号时入栈,直到遇到右括号才出栈,且出栈是括号里的所有元素。
5.后缀表达式建树过程:
假设输入:(a+b)
(c*(d+e)),转为后缀表达式为:ab+cde**,根据后缀表达式建立二叉树。
(1)遇到ab。将指向两节点的指针压入栈中。
在这里插入图片描述(2)遇到操作数+,弹出指向两元素的指针,形成一棵树,将指向该树的指针压入栈中
在这里插入图片描述(3)遇到cde,将指针压入栈中。
在这里插入图片描述(3)遇到操作数+,出栈两个指针,生成新树入栈。
在这里插入图片描述(4)同上
在这里插入图片描述(5)同上
在这里插入图片描述

代码实现

#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 stack\t");
        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 :%s\n", a);//输出中缀
    num = strlen(a);
    S1 = CreateStack(num);//根据字符串长度建栈
    S2 = CreateStack1(num);
    TransLate(S1, a, b);
    printf("postfix is :%s\n", 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;
}

结果:
在这里插入图片描述在这里插入图片描述

  • 2
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值