本实验主要实现的功能如下。
1.把一个算术表达式变成一棵二叉树,并求值
2.利用表达树做数字逻辑课程中的半加器实验
3.交换表达树中的所有的左右子树,即实现表达式中每个运算符对应的两个操作数之间的交换
实验环境是Windows10,Visual Studio 2017
具体程序源代码如下所示(主程序+几个头文件):
#include"实验总控制.h"
int main()
{
//freopen("in.txt", "r", stdin);
go();
return 0;
}
普通表达树.h
#include<iostream>
#include<stack>
#include<string>
#include<cstdlib>
using namespace std;
//定义表达树结点类
class TNode {
public:
char oper;
TNode *left;
TNode *right;
int s, t;
TNode() {
left = right = NULL;
oper = 0;
}
TNode(char op) {
left = right = NULL;
oper = op;
}
};
bool isoper(char op);//判断是否是运算符
int get_oper_order(char op);//得到某运算符级别
void free_tree(TNode *&p); //销毁树
void post_order(TNode *p);//树的后序遍历
void pre_order(TNode *p);//树的先序遍历
void in_order(TNode *p);//树的中序遍历
void exp_tree1(TNode *&p, string str); //前缀表达式生成二叉树
void exp_tree2(TNode *&p, string str); //后缀表达式生成二叉树
double value(TNode *p);//表达树求值
void exp_tree_go();//普通表达树程序运行
//判断是否是运算符
bool isoper(char op) {
char oper[] = { '(',')','+','-','*','/','^' };
for (int i = 0; i<sizeof(oper); i++) {
if (op == oper[i])
return true;
}
return false;
}
//得到某运算符级别
int get_oper_order(char op) {
switch (op) {
case '(':return 1;
case '+':
case '-':return 2;
case '*':
case '/':return 3;
case '^':return 4;
default:return 0;//定义在栈中的右括号和栈底字符的优先级最低
}
}
//销毁树
void free_tree(TNode *&p) {
if (p) {
if (p->left != NULL) { free_tree(p->left); delete p->left; p->left = NULL; }
if (p->right != NULL) { free_tree(p->right); delete p->right; p->right = NULL; }
if (p) { delete p; p = NULL; }
}
}
//树的后序遍历
void post_order(TNode *p) {
if (p) {
post_order(p->left);
post_order(p->right);
cout << p->oper;
}
}
//树的先序遍历
void pre_order(TNode *p) {
if (p) {
cout << p->oper;
pre_order(p->left);
pre_order(p->right);
}
}
//树的中序遍历
void in_order(TNode *p) {
if (p) {
if (p->left) {
if (isoper(p->left->oper) && get_oper_order(p->left->oper)<=get_oper_order(p->oper)) {
cout << "(";
in_order(p->left);
cout << ")";
}
else {
in_order(p->left);
}
}
cout << p->oper;
if (p->right) {
if (isoper(p->right->oper) && get_oper_order(p->right->oper) <= get_oper_order(p->oper)) {
cout << "(";
in_order(p->right);
cout << ")";
}
else {
in_order(p->right);
}
}
}
}
//后缀表达式生成二叉树
void exp_tree2(TNode *&p, string str) {
stack<TNode*>sta;
char tmp;
int i = 0;
tmp = str[i++];
while (tmp != '\0') {
if (tmp != '\0' && !isoper(tmp)) {
p = new TNode(tmp);
sta.push(p);
tmp = str[i++];
}
else {
p = new TNode(tmp);
if (sta.size()) {
p->right = sta.top();
sta.pop();
}
if (sta.size()) {
p->left = sta.top();
sta.pop();
}
sta.push(p);
tmp = str[i++];
}
}
}
//前缀表达式生成二叉树(与后缀表达式生成二叉树过程相反)
void exp_tree1(TNode *&p, string s) {
stack<TNode *>sta;
char tmp;
string str(s.rbegin(), s.rend());//s的逆序
int i = 0;
tmp = str[i++];
while (tmp != '\0') {
if (!isoper(tmp)) {
p = new TNode(tmp);
sta.push(p);
tmp = str[i++];
}
else {
p = new TNode(tmp);
if (sta.size()) {
p->left = sta.top();
sta.pop();
}
if (sta.size()) {
p->right = sta.top();
sta.pop();
}
sta.push(p);
tmp = str[i++];
}
}
}
//表达树求值
double value(TNode *p) {
double v1, v2;
if (p == NULL) return 0;
if (p->left == NULL && p->right == NULL)
return p->oper - '0';
v1 = value(p->left);
v2 = value(p->right);
switch (p->oper) {
case '+':return v1 + v2;
case '-':return v1 - v2;
case '*':return v1*v2;
case '/':if (v2 == 0) { cout << "出现分母为0的情况!!!" << endl; exit(-1); }
else return v1 / v2;
}
}
//普通表达树程序开始运行
void exp_tree_go() {
while (1) {
string exp;
TNode *tree=NULL;
cout << "---------------------普通表达树---------------------" << endl;
cout << "请输入一个前缀表达式: ";
cin >> exp;
exp_tree1(tree, exp);
cout << "该表达式对应的中缀表达式: "; in_order(tree); cout << endl;
cout << "该表达式对应的后缀表达式: "; post_order(tree); cout << endl;
cout << "运算结果是: "; cout << value(tree)<<endl;
cout<<"本局结束,如再玩,请输入\"1\",否则请输入\"0\""<<endl;
string tmp;
cin >> tmp;
if (tmp == "0") { cout << "您已退出\"普通表达树\"!" << endl<<endl<<endl; break; }
else if (tmp == "1") { cout << endl; continue; }
else { cout << "您输入错误,\"普通表达树\"强制退出!!!" <<endl<<endl<< endl; return; }
}
}
布尔表达树.h
#pragma once
#include"普通表达树.h"
bool is_bool_oper(char op);//判断是否是逻辑运算符
void bool_exp_tree1(TNode *&p, string str);//布尔前缀表达式生成二叉树
int get_bool_oper_order(char op); //得到某布尔运算符级别
void bool_in_order(TNode *p); //布尔表达树的中序遍历
bool bool_compute(bool v1, bool v2, char oper);//布尔运算
bool bool_value(TNode *p);//求布尔表达树的值
void bool_exp_tree_go();//布尔表达树程序运行
//判断是否是逻辑运算符
bool is_bool_oper(char op) {
char oper[] = { '(',')','+','-','*' };
for (int i = 0; i<sizeof(oper); i++) {
if (op == oper[i])
return true;
}
return false;
}
//布尔前缀表达式生成二叉树
void bool_exp_tree1(TNode *&p, string s) {
stack<TNode *>sta;
char tmp;
string str(s.rbegin(), s.rend());//s的逆序
int i = 0;
tmp = str[i++];
while (tmp != '\0') {
if (!is_bool_oper(tmp)) {
p = new TNode(tmp);
sta.push(p);
tmp = str[i++];
}
else if (tmp == '-') {
p = new TNode(tmp);
p->right = sta.top();
sta.pop();
sta.push(p);
tmp = str[i++];
}
else if (tmp == '+' || tmp=='*'){
p = new TNode(tmp);
if (sta.size()) {
p->left = sta.top();
sta.pop();
}
if (sta.size()) {
p->right = sta.top();
sta.pop();
}
sta.push(p);
tmp = str[i++];
}
}
}
//得到某布尔运算符级别
int get_bool_oper_order(char op) {
switch (op) {
case '-':return 0;
case '+':
case '*':return 2;
default:exit(-1);//错误
}
}
//布尔表达树的中序遍历
void bool_in_order(TNode *p) {
if (p) {
if (p->left) {
if (is_bool_oper(p->left->oper) && get_bool_oper_order(p->left->oper)<get_bool_oper_order(p->oper)) {
cout << "(";
bool_in_order(p->left);
cout << ")";
}
else {
bool_in_order(p->left);
}
}
cout << p->oper;
if (p->right) {
if (is_bool_oper(p->right->oper) && get_bool_oper_order(p->right->oper) <= get_bool_oper_order(p->oper)) {
cout << "(";
bool_in_order(p->right);
cout << ")";
}
else {
bool_in_order(p->right);
}
}
}
}
//布尔运算
bool bool_compute(bool v1, bool v2, char oper) {
if (oper == '+') {
if (v1 == 0 && v2 == 0) return 0;
else return 1;
}
else if (oper == '*') {
if (v1 == 1 && v2 == 1) return 1;
else return 0;
}
else if (oper == '-') return (!(v2));
exit(-1);//布尔运算只涉及逻辑与、逻辑或,逻辑非已经处理,此处不涉及
}
//求布尔表达树的值( +*10*1-0)(程序待修改,本函数错误)
bool bool_value(TNode *p) {
bool v1, v2;
if (p == NULL) return 0;
if (p->left == NULL && p->right == NULL)
return p->oper-'0';
v1 = bool_value(p->left);//此处刚开始写的竟然是value,浪费我大量时间才找出这个bug。。。
v2 = bool_value(p->right);
if (is_bool_oper(p->oper))
return bool_compute(v1, v2, p->oper);
}
//布尔表达树程序运行
void bool_exp_tree_go() {
while (1) {
string exp;
TNode *tree = NULL;
cout << "---------------------布尔表达树---------------------" << endl;
cout << "请输入一个布尔前缀表达式: ";
cin >> exp;
bool_exp_tree1(tree, exp);
cout << "该表达式对应的中缀表达式: "; bool_in_order(tree); cout << endl;
cout << "该表达式对应的后缀表达式: "; post_order(tree); cout << endl;
cout << "运算结果是: "; cout << bool_value(tree) << endl;
cout << "本局结束,如再玩,请输入\"1\",否则请输入\"0\"" << endl;
string tmp;
cin >> tmp;
if (tmp == "0") { cout << "您已退出\"布尔表达树\"!" << endl<<endl<<endl; break; }
else if (tmp == "1") { cout << endl;; continue; }
else { cout << "您输入错误,\"布尔表达树\"强制退出!!!" <<endl<<endl<< endl; return; }
}
}
复制表达树.h
#pragma once
//复制二叉树
TNode *get_node(char e, TNode *l, TNode *r) {
TNode *tmp = new TNode;
tmp->left = l;
tmp->right = r;
tmp->oper = e;
return tmp;
}
TNode *copy_tree(TNode *tree) {
if (!tree) return NULL;
TNode *p = NULL, *q = NULL;
if (tree->left) p = copy_tree(tree->left);
else p= NULL;
if (tree->right) q = copy_tree(tree->right);
else q= NULL;
TNode *new_node = get_node(tree->oper, p, q);
return new_node;
}
//复制表达树程序开始运行
void copy_exp_tree_go() {
while (1) {
cout << "---------------------复制表达树---------------------" << endl;
TNode *tree, *tree_copy;
string s;
cout << "请输入一个前缀算术表达式: "; cin >> s;
exp_tree1(tree, s);
tree_copy = copy_tree(tree);
cout << "创建的表达树: "; in_order(tree); cout << endl;
cout << "对应副本:"; in_order(tree_copy); cout << endl;
cout << "副本对应的值: "; cout << value(tree_copy) << endl;
cout << "本局结束,如再玩,请输入\"1\",否则请输入\"0\"" << endl;
string tmp;
cin >> tmp;
if (tmp == "0") { cout << "您已退出\"复制表达树\"!" << endl << endl << endl; break; }
else if (tmp == "1") { cout << endl;; continue; }
else { cout << "您输入错误,\"复制表达树\"强制退出!!!" << endl << endl << endl; return; }
}
}
交换表达树.h
#pragma once
//交换表达树中的所有左右子树
void exchange_exp_tree(TNode *tree) {
if (tree) {
if (tree->left) exchange_exp_tree(tree->left);
if (tree->right)exchange_exp_tree(tree->right);
TNode *tmp = tree->left; tree->left = tree->right; tree->right = tmp;
}
}
void exchange_exp_tree_go(){
while (1) {
cout << "---------------------交换表达树---------------------" << endl;
string s;
TNode *tree;
cout << "请输入一个前缀算术表达式: "; cin >> s;
exp_tree1(tree, s);
cout << "对应的中缀表达式: "; in_order(tree); cout << endl;
cout << "对应的后缀表达式: "; post_order(tree); cout << endl;
exchange_exp_tree(tree);
cout << endl;
cout << "交换表达树的前缀表达式: "; pre_order(tree); cout << endl;
cout << "交换表达树的中缀表达式: "; in_order(tree); cout << endl;
cout << "交换表达式的后缀表达式: "; post_order(tree); cout << endl;
cout << "本局结束,如再玩,请输入\"1\",否则请输入\"0\"" << endl;
string tmp;
cin >> tmp;
if (tmp == "0") { cout << "您已退出\"交换表达树\"!" << endl << endl << endl; break; }
else if (tmp == "1") { cout << endl;; continue; }
else { cout << "您输入错误,\"交换表达树\"强制退出!!!" << endl << endl << endl; return; }
}
}
半加器实验.h
#pragma once
#include"布尔表达树.h"
//半加器实验程序开始运行
void half_adder_go() {
while (1) {
cout << "---------------------半加器实验---------------------" << endl;
char X, Y;
string s1="*XY", s2="+*X-Y*-XY";
cout << "请输入两个一位二进制数: " << endl;
cout << "X="; cin >> X;
cout << "Y="; cin >> Y;
//把X,Y带入进位C的公式,带入逻辑运算结果S的公式
for (int i = 0; i < s1.length(); i++) {
if (s1[i] == 'X') s1[i] = X;
if (s1[i] == 'Y')s1[i] = Y;
}
for (int i = 0; i < s2.length(); i++) {
if (s2[i] == 'X')s2[i] = X;
if (s2[i] == 'Y')s2[i] = Y;
}
TNode *tree1,*tree2;
bool_exp_tree1(tree1,s1);
bool_exp_tree1(tree2,s2);
bool C = bool_value(tree1);
bool S = bool_value(tree2);
cout << "X Y C S" << endl;
cout << X << " " << Y << " " << C << " " << S << endl;
cout << "本局结束,如再玩,请输入\"1\",否则请输入\"0\"" << endl;
string tmp;
cin >> tmp;
if (tmp == "0") { cout << "您已退出\"半加器实验\"!" << endl << endl << endl; break; }
else if (tmp == "1") { cout << endl;; continue; }
else { cout << "您输入错误,\"半加器实验\"强制退出!!!" << endl << endl << endl; return; }
}
}
实验总控制.h
#pragma once
#include"半加器实验.h"
#include"复制表达树.h"
#include"交换表达树.h"
void menu() {
cout << "==============================================" << endl;
cout << "*****1→→→→→→普通表达树←←←←←←1*****" << endl;
cout << "*****2→→→→→→布尔表达树←←←←←←2*****" << endl;
cout << "*****3→→→→→→半加器实验←←←←←←3*****" << endl;
cout << "*****4→→→→→→复制表达树←←←←←←4*****" << endl;
cout << "*****5→→→→→→交换表达树←←←←←←5*****" << endl;
cout << "*****0→→→→→→→→→→→→→→→ 退出*****" << endl;
cout << "==============================================" << endl;
}
//总实验控制端
void go() {
while (1) {
menu();
int number;
cout << "请根据提示输入您要测试的实验编号: "; cin >> number;
switch (number) {
case 0: {cout << "您已退出游戏,欢迎再次玩耍!!!" << endl; return; }
case 1: {
cout << "欢迎来到\"普通表达树 \"" << endl << endl;;
exp_tree_go();
break; }
case 2: {
cout << "欢迎来到\"布尔表达树 \"" << endl << endl;;
bool_exp_tree_go();
break;
}
case 3: {
cout << "欢迎来到\"半加器实验\" C=*XY S=+*X-Y*-XY" << endl << endl;
half_adder_go();
break;
}
case 4: {
cout << "欢迎来到\"复制表达树\"" << endl << endl;
copy_exp_tree_go();
break;
}
case 5: {
cout << "欢迎来到\"交换表达树\"" << endl << endl;
exchange_exp_tree_go();
break;
}
default: {cout << "您输入错误,请按提示输入!" << endl; }
}
}
}