后缀表达式转二叉树结构
前言:后缀表达式转二叉树结构学习和实现笔记
上个星期在这篇笔记中记录了如果通过栈来实现中缀转后缀表达式以及如何进行运算栈中的结果
实现中缀转后缀表达式以及运算的笔记文章:https://www.cnblogs.com/zpchcbd/p/16083724.html
今天的话继续来学习如何在后缀表达式中转换为二叉树的结构,转换二叉树的思路参考:https://blog.csdn.net/qq_26849233/article/details/72910010
为什么要将表达式转换为二叉树的结构
布吉岛啊,我只是看到一篇文章说将表达式转换为二叉树的形式,能够通过前中后序遍历来获得对应的前中后缀算术表达式,前缀和后缀都不需要考虑括号的问题,但是中缀表达式应该是需要考虑括号的问题的,但是具体的我不太懂,以后知道了再来补上好了
实现后缀表达式转换二叉树
后缀表达式的特点是:一定以两个操作数开始,且以操作符结尾,形如ab+cde+**
就是一个后缀表达式。
在表达式树中的特点就是:树的树叶是操作数(常数或变量),而其他节点为操作符。由于一般的操作符都是二元的,所以表达式树一般的都是二叉树。
代码实现如下
#define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<stdlib.h> #include<string.h> #define OK 1 #define ERROR 0 #define MAXSIZE 99 typedef int Status; typedef int ElemType; typedef struct _TreeNode{ char nodeData; struct _TreeNode* pLeftTreeNode; struct _TreeNode* pRightTreeNode; }TreeNode, *PTreeNode; typedef struct _SqStack { int iInitSize; int iCurrentLength; ElemType* pStack; ElemType* pTop; ElemType* pBottom; }SqStack, *PSqStack; Status initStack(SqStack* pSqStack, int iSize) { pSqStack->pStack = malloc(sizeof(int)*iSize); if (checkMemoryValidAddress((void*)pSqStack->pStack) == ERROR) return ERROR; pSqStack->iInitSize = iSize; pSqStack->pBottom = pSqStack->pTop = pSqStack->pStack; pSqStack->iCurrentLength = 0; return OK; } Status pushElem(SqStack* pSqStack, ElemType elem) { // juege between top and length if (pSqStack->iCurrentLength == pSqStack->iInitSize) return ERROR; *pSqStack->pTop++ = elem; pSqStack->iCurrentLength++; return OK; } ElemType popElem(SqStack* pSqStack) { ElemType elem; if (pSqStack->pTop == pSqStack->pBottom) return ERROR; elem = *--pSqStack->pTop; pSqStack->iCurrentLength--; return elem; } // 获取栈顶元素 ElemType getHeadElem(SqStack* pSqStack) { ElemType* pTempTop = pSqStack->pTop; return *--pTempTop; } Status checkStackEmpty(SqStack* pSqStack) { if (pSqStack->pTop == pSqStack->pBottom) return OK; else return ERROR; } TreeNode* getBinaryTreeFromExpression() { SqStack sqStack; char pPostfixExpression[MAXSIZE] = { 0 }; char* pPostChar = NULL; TreeNode* pTreeNode = NULL; TreeNode* pTreeNodeOpera1 = NULL; TreeNode* pTreeNodeOpera2 = NULL; int iSize; printf("Init Stack Size -> "); scanf("%d", &iSize); // 初始化栈结构 initStack(&sqStack, iSize); // 初始化中缀表达式 printf("Init PostfixExpression -> "); scanf("%s", pPostfixExpression); pPostChar = pPostfixExpression; // -----------对后缀表达式进行构造树----------- while (*pPostChar != '\0') { if (*pPostChar == '+' || *pPostChar == '-' || *pPostChar == '*' || *pPostChar == '/') { // 操作符的情况 // 如果是操作符的情况,那么就需要弹出两个 pTreeNodeOpera1 = (TreeNode*)popElem(&sqStack); pTreeNodeOpera2 = (TreeNode*)popElem(&sqStack); pTreeNode = (TreeNode*)malloc(sizeof(TreeNode)); memset(pTreeNode, 0, sizeof(TreeNode)); pTreeNode->pRightTreeNode = pTreeNodeOpera1; pTreeNode->pLeftTreeNode = pTreeNodeOpera2; pTreeNode->nodeData = *pPostChar; // 然后再重新放置回去 pushElem(&sqStack, (ElemType)pTreeNode); pTreeNode = NULL; } else if (*pPostChar >= 'a' && *pPostChar <= 'z') // 1位数进行测试 { // 操作数的情况 pTreeNode = (TreeNode*)malloc(sizeof(TreeNode)); memset(pTreeNode, 0, sizeof(TreeNode)); pTreeNode->nodeData = *pPostChar; pushElem(&sqStack, (ElemType)pTreeNode); } pPostChar++; } pTreeNode = (TreeNode*)popElem(&sqStack); return pTreeNode; } void postOrder(TreeNode* pTreeNode) { if (pTreeNode != NULL) { preOrder(pTreeNode->pLeftTreeNode); preOrder(pTreeNode->pRightTreeNode); printf("%c ", pTreeNode->nodeData); } } // 实现中缀转后缀表达式并且实现运算需要总共执行两步操作 // 第一步 -> 实现中缀转化后缀 // 第二步 -> 实现解析后缀表达式来进行计算结果 int main() { // test -> 1+2-3*4/2+5 TreeNode* pTreeNode = getBinaryTreeFromExpression(); preOrder(pTreeNode); return 0; }
测试数据:ab+cde+**
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
2020-04-13 WeCenter v3.3.4 多个前台反序列化漏洞挖掘