实验(表达树)

本实验主要实现的功能如下。
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; }
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值