数据结构与算法B代码编写作业,表达式·表达式树·表达式求值,AC代码&注释

现在处于刚刚A题身心俱疲的状态…解题报告什么的实在是写不动了…从这篇文章开始将没有解题报告,只有附有详细注释的代码。

另外…这里的代码只是一个思路的参考,同学们还是要自己写的啊=___=

当然真实情况是为了防止被助教同志查出代码重复而请我喝茶…小伙伴们一定不要直接把我的代码交给DSB……

所以代码在下面……

/*
ID: Moien_Podiene
LANG: C++
*/

#include <iostream>
#include <cstdlib>
#include <string.h>
#include <memory.h>

using namespace std;

const int MAX_LEN = 65536;	//表达式最大长度
const int MAX_ELE = 256;	//最大变量数

class BinTreeNode;

class BinTreeNode
{
public:
	BinTreeNode(int, char);	//由当前节点的变量值(参数1)和变量名(参数2)创建节点
	BinTreeNode *GetLeftChild();	//返回当前节点的左孩子指针
	BinTreeNode *GetRightChild();	//返回当前节点的右孩子指针
	BinTreeNode *SetLeftChild(BinTreeNode *);	//由参数中的节点设置当前节点的左孩子,返回左孩子指针
	BinTreeNode *SetRightChild(BinTreeNode *);	//由参数中的节点设置当前节点的右孩子,返回右孩子指针
	int GetData();	//获取节点值
	int SetData(int);	//设置节点值,返回设置的值
	char GetName();	//获取变量名
	char SetName(char);	//设置变量名,返回设置名字
private:
	int data;	//当前节点的值,若为运算符则为-1
	char name;	//当前节点的变量名,或运算符号
	BinTreeNode *leftChild;
	BinTreeNode *rightChild;
};

int MaxInt(int, int);	//求两树最大值,返回最大值
int Power(int, int);	//乘方函数,求参数1的参数2次方

BinTreeNode *BuildTree(int, int, char *);	//生成参数3表达式中,从参数1到参数2的树,并返回根节点指针
BinTreeNode *LastOrder(BinTreeNode *);	//后序遍历一棵树,并输出变量名和运算符,返回树的根节点指针
BinTreeNode *FindNode(BinTreeNode *, int, int);	//返回参数1为根的第参数2层第参数3个节点的指针

int Calculate(int, int, char *, int *, char *, int);	//计算参数3的表达式从参数1到参数2的值,返回结果
														//参数4、5为变量名-数值对照表,参数6为表的元素数
int FindLevel(BinTreeNode *);	//返回以参数为根节点的二叉树的层数
bool MakeChart(char[][MAX_ELE], int, BinTreeNode *);	//生成用来输出的层数为参数2的根为参数3的二叉树示意图,存储在参数1的数组中
												//若树为空返回false,否则返回true

int main()
{
	int treeLevel = 0;
	int chartLen = 0;	//变量值-变量名表的长度
	int valChart[MAX_ELE];	//变量值表
	char nameChart[MAX_ELE];	//变量名表
	char formula[MAX_LEN];	//表达式字符串
	char treeChart[MAX_ELE][MAX_ELE];	//输出树的格式
	cin >> formula;
	cin >> chartLen;
	for(int i = 0; i < chartLen; i++)
		cin >> nameChart[i] >> valChart[i];
	BinTreeNode *root = BuildTree(0, strlen(formula) - 1, formula);	//由整个表达式生成二叉树
	treeLevel = FindLevel(root);	//查找树的深度
	LastOrder(root);	//后序遍历整棵二叉树输出逆波兰表达式
	cout << endl;
	MakeChart(treeChart, treeLevel, root);	//建立输出表
	for(int i = 0; i < treeLevel * 2 - 1; i++)
		cout << treeChart[i] << endl;
	cout << Calculate(0, strlen(formula) - 1, formula, valChart, nameChart, chartLen) << endl;	//计算并输出计算结果
	return 0;
}

BinTreeNode::BinTreeNode(int val, char word)
{
	data = val;
	name = word;
	leftChild = rightChild = NULL;
}

BinTreeNode *BinTreeNode::GetLeftChild()
{
	return leftChild;
}

BinTreeNode *BinTreeNode::GetRightChild()
{
	return rightChild;
}

BinTreeNode *BinTreeNode::SetLeftChild(BinTreeNode *val)
{
	leftChild = val;
	return leftChild;
}

BinTreeNode *BinTreeNode::SetRightChild(BinTreeNode *val)
{
	rightChild = val;
	return rightChild;
}

int BinTreeNode::GetData()
{
	return data;
}

int BinTreeNode::SetData(int val)
{
	data = val;
	return data;
}

char BinTreeNode::GetName()
{
	return name;
}

char BinTreeNode::SetName(char word)
{
	name = word;
	return name;
}

int MaxInt(int x, int y)
{
	if(x > y)
		return x;
	else
		return y;
}

int Power(int x, int y)
{
	int res = 1;
	if(y < 0)
		return 0;	//后面构造输出表时用到,负指数定义为0
	for(int i = 0; i < y; i++)
		res *= x;
	return res;
}

BinTreeNode *BuildTree(int start, int end, char *formula)
{
	if(start > end)
		return NULL;
	int match = 0;
	for(int i = end; i >= start; i--)
	{
		if(formula[i] == '(')
			match++;
		else if(formula[i] == ')')
			match--;
		else if(formula[i] == '+' && match == 0)
		{
			BinTreeNode *root = new BinTreeNode(-1, '+');	//存储当前节点为运算符
			root -> SetLeftChild(BuildTree(start, i - 1, formula));	//递归处理左侧表达式为左子树
			root -> SetRightChild(BuildTree(i + 1, end, formula));	//递归处理右侧表达式为右子树
			return root;
		}
		else if(formula[i] == '-' && match == 0)
		{
			BinTreeNode *root = new BinTreeNode(-1, '-');	//存储当前节点为运算符
			root -> SetLeftChild(BuildTree(start, i - 1, formula));	//递归处理左侧表达式为左子树
			root -> SetRightChild(BuildTree(i + 1, end, formula));	//递归处理右侧表达式为右子树
			return root;
		}
	}
	match = 0;
	for(int i = end; i >= start; i--)
	{
		if(formula[i] == '(')
			match++;
		else if(formula[i] == ')')
			match--;
		else if(formula[i] == '*' && match == 0)
		{
			BinTreeNode *root = new BinTreeNode(-1, '*');	//存储当前节点为运算符
			root -> SetLeftChild(BuildTree(start, i - 1, formula));	//递归处理左侧表达式为左子树
			root -> SetRightChild(BuildTree(i + 1, end, formula));	//递归处理右侧表达式为右子树
			return root;
		}
		else if(formula[i] == '/' && match == 0)
		{
			BinTreeNode *root = new BinTreeNode(-1, '/');	//存储当前节点为运算符
			root -> SetLeftChild(BuildTree(start, i - 1, formula));	//递归处理左侧表达式为左子树
			root -> SetRightChild(BuildTree(i + 1, end, formula));	//递归处理右侧表达式为右子树
			return root;
		}
	}
	if(formula[start] == '(' && formula[end] == ')')
		return BuildTree(start + 1, end - 1, formula);
	BinTreeNode *root = new BinTreeNode(-1, formula[start]);	//若未遇到运算符则必为单字符变量
	return root;
}

BinTreeNode *LastOrder(BinTreeNode *root)
{
	if(root -> GetLeftChild() != NULL)
		LastOrder(root -> GetLeftChild());	//递归后序遍历左子树
	if(root -> GetRightChild() != NULL)
		LastOrder(root -> GetRightChild());	//递归后序遍历右子树
	cout << root -> GetName();
	return root;
}

BinTreeNode *FindNode(BinTreeNode *root, int level, int num)
{
	if(root == NULL)
		return root;	//如果子树为空,直接返回空指针
	if(level == 1)	//递归出口,已查找到当前层
		return root;
	if(num <= Power(2, level - 2))
		return FindNode(root -> GetLeftChild(), level - 1, num);	//节点序号小于左右序号分界点2^(level - 2)
																	//在左子树,递归查找左子树
	else
		return FindNode(root -> GetRightChild(), level - 1, num - Power(2, level - 2));	//节点序号超过左右分界点
																						//在右子树,递归查找右子树
	return NULL;
}

int Calculate(int start, int end, char *formula, int *valChart, char *nameChart, int chartLen)
{
	int match = 0;
	for(int i = end; i >= start; i--)
	{
		if(formula[i] == '(')
			match++;
		else if(formula[i] == ')')
			match--;
		else if(formula[i] == '+' && match == 0)	//检测运算符,将表达式分为运算符左侧与运算符右侧,二分求值
			return Calculate(start, i - 1, formula, valChart, nameChart, chartLen) + 
				   Calculate(i + 1, end, formula, valChart, nameChart, chartLen);
		else if(formula[i] == '-' && match == 0)
			return Calculate(start, i - 1, formula, valChart, nameChart, chartLen) - 
				   Calculate(i + 1, end, formula, valChart, nameChart, chartLen);
	}
	match = 0;
	for(int i = end; i >= start; i--)
	{
		if(formula[i] == '(')
			match++;
		else if(formula[i] == ')')
			match--;
		else if(formula[i] == '*' && match == 0)
			return Calculate(start, i - 1, formula, valChart, nameChart, chartLen) * 
				   Calculate(i + 1, end, formula, valChart, nameChart, chartLen);
		else if(formula[i] == '/' && match == 0)
			return Calculate(start, i - 1, formula, valChart, nameChart, chartLen) / 
				   Calculate(i + 1, end, formula, valChart, nameChart, chartLen);
	}
	if(formula[start] == '(' && formula[end] == ')')
		return Calculate(start + 1, end - 1, formula, valChart, nameChart, chartLen);
	char buff = formula[start];	//若未遇到运算符则必为单字符变量
	for(int i = 0; i < chartLen; i++)
	{
		if(nameChart[i] == buff)
			return valChart[i];
	}
	return 1;
}

int FindLevel(BinTreeNode *root)
{
	if(root -> GetLeftChild() == NULL && root -> GetRightChild() == NULL)
		return 1;	//左右子树均为空,叶节点,已经到底层
	else if(root -> GetLeftChild() == NULL)
		return FindLevel(root -> GetRightChild()) + 1;
	else if(root -> GetRightChild() == NULL)
		return FindLevel(root -> GetLeftChild()) + 1;
	return MaxInt(FindLevel(root -> GetLeftChild()), FindLevel(root -> GetRightChild())) + 1;
}

bool MakeChart(char treeChart[][MAX_ELE], int treeLevel, BinTreeNode *root)
{
	if(treeLevel == 0)
		return false;
	for(int i = 0; i < MAX_ELE; i++)
	{
		for(int j = 0; j < MAX_ELE; j++)
			treeChart[i][j] = ' ';	//将后面可能考虑不到的地方先填上空格
		treeChart[i][MAX_ELE - 1] = 0;
	}
	int eleNum;	//当前层节点数
	int posi[MAX_LEN];	//当前处理层有字符的位置序号
	BinTreeNode *nodeBuff;	//暂存找到的节点
	memset(posi, 0, sizeof(posi));
	eleNum = Power(2, treeLevel - 1);	//二叉树第n层有2^(n - 1)个位置
	for(int i = 0; i < eleNum; i++)
		posi[i] = i * 2;	//1、3、5、7……位置对应数组标号0、2、4、6……
	for(int i = treeLevel; i > 0; i--)	//从叶节点层根据叶节点位置数据开始生成输出表
	{
		for(int j = 0; j < eleNum; j++)
		{
			nodeBuff = FindNode(root, i, j + 1);	//找到当前处理节点
			if(nodeBuff != NULL)
			{
				treeChart[i * 2 - 2][posi[j]] = nodeBuff -> GetName();
				for(int k = 0; k < j; k++)
					treeChart[i * 2 - 2][posi[k] + 1] = ' ';	//抹去前面设置的行结尾符号
				treeChart[i * 2 - 2][posi[j] + 1] = 0;	//设置行结尾,若后面再没有有效节点,这里就是行结尾
				if(i != treeLevel)	//若非末尾行,构造下面的树枝符号
				{
					if(nodeBuff -> GetLeftChild() != NULL)
					{
						treeChart[i * 2 - 1][posi[j] - 1] = '/';	//左子树示意字符
						for(int k = 0; k < j; k++)
							treeChart[i * 2 - 1][posi[k]] = treeChart[i * 2 - 1][posi[k] + 2] = ' ';	
																					//抹去前面设置的行结尾符号
						treeChart[i * 2 - 1][posi[j]] = 0;	//设置行结尾,若后面再没有有效节点,这里就是行结尾
					}
					if(nodeBuff -> GetRightChild() != NULL)
					{
						treeChart[i * 2 - 1][posi[j] + 1] = '\\';	//右子树示意字符,注意C++中反斜杠\标记为'\\'
						for(int k = 0; k <= j; k++)
							treeChart[i * 2 - 1][posi[k]] = treeChart[i * 2 - 1][posi[k] + 2] = ' ';	
																					//抹去前面设置的行结尾符号
						treeChart[i * 2 - 1][posi[j] + 2] = 0;	//设置行结尾,若后面再没有有效节点,这里就是行结尾
					}
				}
			}
		}
		eleNum = Power(2, i - 2);
		for(int j = 0; j < eleNum; j++)	//构造上一层的位置表:前一层俩位置中间
			posi[j] = (posi[j * 2] + posi[j * 2 + 1]) / 2;
	}
	return true;
}

我曾经邪恶的想过这样上传我的代码:


想了想还是算了…没被请喝茶我就继续传文本…不用图片折磨大家了…

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值