重言式判别

  • 需求分析
  • 概要设计
  • 详细设计
  • 调试分析
  • 测试数据及用户手册
  • 附录

需求分析

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

概要设计

二叉树的抽象数据类型定义如下:
ADT BinaryTree{
数据对象D:D是具有相同特性的数据元素的集合。
数据关系R
若D=∅,则R=∅,称BinaryTree为空二叉树;
若D≠∅,则R={H},H是如下二元关系;
(1)在D中存在唯一的称为根的数据元素root,它在关系H下无前驱;
(2)若D-{root}≠∅,则存在D-{root}={Dl,Dr},且Dl∩Dr=∅
(3)若Dl≠∅,则Dl中一定存在唯一的元素xl,<root,xl>∈H,且存在D1上的关系H1 ⊂ H ,若Dr≠∅,则Dr中一定存在唯一的元素xr,<root,xr>∈H,且存在Dr上的关系Hr ⊂ H ;H={<root,xl>,<root,xr>,Hl,Hr};
(4)(Dl,{Hl})是一颗符合基本定义的二叉树,称为根的左子树,(Dr,{Hr})是一颗符合基本定义的二叉树,称为根的右子树。
基本操作P:
CreatBiTree(&T, definition)
初始条件:defination给出二叉树的定义
操作结果:按definition构造二叉树T
Assignvalue(T,&e,value)
初始条件:二叉树T存在,e是T中某个节点
操作结果:节点e赋值为value
PostOrderTraverse(T,Visit())
初始条件:二叉树存在,Visit是对每个节点操作的应用函数
操作结果:后序遍历T,对每一个节点调用函数Visit一次且仅一次
}// ADT BinaryTree

以栈作为辅助,数据类型为:
ADT Stack{
数据对象:
D={ai|a∈EleSet,i=1,2,…,n,n≥0}
数据关系:
R1={<ai-1,ai>|ai-1,ai∈D,i=2,…,n}
约定an为栈顶,a1为栈底。
基本操作:
InitStack(&S)
操作结果:构造一个空栈S
GetTop(S)
初始条件:栈S已存在且非空
操作结果:返回S栈顶元素
Pop(&S, &e)
初始条件:栈S已存在
操作结果:删除S的栈顶元素,并用e返回其值
Push(&S, &e)
初始条件:栈S已存在
操作结果:插入e为新的栈顶元素
}// ADT Stack

使用函数:
int InitStack (BiTStack &S)
操作结果:构造栈存放二叉树节点
int Push (BiTStack &S, BiTree &B)
操作结果:二叉树节点入栈
int Pop(BiTStack &S,BiTree &B)
操作结果:二叉树节点出栈
BiTree Gettop(BiTStack S)
操作结果:返回栈顶元素
int In(char c)
操作结果:判定字符是否为运算符
char Precede(char c1, char c2)
操作结果:判断逻辑运算符的优先级
int CorrectNot(char a[])
操作结果:返回表达式是否合法
int CreatBiTree(BiTree &B, char *a)
操作结果:根据表达式a构造二叉树
int Getvar(char *a,char *ch)
操作结果:返回表达式中不同的变量个数和变量ch
int AssignValue(BiTree B,char c,int value)
操作结果:先序遍历二叉树,为data为c或0,1的节点赋值value或0,1,
int Calculate(BiTree B)
操作结果:后序遍历二叉树,计算表达式真值
int Num2Bin(int *b,int x,int len)
操作结果:数组b返回整数x的二进制表示
int Evaluate(BiTree B, int kind, char *c, int *res)
操作结果:计算二叉树的真值
char Judge(int *res)
操作结果:根据真值表判断表达式为重言式,矛盾式或可满足式
void showoff(char x)
操作结果:显示判断结果

详细设计

  实现重言式判别基本操作的“Tree__Stack.h”文件如下:

#ifndef TREE__STACK_H_INCLUDED
#define TREE__STACK_H_INCLUDED
#endif // TREE__STACK_H_INCLUDEDtypedef struct BiTNode{char data;  //结点值int value;  //参数值struct BiTNode *lchild,*rchild; //左右孩子结点指针
}*BiTree;typedef struct {BiTree *top;BiTree *base;
}BiTStack;int InitStack(BiTStack &S){//构造栈存放二叉树节点S.base=(BiTree*)malloc(sizeof(BiTNode));S.top=S.base;return OK;
}int Push(BiTStack &S, BiTree &B){//二叉树节点入栈*S.top=B;S.top++;return OK;
}int Pop(BiTStack &S,BiTree &B){//二叉树节点出栈S.top--;B=*S.top;return OK;
}BiTree Gettop(BiTStack S){  //返回栈顶元素return *(S.top-1);
}int CorrectNot(char a[]){//返回表达式是否合法int i = 0;int flag = 0;int cnt1=0;int cnt2=0;while(a[i]!='\0'){if(a[i]=='(') cnt1++;if(a[i]==')') cnt2++;if(!(a[i]==' ' ||a[i]=='~' ||a[i]=='|' ||a[i]=='&' ||a[i]=='(' ||a[i]== ')'||(a[i]>='A' && a[i]<='Z')||(a[i]>='0' && a[i]<='1'))) {flag = 1; break;}  //不是运算符和运算数if(cnt2 > cnt1) {flag = 1; break;}  //括号不匹配if(a[i]!=' ' && i !=0){int l,r;l = i-1;r = i+1;while(a[l]==' '){l--;}while(a[r]==' '){r++;}if(a[i]=='~' || a[i]=='|' || a[i]=='&'){if(!(a[r]=='~' || a[r]=='(' || (a[r]>='A' && a[r]<='Z')||(a[r]>='0' && a[r]<='1'))) {flag = 1;break;}
//不是运算数或者不是括号和非if(a[i]!='~'){if(!(a[l]==')'|| (a[l]>='A' && a[l]<='Z')||(a[l]>='0' && a[l]<='1'))) {flag = 1;break;}
//符号前面不是右括号或者运算数}if(a[i]=='~'){if((a[l]==')'|| (a[l]>='A' && a[l]<='Z')||(a[l]>='0' && a[l]<='1'))) {flag = 1;break;}
//右括号跟非或者运算数跟非}}if((a[i]>='A' && a[i]<='Z')||(a[i]>='0' && a[i]<='1')){if((a[r]>='A' && a[r]<='Z')|| (a[l]>='A' && a[l]<='Z')||(a[r]>='0' && a[r]<='1')||(a[l]>='0' && a[l]<='1')){flag=1; break;} //运算数跟运算数}}i++;}if(cnt1 != cnt2) flag = 1; //括号不匹配return flag;
}int In(char c){//判定字符是否为运算符char OP[7] = {'|','&','~','(',')','#','\0'};int flag = 0;int i = 0;while(OP[i] != '\0'){if(OP[i] == c) flag=1;i++;}return flag;
}char Precede(char c1, char c2){//判断逻辑运算符的优先级char OP[7] = {'|','&','~','(',')','#','\0'};unsigned char Prior[7][7] ={'x','|','&','~','(',')','#','|','>','<','<','<','>','>','&','>','<','<','<','>','>','~','>','>','>','<','>','>','(','<','<','<','<','=',' ',')','>','>','>','>','>','>','#','<','<','<','<',' ','='};int i = 0; int j = 0;while(c1 != OP[i]) i++;while(c2 != OP[j]) j++;return Prior[i+1][j+1];
}int CreatBiTree(BiTree &B, char *a){//根据表达式a构造二叉树char *expr;char End[] = {'#','\0'};expr = strcat(a,End);BiTStack OPTR, OPND;InitStack(OPTR); //运算符栈InitStack(OPND);//运算数栈BiTree b1,b,x,y,theta;b1 = (BiTree)malloc(sizeof(BiTNode));b1->data = '#';b1->value = 0;b1->lchild = NULL;b1->rchild = NULL;Push(OPTR, b1);while(*expr !='#'||Gettop(OPTR)->data!='#'){if(*expr ==' '){expr++;continue;}b = (BiTree)malloc(sizeof(BiTNode));b->data = *expr;b->value = 0;b->lchild = NULL;b->rchild = NULL;if(!In(*expr)){Push(OPND, b);expr++;continue;}else {switch(Precede(Gettop(OPTR)->data, *expr)){case '<':Push(OPTR,b);expr++;break;case '=':Pop(OPTR, b);expr++;break;case '>':Pop(OPTR, theta);Pop(OPND, x);theta->rchild = x;if(theta->data != '~'){Pop(OPND, y);theta->lchild = y;}Push(OPND,theta);}}}B=Gettop(OPND);return 1;
}int Getvar(char *a,char *ch){//返回表达式中不同的变量个数和变量chint i=0,k=0,flag=1;while(a[i]){if(a[i]>='A' && a[i]<='Z'){int j=0;while(ch[j]!='\0'){if(ch[j]==a[i]){flag=0; break;}j++;}if(flag){ch[k]=a[i]; k++;}}i++;flag=1;}return k;
}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->rchild->value;break;}}return 1;
}int Num2Bin(int *b,int x,int len){// 数组b返回整数x的二进制表示while(x!=0){b[len]=(x%2);x=x/2;len--;}return 1;
}int Evaluate(BiTree B, int blmun, char *c, int *res){//计算二叉树的真值int comb[20];int i,j,k,l;int num;num = pow(2,double(blmun));for(k=0; k<num; k++){for(i=0; i<blmun; i++){comb[i] = 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;
}char 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) return 'S';i++;}if(flag1) return 'F';if(flag2) return 'T';
}void showoff(char x){//显示判断结果switch(x){case 'T':printf("该表达式是重言式\n");break;case 'F':printf("该表达式是矛盾式\n");break;case 'S':printf("该表达式是可满足式\n");break;}
}

  重言式判别主函数“chongyanshi.cpp”文件如下:

#include<string.h>
#include<stdio.h>
#include<malloc.h>
#include<math.h>
#define OK 1
#include"Tree__Stack.h"int main(){int res[1024]; //存放真值表真值int blmun; //变量数int flag = 0;BiTree b;char a[100];//存放表达式char ch[10];//存放变量for(int m=0; m<1024; m++){res[m]=-1;}  //真值初始化for(int k=0; k<20; k++){ch[k]='\0';}  //表达式初始化printf("请输入逻辑表达式:\n\n");gets(a);  //获取表达式printf("\n");if(!CorrectNot(a)){ //表达式合法的情况下int i = 0;blmun = Getvar(a, ch);//获取变量数以及变量组合CreatBiTree(b,a); //根据表达式构建二叉树Evaluate(b, blmun, ch, res);// 进行表达式真值计算showoff(Judge(res));//根据判断结果返回逻辑表达式类型}else{printf("表达式不合法");}return 1;
}

调试分析

  本程序实现了逻辑表达式的类型判断。“Tree__Stack.h”文件定义了带有参数值的二叉树的存储结构,并基于此结构实现了关于逻辑表达式求值的各个基本操作,再根据逻辑表达式的求值结果进行逻辑表达式的类型判定。
  此算法使用了两个工作站OPTR和OPND辅助构建了逻辑表达式二叉树,并通过二叉树的先序遍历为所读取的变量参数进行赋值,再以二叉树的后序遍历计算逻辑表达式二叉树的真值,最后根据其真值进行逻辑表达式的类型判断。
  因为需要对n个运算数的不同可能建立真值表,n个运算数的不同组合共有2n种,所以该算法的复杂度为O(2n)。
  最初程序设计时没有考虑到输入字符为‘0’和‘1’的情况,后对表达式进行了更改。首先更改了判断表达式是否合法的函数,增加了输入是‘0’和‘1’的判断。接着将‘0’和‘1’同样当作是运算数进行建树操作,在遍历赋值时,若该二叉树的结点值为‘0’和‘1’,则自动为其参数值赋值‘0’和‘1’。以此实现了运算数含有布尔类型的逻辑表达式的类型判断。

测试数据及用户手册

  程序经Codeblocks编译器编译,运行环境为windows 10操作系统,进入程序运行后提示用户输入逻辑表达式,之后进行表达式类型判断。请确保逻辑表达式输入正确,否则会提示表达式不合法。
  执行chongyanshi.exe文件,运行结果如下:

附录

源程序文件名清单:

  1. Tree__Stack.h
  2. chongyanshi.cpp

杭电数据结构课程实践-重言式判别相关推荐

  1. 杭电数字电路课程设计——移位寄存器

    杭电数字电路课程设计-移位寄存器 实验目的 (1)学习双向移位寄存器. (2)掌握灵活运用Verilog HDL语言进行各种描述与建模的技巧和方法. 模块设计 模块功能: 用于实现多功能移位寄存器,受 ...

  2. 数据结构课程实践报告——校园导航系统

    一.需求分析 (1)设计校园平面图,其中所含景点不少于10个.以图中顶点表示校内各景点,存放景点名称.代号.简介等信息:以边表示路径,存放路径长度等相关信息: (2)为来访客人提供图中任意景点相关信息 ...

  3. 《数据结构课程实践》_01_学生成绩档案管理系统_准备工作

    01_学生成绩档案管理系统_准备工作 一.实验题目与要求 二.编程语言以及开发环境 三.实验思路 1. 思考初始化数据处理 2. 学生对象处理 3. 操作处理 4. 方法描述 四.预习小结 一.实验题 ...

  4. 《数据结构课程实践》_02_隐式图的搜索问题_准备工作

    02_隐式图的搜索问题_准备工作 一.实验题目与要求 二.编程语言以及开发环境 三.实验思路 A*算法 四.预习小结 一.实验题目与要求 实验要求: 对九宫重排问题,建立图的启发式搜索求解方法: 用A ...

  5. 《数据结构课程实践》_02_隐式图的搜索问题_实现

    02_隐式图的搜索问题_实现 一.实验题目 二.编程语言以及开发环境 三.源代码 1.main类 2.节点类 3.算法类 四.运行结果 五.实验小结 一.实验题目 实验要求: 对九宫重排问题,建立图的 ...

  6. 《数据结构课程实践》_01_学生成绩档案管理系统_实现

    01_学生成绩档案管理系统_实现 一.实验题目 二.编程语言以及开发环境 三.源代码 1.学生类 2.自定义数据库类 3.数据操作类 4.总服务类 5. main类 四.运行结果 五.实验小结 一.实 ...

  7. 杭电嵌入式课程设计——上位机

    TCP服务器 课程设计要求 将电脑作为TCP服务器 处理接收到的数据 曲线绘制 图表 曲线 文件写入 工程链接 课程设计要求 如下图: 我们选择采用C#进行开发,因为串口有距离限制不方便我们采集数据, ...

  8. 杭电数字电路课程设计-实验十-JK触发器设计实验

    JK触发器设计 实验目的 实验要求 实验原理 程序代码 电路管脚图 引脚配置文件 工程文件 实验目的 学习JK触发器的原理与设计方法: 掌握灵活运用Verilog HDL语言进行各种描述与建模的技巧和 ...

  9. 《数据结构课程实践》_03_文本文件单词的检索与计数_准备工作

    03_文本文件单词的检索与计数_准备工作 一.实验题目与要求 二.编程语言以及开发环境 三.实验思路 1.朴素模式匹配算法 2.KMP算法 四.预习小结 一.实验题目与要求 实验题目: 建立一个文本文 ...

  10. 重言式判别c语言中文网,重言式判别 重言式判别源码及课程设计 c语言版.doc

    重言式判别 重言式判别源码及课程设计 c语言版 重言式的判别 题目: 一个逻辑表达式如果对于其変元的任一种取值都为真,则称为重言式:反之,如果对于其变元的任一种取值都为假,则称为矛盾式:然而,更多的情 ...

最新文章

  1. python3调用OCR识别
  2. 1.1.1. Atitit Cocos2d-JS v3.x的问题
  3. java 异常的捕获及处理
  4. python编程经典案例-一个非常适合Python新手的编程案例——投票小程序
  5. 哪些情况下索引会失效?
  6. 黑马程序员C语言基础(第三天)
  7. 数据库元数据数据字典查询_7_列出给定表的检查约束
  8. 汉诺塔问题深度剖析(python实现)
  9. hadoop Idea Win本地运行
  10. 设置图片和文字的垂直居中
  11. 使用maven启动web项目报错
  12. 19.SimLogin_case01
  13. 生成验证码封装(新版)
  14. 什么技术才值得你长期投入? | 凌云时刻
  15. 阿里云播放器的官方文档
  16. OpenCms创建网站过程图解
  17. 嵌入式linux软件数据参数保存的三种方式
  18. sklearn.datasets.make_blobs 生成符合高斯分布的点
  19. SDNU_ACM_ICPC_2019_Winter_Practice_9th题解
  20. 生活随记 - 含苞待放

热门文章

  1. Java 使用记事本编写第一个java程序
  2. 如何制作一个优秀的个人网站?
  3. 2021的第一篇文章,开个好头先
  4. java mediatype属性_Java MediaType.MULTIPART_FORM_DATA_TYPE属性代码示例
  5. 四、Flink部署 , job配置与运行
  6. 关于windows密码加密算法的说明
  7. 《私募股权基金投资基础知识》---第十章
  8. linux进入cbq文件夹,Linux流量控制(SFQ/TBFPRIO/CBQ/HTB原理介绍)
  9. 波士顿学院计算机,波士顿学院(Boston College)_快飞留学
  10. 1.名词(noun)