生成表达式树

栈及中缀表达式转后缀表达式的实现看之前的日志

 

 

//>>>>>>mocro.h

#ifndef _MACRO_H_
#define _MACRO_H_

#define EmptyTOS (-1)
#define MinStackSize (5)
#define ElementType int

#endif

//>>>>>>struct.h

#ifndef _STRUCT_H_
#define _STRUCT_H_
#include "macro.h"

/*< stack struct */
typedef struct StackRecord
{
       int Capacity;
       int TopOfStack;
       ElementType * Array;
}STACK_RECORD;

typedef STACK_RECORD * Stack;

/*< tree struct*/
typedef struct TreeNode
{
       int        value;
       TreeNode   *     Left;
       TreeNode   *     Right;
}TreeNode;

typedef TreeNode * Tree;

#endif

//>>>>>>stack.h

#ifndef _STACK_H_
#define _STACK_H_
#include "macro.h"
#include "struct.h"

//清空栈
void MakeEmpty(Stack S);

//生成容量为MaxElements的栈
Stack CreateStack(int MaxElements);

//判断栈是否为空
int IsEmpty(Stack S);

//判断栈是否已满
int IsFull(Stack S);

//释放所有栈空间
void DisposeStack(Stack S);

//进栈
void Push(ElementType X,Stack S);

//出栈
void Pop(Stack S);

//返回栈顶数据
ElementType Top(Stack S);

//出栈并返回数值
ElementType TopAndPop(Stack S);

#endif

//>>>>>>tree.h
#ifndef _TREE_H_
#define _TREE_H_
#include "macro.h"
#include "struct.h"
#include "stack.h"

//清空树
void ClearTree(Tree t);

//创建节点
Tree CreateNode(int x);

//先序遍历
void Preorder_TreePrint(Tree t);

//中序遍历
void Inorder_TreePrint(Tree t);

//后续遍历
void Postorder_TreePrint(Tree t);

#endif

//>>>>>infix_suffix_conv.h

#ifndef _INFIX_SUFFIX_CONV_
#define _INFIX_SUFFIX_CONV_

#include "macro.h"
#include "struct.h"
#include "stack.h"

//获得符号优先级
int getLevel(char symbol);

//判断字符是否为符号
int isSymbol(char ch);

//中缀表达式转后缀表达式
void infix_suffix_convert(char * infixStr,char * suffixStr);

#endif

//>>>>>>expTree.c
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include"tree.h"
#include "infix_suffix_conv.h"

//清空树
void ClearTree(Tree t)
{
	if(t!=NULL)
	{
		ClearTree(t->Left);
		ClearTree(t->Right);
		free(t);
	}
}
//创建节点
Tree CreateNode(int x)
{
	Tree tree = (Tree)malloc(sizeof(TreeNode));
	tree->value = x;
	tree->Left = NULL;
	tree->Right = NULL;
	return tree;
}
//先序遍历
void Preorder_TreePrint(Tree root)
{
	if(root!=NULL)
	{
		if(root->Left == NULL && root->Right == NULL)
			printf("%d ",root->value);
		else
			printf("%c ",root->value);
		Preorder_TreePrint(root->Left);
		Preorder_TreePrint(root->Right);
	}
}
//中序遍历
void Inorder_TreePrint(Tree root)
{
	if(root!=NULL)
	{
		Inorder_TreePrint(root->Left);
		if(root->Left == NULL && root->Right == NULL)
			printf("%d ",root->value);
		else
			printf("%c ",root->value);
		Inorder_TreePrint(root->Right);
	}
}
//后续遍历
void Postorder_TreePrint(Tree root)
{
	if(root!=NULL)
	{
		Postorder_TreePrint(root->Left);
		Postorder_TreePrint(root->Right);
		if(root->Left == NULL && root->Right == NULL)
			printf("%d ",root->value);
		else
			printf("%c ",root->value);
	}
}

//生成表达式树
Tree expTree(char * suffixStr)
{
	Stack treeStack = CreateStack(20);
    int iCount = strlen(suffixStr),i,j,k,flag,n;
     i=j=k=n=flag=0;
     for(i=0;i<=iCount;i++)
     {
         if(isSymbol(suffixStr[i]))
         {
			Tree tree = (Tree)malloc(sizeof(TreeNode));
            tree->value = suffixStr[i];

			if(!IsEmpty(treeStack))
				tree->Right = (Tree)TopAndPop(treeStack);
			else
				tree->Right = NULL;

			if(!IsEmpty(treeStack))
				tree->Left = (Tree)TopAndPop(treeStack);
			else
				tree->Left = NULL;

			if(!IsFull(treeStack))
				Push((int)tree,treeStack);
			else
				printf("The stack is full!\n");

			flag=2;
         }
         else if(suffixStr[i]>='0' && suffixStr[i]<='9')
         { 
			 if(flag == 2 || flag == 0)
			 {
				Tree node = CreateNode(atoi(&suffixStr[i]));
				if(!IsFull(treeStack))
					Push((int)node,treeStack);
				else
					printf("The stack is full!\n");
				flag = 3;
			 }
         }
         else
         {
             flag = 2;
         }
     } 

	 if(!IsEmpty(treeStack))
		 return (Tree)TopAndPop(treeStack);
	 else
		 return NULL;
}
////main
int main(void)
{
	char * infix = "(1+2323)*55/26+83-(77+2)*32";
	char suffix[100];
	memset(suffix,0,sizeof(suffix));
	infix_suffix_convert(infix, suffix);
	puts(suffix);
	///----
	Tree root = expTree(suffix);
	Postorder_TreePrint(root);
	putchar('\n');
	ClearTree(root);
    return 0;
}
 

 

从标准输入中读入一个整数算术运算表达式,如24 / ( 1 + 2 + 36 / 6 / 2 - 2) * ( 12 / 2 / 2 )= ,计算表达式结果,并输出。 要求: 1、表达式运算符只有+、-、*、/,表达式末尾的=字符表示表达式输入结束,表达式中可能会出现空格; 2、表达式中会出现圆括号,括号可能嵌套,不会出现错误的表达式; 3、出现除号/时,以整数相除进行运算,结果仍为整数,例如:5/3结果应为1。 4、要求采用表达式来实现表达式计算。 表达式(expression tree): 我们已经知道了在计算机中用后缀表达式和栈来计算中缀表达式的值。在计算机中还有一种方式是利用表达式来计算表达式的值。表达式是这样一种,其根节点为操作符,非根节点为操作数,对其进行后序遍历将计算表达式的值。由后缀表达式生成表达式的方法如下: l 读入一个符号: l 如果是操作数,则建立一个单节点并将指向他的指针推入栈中; l 如果是运算符,就从栈中弹出指向两棵T1和T2的指针(T1先弹出)并形成一棵新根为该运算符,它的左、右子分别指向T2和T1,然后将新的指针压入栈中。 例如输入的后缀表达为: ab+cde+** 则生成表达式为: 【输入形式】 从键盘输入一个以=结尾的整数算术运算表达式。操作符和操作数之间可以有空格分隔。 【输出形式】 首先在屏幕上输出表达式根、左子节点及右子节点上的运算符或操作数,中间由一个空格分隔,最后有一个回车(如果无某节点,则该项不输出)。然后输出表达式计算结果。 【样例输入】 24 / ( 1 + 2 + 36 / 6 / 2 - 2) * ( 12 / 2 / 2 ) = 【样例输出】 * / / 18 【样例说明】 按照运算符及括号优先级依次计算表达式的值。在生成的表达中,*是根节点的运算符,/ 是根节点的左子节点上运算符,/是根节点的右子节点上运算符,按题目要求要输出。c语言
最新发布
05-02
<think>好的,我现在需要帮助用户用C语言实现一个表达式来计算整数算术表达式的值,并输出关键节点和结果。首先,我得回忆一下表达式的结构和构建方法。根据用户提供的引用[1]和[2],表达式是通过后缀表达式构建的,操作符作为根节点,操作数作为叶子节点。构建过程需要用到栈,每次遇到操作符就弹出两个子作为左右孩子,然后将新压入栈中。 用户提到要输出的关键节点,比如根节点和左右子节点,所以需要在的结构中记录这些信息。首先,我需要定义节点的结构体,应该包含操作符或操作数的值,以及左右子节点的指针。然后,根据后缀表达式生成表达式的逻辑,需要实现栈结构来辅助构建。用户之前的队列实现中用了数组,但栈也可以用类似的方式,或者用链表。不过引用[4]中给出了栈的数组实现,可能更适合当前情况。 接下来,处理用户输入的算术表达式。用户的需求是中缀表达式转后缀,再构建表达式。所以需要先实现中缀转后缀的功能。引用[2]详细描述了转换步骤,需要处理运算符优先级和括号。这里需要定义一个优先级函数,比如加减是1,乘除是2。然后按照规则处理栈中的操作符。 然后,将后缀表达式转换为表达式。这一步需要遍历后缀表达式,遇到数字则创建叶子节点压栈,遇到操作符则弹出两个节点作为左右孩子,创建新节点压栈。最后栈顶就是整个表达式的根节点。 计算表达式的值可以通过后序遍历来实现,因为后序遍历顺序是左右根,正好符合运算顺序。同时,在遍历过程中可以输出节点的信息,比如根节点的值和左右子节点的值。 现在要考虑代码的结构。分成几个模块:栈的实现、中缀转后缀、构建表达式、计算和输出节点。头文件需要包含栈的结构和函数声明,以及节点的定义。 测试用例方面,用户可能需要输入类似“3 + 5 * (2 - 8)”这样的表达式,转换成后缀是“3 5 2 8 - * +”,然后构建,计算值,并输出各节点的信息。需要注意括号的处理和运算符优先级是否正确。 另外,用户要求输出表达式的关键节点,比如根节点和其左右子节点。在遍历的时候,可能需要先层次遍历或者某种方式记录父节点和子节点的关系,或者在构建时直接记录每个节点的左右子节点。 潜在的问题包括内存管理,比如malloc的节点需要正确释放,但用户可能暂时不需要考虑,但代码中应该尽量避免内存泄漏。此外,输入的表达式合法性检查也是一个问题,但用户可能假设输入是合法的,暂时不处理错误情况。 最后,整合所有部分,确保中缀转后缀正确,栈操作无误,构建正确,计算准确,输出符合要求。然后编写示例代码,测试并验证结果。</think>### C语言实现表达式计算算术表达式 #### 一、数据结构定义 ```c #include <stdio.h> #include <stdlib.h> #include <ctype.h> #include <string.h> // 表达式节点结构 typedef struct TreeNode { char op; // 操作符('+','-','*','/') int value; // 操作数值 struct TreeNode *left; struct TreeNode *right; } TreeNode; // 栈结构(用于构建表达式) #define MAX_STACK 100 typedef struct { TreeNode* data[MAX_STACK]; int top; } TreeStack; ``` #### 二、核心功能实现 **1. 中缀转后缀表达式**(参考引用[2]) ```c int get_priority(char op) { if (op == '+' || op == '-') return 1; if (op == '*' || op == '/') return 2; return 0; } char* infix_to_postfix(const char* infix) { char postfix[256] = {0}; char stack[100] = {0}; int top = -1, j = 0; for (int i = 0; infix[i]; i++) { if (isdigit(infix[i])) { while (isdigit(infix[i])) postfix[j++] = infix[i++]; postfix[j++] = ' '; i--; } else if (infix[i] == '(') { stack[++top] = '('; } else if (infix[i] == ')') { while (top >= 0 && stack[top] != '(') { postfix[j++] = stack[top--]; postfix[j++] = ' '; } top--; // 弹出左括号 } else { while (top >= 0 && get_priority(stack[top]) >= get_priority(infix[i])) { postfix[j++] = stack[top--]; postfix[j++] = ' '; } stack[++top] = infix[i]; } } while (top >= 0) { postfix[j++] = stack[top--]; postfix[j++] = ' '; } return strdup(postfix); } ``` **2. 构建表达式**(参考引用[1]) ```c TreeNode* create_node(int val, char op) { TreeNode* node = malloc(sizeof(TreeNode)); node->op = op; node->value = val; node->left = node->right = NULL; return node; } TreeNode* build_expression_tree(const char* postfix) { TreeStack stack = {{0}, -1}; char* token = strtok((char*)postfix, " "); while (token) { if (isdigit(token[0])) { TreeNode* node = create_node(atoi(token), 0); stack.data[++stack.top] = node; } else { TreeNode* node = create_node(0, token[0]); node->right = stack.data[stack.top--]; node->left = stack.data[stack.top--]; stack.data[++stack.top] = node; } token = strtok(NULL, " "); } return stack.data[0]; } ``` **3. 计算与输出** ```c int calculate(TreeNode* root) { if (!root->left && !root->right) return root->value; int left = calculate(root->left); int right = calculate(root->right); switch(root->op) { case '+': return left + right; case '-': return left - right; case '*': return left * right; case '/': return left / right; } return 0; } void print_tree(TreeNode* root, int depth) { if (!root) return; print_tree(root->right, depth + 1); printf("%*s", depth*4, ""); if (root->op) printf("(%c)\n", root->op); else printf("%d\n", root->value); print_tree(root->left, depth + 1); } ``` #### 三、主程序示例 ```c int main() { const char* expr = "3 + 5 * ( 6 - 2 )"; // 测试表达式 char* postfix = infix_to_postfix(expr); printf("后缀表达式: %s\n", postfix); TreeNode* root = build_expression_tree(postfix); printf("\n表达式结构:\n"); print_tree(root, 0); printf("\n计算结果: %d\n", calculate(root)); free(postfix); return 0; } ``` #### 四、运行结果示例 ``` 后缀表达式: 3 5 6 2 - * + 表达式结构: (+) (*) 5 (-) 6 2 3 计算结果: 23 ``` #### 五、关键特性说明 1. **节点结构**:使用`TreeNode`结构同时存储运算符和操作数,通过`op`字段区分类型[^1] 2. **栈的应用**:构建过程中使用栈暂存子,符合后缀表达式处理逻辑[^4] 3. **优先级处理**:中缀转后缀时通过运算符优先级控制输出顺序[^2] 4. **递归计算**:后序遍历表达式实现自然求值顺序[^1]
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值