重言式判别(栈和二叉树)

  • 问题描述
  • 设计要求
  • 思路分析
    • 递归建立表达式二叉树
    • 借助栈建立二叉树
  • 根据二叉树得到真值表
  • 完整代码

问题描述

一个逻辑表达式如果对于其变元的任一种取值都为真,则称重言式;反之,如果对于其任一种取值都为假,则称矛盾式;其它情形称为可满足式。编写程序,判断逻辑表达式属于哪种情形。

设计要求

1.建立逻辑二叉树表达式
2.写一程序,根据逻辑二叉表达式对包括逻辑变量的逻辑表达式进行重言式判别

思路分析

问题的关键式表达式二叉树的建立,建立表达式二叉树有两种方式

递归建立表达式二叉树

代码的核心思想是:找到表达式中最后使用的操作符,作为二叉树根节点,左侧右侧递归生成的二叉树分别为左孩子和右孩子,如果优先级最低的操作符有多个,就取最右边的那个。该方法的优点是代码简单,思路清晰,缺点是要自己动手写!因为我写的时候没找到相关的代码,因此我参考了另一种方法,这里给出一篇大神写的博客供大家参考思路递归建立表达式二叉树

借助栈建立二叉树




差不多就是这样的思路,想更详细的了解表达式二叉树的建立可以看这篇文章数据结构与算法 表达式二叉树
当然了解了表达式二叉树的建立之后,还要把它改编成逻辑表达式二叉树这里就不多叙述了,关键是思路。

根据二叉树得到真值表

得到了二叉树之后,要对变量进行赋值和表达式值的计算,那么我们就需要一个函数得到变量的个数。现在假设有三个变量ABC,他们取不同的值对应的真值表刚好是0-7的二进制表示那么就可以用一个循环对表达式中的ABC赋值并算出每种情况下的真值,最后根据真值表判断是不是重言式就好了。

完整代码

//
//  main.cpp
//  test#include <iostream>
#include <string>using namespace std;typedef struct TreeNode{char data;int value;struct TreeNode *lchild;struct TreeNode *rchild;
}*Bitree;struct Stack
{Bitree *base;int top;int size;
};void InitStack(Stack &s){s.base = new Bitree[50];s.top = 0;s.size = 50;
}void push(Stack &s,Bitree &node){if(s.top >= s.size){Bitree *newbase;newbase = new Bitree[s.size + 10];for(int j = 0;j < s.top; j++){newbase[j] = s.base[j];}delete[] s.base;s.base = newbase;s.size += 10;}s.base[s.top++] = node;
}bool empty(Stack &s){return s.top == 0;
}bool pop(Stack &s,Bitree &node){if(empty(s)){return false;}node = s.base[--s.top];return true;
}bool Gettop(Stack s,Bitree &node){if(!empty(s)){node = s.base[s.top - 1];return true;}else return false;
}
//栈的定义
bool JudgeSimbol(char &c){switch(c){case'|':case'&':case'~':case'(':case')':case'=':return true;default:return false;}
}bool JudgeNum(char &c){if(c == '0'|| c == '1') return true;else return false;
}bool JudgeCaps(char &c){               //检查大写字母if(c >= 'A'&&c <= 'Z') return true;else return false;
}int JudgeCin(string c){                    //检查字符串的正确性int left = 0;int right = 0;for(int i = 0;i < (int)c.length();i++){if(!(JudgeSimbol(c[i])||JudgeNum(c[i])||JudgeCaps(c[i]))){return false;                                                        //不是大写不是符号不是数字}else if(JudgeSimbol(c[0])){if(c[0]!='~'&&c[0] != '(') return false;}if(c[i] == '(') left++;if(c[i] == ')') right++;}if(left != right) return false;int i;i = (int)c.length() - 1;if(c[i] != '=') return false;for(int i = 0;i < (int)c.length();i++){if(JudgeCaps(c[i])){if(JudgeCaps(c[i - 1])||JudgeCaps(c[i + 1])) return false;            //大写字母}else if(JudgeSimbol(c[i])){if(c[i] == '~'){if(JudgeCaps(c[i - 1])||JudgeNum(c[i - 1])) return false;        //~运算符else if(JudgeSimbol(c[i + 1])) return false;}else if(c[i] == '('){if(JudgeCaps(c[i - 1])||c[i - 1] == '~'||JudgeNum(c[i - 1])){return false;}else if(JudgeSimbol(c[i + 1])&&c[i + 1] != '~'){return false;}}else if(c[i] == ')'){if(JudgeSimbol(c[i - 1])){return false;}else if(JudgeSimbol(c[i + 1])&&(c[i + 1] == '~'||c[i + 1] == '(')){return false;}}}}return true;
}int premier(char c){switch(c){case'|':return 3;case'&':return 2;case'~':return 0;case')':return 1;case'(':return 10;default:return -1;};
}                       //操作符优先级判断int compare(char c1, char c2){return premier(c1)>premier(c2)?1:0;
}                       //比较操作符优先级void StringCut(string &c1){string c2;for(int i = 0;i < (int)c1.length();i++){if(c1[i] != ' ' && c1[i] != '='){c2.push_back(c1[i]);}}c1 = c2;
}               //去除字符串中的空格和等于号void CreateOpratorTree(TreeNode *&T,string c){ //建立逻辑表达式二叉树Stack s1,s2;InitStack(s1);InitStack(s2);TreeNode *a,*top,*b1,*b2,*trash;for(int i = 0;i < (int)c.length(); i++){a = (TreeNode *)malloc(sizeof(TreeNode));a->data = c[i];a->value = 0;a->lchild = NULL;a->rchild = NULL;if(JudgeSimbol(c[i])){if(empty(s1)) {push(s1,a);Gettop(s1,top);continue;}                   //如果操作符栈是空,直接push进来,跳过判断,然后取下一个字符Gettop(s1,top);while(compare(a->data,top->data)&&c[i] != '~'&&c[i] != ')'&&c[i] != '('&&!empty(s1)){pop(s1,top);pop(s2,b1);pop(s2,b2);top->lchild = b1;top->rchild = b2;push(s2,top);}                 //push操作符之前比较优先级push(s1,a);if(c[i] == ')'){pop(s1,trash);Gettop(s1,top);while(top->data != '('){pop(s1,top);pop(s2,b1);pop(s2,b2);top->lchild = b1;top->rchild = b2;push(s2,top);Gettop(s1,top);}pop(s1,trash);           //处理括号}}else{push(s2,a);if(!empty(s1)){Gettop(s1,top);if(top->data == '~') {pop(s1,top);pop(s2,b1);top->lchild = b1;top->rchild = NULL;push(s2,top);}}                   //处理~}}while(!empty(s1)){pop(s1,top);pop(s2,b1);pop(s2,b2);top -> lchild = b1;top -> rchild = b2;push(s2,top);}Gettop(s2,T);
}int Getvar(string s,string &var){int num = 0;for (int i = 0; i < s.length();i++) {if(JudgeCaps(s[i])) {num++;var.push_back(s[i]);}}return num;
}                                   //获得变量数和变量void xuanxu(Bitree B){if(B == NULL) return ;cout << B->data;cout << B->value;xuanxu (B -> lchild);xuanxu (B -> rchild);
}                               //先序遍历测试用int AssignValue(Bitree B,char c,int value){// 先序遍历二叉树,为data为c或0,1的节点赋值value或0,1,if(B){if(B->data==c) B->value=value;if(B->data=='1') B->value=1;if(B->data=='0') B->value=0;AssignValue(B->lchild, c, value);AssignValue(B->rchild, c, value);}return 1;
}int Calculate(Bitree B){// 后序遍历二叉树,计算表达式真值if(B){Calculate(B->lchild);Calculate(B->rchild);switch(B->data){case '|':B->value = B->lchild->value||B->rchild->value;break;case '&':B->value = B->lchild->value&&B->rchild->value;break;case '~':B->value = !B->lchild->value;break;}}return 1;
}int Num2Bin(int b[],int x,int len){// 数组b返回整数x的二进制表示,len表示二进制数所占的位数while(x!=0){b[len]=(x%2);x=x/2;len--;}return 1;
}int Evaluate(Bitree B, int blmun, string c, int *res){//计算二叉树的真值int comb[100];int i,j,k;int num;num = pow(2,double(blmun));for(k=0; k<num; k++){fill(comb,comb+100,0);Num2Bin(comb, k, blmun-1);for(j=0; j<blmun; j++){AssignValue(B, c[j], comb[j]);}Calculate(B);res[k] = B->value;}return 1;
}void Judge(int res[]){//根据真值表判断表达式为重言式,矛盾式或可满足式int i=0,flag1=0,flag2=0;while(res[i] != -1){if(res[i] == 0) flag1=1;if(res[i] == 1) flag2=1;if(flag1 && flag2) {cout << "该表达式是可满足式" << endl;return ;}i++;}if(flag1) {cout << "该表达式是矛盾式" << endl;return ;}if(flag2) {cout << "该表达式是重言式" << endl;return ;}
}int main(int argc, const char * argv[]) {int res[1024];fill(res,res + 1024,-1);TreeNode *T = NULL;string ch;string s1 = "B&~B&B=";//getline(cin,s1);if(!JudgeCin(s1)){cout << "请输入正确的表达式" << endl;}StringCut(s1);CreateOpratorTree(T, s1);int blnum = Getvar(s1, ch);Evaluate(T,blnum,ch, res);Judge(res);return 0;
}

有更简洁的建立表达式二叉树的代码可以分享一下,我写的有些冗长了。希望对大家做题能提供帮助!

数据结构课程设计 重言式判别相关推荐

  1. C/C++数据结构课程设计安排

    C/C++数据结构课程设计安排 数据结构课程设计安排 课程设计学时:32学时 课程设计目的:综合应用数据结构课程中所学的数据结构:线性表.栈.队列.数组.广义表.树.二叉树.图.查找表中的一种或多种数 ...

  2. 数据结构课程设计——机票售卖系统(C++)

    引言 这学期最后的数据结构课程设计需要我们完成一个简单的小程序,我选择了一个机票售卖系统,实现了一些基本的功能:因为时间给的比较短,又赶在复习周补课,所以并没有什么突出的地方,我就在这里聊聊我的代码实 ...

  3. 数据结构课程设计---最长公共子串

    数据结构课程设计,由用户输入两个字符串串X和Y,再由用户输入一个任意的字符串Z,实现以下功能: ①如果字符串Z是字符串X的子串,则显示Z在X中的位置并记录,如果字符串Z是字符串Y的子串,则显示Z在Y中 ...

  4. 设树采用孩子兄弟表示法存放.用类c语言设计算法计算树的高度.,(数据结构课程设计分类题目.doc...

    (数据结构课程设计分类题目 线性表 顺序表: 1.设有一元素为整数的线性表L=(a1,a2,a3,-,an),存放在一维数组A[N]中,设计一个算法,以表中an作为参考元素,将该表分为左.右两部分,其 ...

  5. c语言数据结构五子棋实验报告,数据结构课程设计-五子棋

    数据结构课程设计-五子棋 姓 名: 学 院: 计算机与通信学院 班 级: 通信工程 101 班 指导老师: 目录一.需求分析 31.1 开发背景 .32.2 功能简介 .3二.系统设计 42.1 函数 ...

  6. 数据结构迷宫代码_数据结构课程设计——迷宫求解(二)

    前言 接上文的介绍,本文将主要介绍如何生成随机迷宫,在网上找到的资源也比较多,这里我选取了随机 Prim 算法生成迷宫,选择这个算法的理由如下: 算法思想简单,易于实现 生成的迷宫比较自然,不会出现明 ...

  7. c语言小数表达式运算课程设计,数据结构课程设计表达式计算.doc

    数据结构课程设计表达式计算 福建农林大学计算机与信息学院 计算机类 课程设计报告 课程名称:算法与数据结构课程设计题目:表达式计算姓 名:系:数学系专 业:数学与应用数学年 级:学 号:指导教师:宁正 ...

  8. 数据结构课程设计:顺序结构、动态链表结构下的一元多项式的加法、减法、乘法的实现...

    原来做的数据结构课程设计,今天整理资料时偶然发现了,自己留着没啥意思,共享一下吧,互相交流学习 要求 设有一元多项式Am(x)和Bn(x). Am(x)=A0+A1x1+A2x2+A3x3+- +Am ...

  9. c语言数据结构课程设计停车场管理系统,数据结构课程设计报告停车场管理系统...

    <数据结构课程设计报告停车场管理系统>由会员分享,可在线阅读,更多相关<数据结构课程设计报告停车场管理系统(8页珍藏版)>请在人人文库网上搜索. 1.数据结构课程设计报告系 别 ...

  10. 学生搭配问题数据结构报告c语言,数据结构课程设计_学生搭配问题.doc

    数据结构课程设计_学生搭配问题 数据结构课程设计 题 目: 学生搭配问题 学 院: 班 级: 学 生 姓 名: 学 生 学 号: 指 导 教 师: 2012 年 12 月 3 日 课程设计任务书 姓名 ...

最新文章

  1. tp3 普通模式url模式_Thinkphp 3.2.3 url 路由访问模式
  2. Oracle EBS-SQL (QA-1):检查超出检验周期的检验数据.sql
  3. 3.通过现有的PDB创建一个新的PDB
  4. BeanDefinition构建示例
  5. mysql 查询 汇总_Mysql-Sql查询汇总
  6. Android通过透明度设置背景变暗
  7. 容器编排技术 -- Kubernetes kubectl create service loadbalancer 命令详解
  8. 用maven建立一个工程2
  9. 环境准备 Ubuntu Docker
  10. 下半年值得关注的新机和科技趋势
  11. vue3.0项目创建
  12. Ubantu指令收藏
  13. dotcms open source java cms_开放源Java(JSP)CMS系统的推荐源代码
  14. 采用Java+SSH+JSP技术架构开发实现在线会议租赁管理系统
  15. 电脑间串口连接传输文件
  16. 高德地图测开笔试题分享
  17. mysql 类似oracle dual_MySQL类似Oracle的dual虚拟表
  18. python面试题No5
  19. android删除自带应用程序,安卓手机自带软件怎么卸载?无需root卸载安卓手机自带软件方法...
  20. ps滤镜之——马赛克

热门文章

  1. 网站metro风格正式发布
  2. (数据结构)线性表(总结)——链式存储结构与顺序储存结构的优缺点
  3. JavaScript中的函数 1
  4. TopCoder SRM 677 Div2
  5. 大规模容器镜像管理方案
  6. 手机如何将PDF文件拆分?分享两种手机拆分文件方法
  7. C语言实现万年历记事本,简单的日历记事本jQuery插件e-calendar(带样式美化)
  8. 基于MATLAB的指纹对比识别系统
  9. c 语言小游戏坦克大战,C++实现坦克大战小游戏EGE图形界面
  10. Flux、Mono、Reactor 实战(史上最全)