现在处于刚刚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;
}
我曾经邪恶的想过这样上传我的代码:
想了想还是算了…没被请喝茶我就继续传文本…不用图片折磨大家了…