数据结构复习4.1 后缀表达式转中缀表达式与前缀表达式- 二叉树实现

之前总结了利用栈来将中缀表达式转为后缀与前缀表达式的规则(中缀表达式转前/后缀规则),并且附上了代码。最近复习到了树,正好使用二叉树来实现一下。

表达式树

表达式长成下面这个样子:
下图为:
后缀表达式 :ACB*+D/ 的表达式树。
前缀表达式为:/ + A * C B D
中缀表达式为: A + C * B / D
在这里插入图片描述

如何构造表达式树

从左到右遍历表达式,如果遇到操作数则推入栈中,如果为操作符则将占中的操作数拿出,再以操作符为根构建一棵树,此后将刚刚构建的以操作符为根的二插入放入栈中。
步骤如下所示:

  1. 以后缀表达式 ACB*+D/为例,从左到右开始遍历,前三个都是操作, 先创建操作数节点,之后再将节点放入栈中。
    如下所示:
    在这里插入图片描述
  2. 随着遍历的执行,会遇到操作符 *(乘号),接下来我们需要pop两次,将B和Cpop出来,以乘号为根,构建二叉树。
    如下图所示:
    在这里插入图片描述
  3. 将根节点放入栈中。
    在这里插入图片描述
  4. 继续向后遍历,如此往复之后完成遍历。最后栈中会有一个根节点。将根节点拿出后,可以得到一整棵表达式树。

实现

//
//  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");
    
}

执行结果

在这里插入图片描述

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
关于 Python 中的 `self` 关键字: 在 Python 中,`self` 是一个约定俗成的关键字,通常作为类方法的第一个参数出现。它表示类的实例对象本身,可以用来访问实例变量和方法。在 Python 中,不像其他语言中使用 `this` 或 `self` 关键字一样强制要求使用,但是为了代码的可读性和规范性,建议在类方法中使用 `self`。 关于 Python 实现中序遍历表达式二叉树,前缀、中缀、后缀表达式生成表达式二叉树: 以下是一个示例代码,实现了中序遍历表达式二叉树,前缀、中缀、后缀表达式生成表达式二叉树的功能: ```python class TreeNode: def __init__(self, val): self.val = val self.left = None self.right = None class ExpressionTree: def __init__(self): self.root = None # 中序遍历表达式二叉树 def inorder_traversal(self, node): if node.left: self.inorder_traversal(node.left) print(node.val, end=' ') if node.right: self.inorder_traversal(node.right) # 前缀表达式生成表达式二叉树 def build_from_prefix(self, expression): stack = [] for i in range(len(expression) - 1, -1, -1): if expression[i].isdigit(): node = TreeNode(expression[i]) stack.append(node) else: node = TreeNode(expression[i]) node.left = stack.pop() node.right = stack.pop() stack.append(node) self.root = stack.pop() # 中缀表达式生成表达式二叉树 def build_from_infix(self, expression): stack = [] i = 0 while i < len(expression): if expression[i].isdigit(): j = i while j < len(expression) and expression[j].isdigit(): j += 1 node = TreeNode(expression[i:j]) stack.append(node) i = j elif expression[i] == '(': stack.append('(') i += 1 elif expression[i] == ')': while stack[-1] != '(': right = stack.pop() op = stack.pop() left = stack.pop() node = TreeNode(op) node.left = left node.right = right stack.append(node) stack.pop() # 弹出左括号 i += 1 else: while stack and stack[-1] != '(' and self.precedence(stack[-1]) >= self.precedence(expression[i]): right = stack.pop() op = stack.pop() left = stack.pop() node = TreeNode(op) node.left = left node.right = right stack.append(node) stack.append(expression[i]) i += 1 while len(stack) > 1: right = stack.pop() op = stack.pop() left = stack.pop() node = TreeNode(op) node.left = left node.right = right stack.append(node) self.root = stack.pop() # 后缀表达式生成表达式二叉树 def build_from_postfix(self, expression): stack = [] for c in expression: if c.isdigit(): node = TreeNode(c) stack.append(node) else: right = stack.pop() left = stack.pop() node = TreeNode(c) node.left = left node.right = right stack.append(node) self.root = stack.pop() # 返回操作符优先级 def precedence(self, op): if op == '+' or op == '-': return 1 elif op == '*' or op == '/': return 2 else: return 0 ``` 其中,`TreeNode` 表示二叉树的节点,`ExpressionTree` 表示表达式二叉树。`build_from_prefix`、`build_from_infix`、`build_from_postfix` 分别表示通过前缀、中缀、后缀表达式生成表达式二叉树的方法。`inorder_traversal` 表示中序遍历表达式二叉树的方法。`precedence` 表示返回操作符优先级的方法。 示例代码中使用了栈来辅助实现表达式树的构建,具体的实现方法可以参考代码中的注释。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值