四 计算命题演算公式的真值
一.实验题目
所谓命题演算公式是指由逻辑变量(其值为 TRUE 或 FALSE)和逻辑运算符∧(AND)、
∨(OR)和┐(NOT)按一定规则所组成的公式(蕴含之类的运算可以用∧、∨和┐来表
示)。公式运算的先后顺序为┐、∧、∨,而括号()可以改变优先次序。已知一个命题演
算公式及各变量的值,要求设计一个程序来计算公式的真值。
要求:
(1)利用二叉树来计算公式的真值。首先利用堆栈将中缀形式的公式变为后缀形式;
然后根据后缀形式,从叶结点开始构造相应的二叉树;最后按后序遍历该树,求各子树之值,
即每到达一个结点,其子树之值已经计算出来,当到达根结点时,求得的值就是公式之真值。
(2)逻辑变元的标识符不限于单字母,而可以是任意长的字母数字串。
(3)根据用户的要求显示表达式的真值表。
二.实验设计
1. 设计思想
(1)数据结构设计
a 建立一个链式堆栈,实现括号的匹配问题。
b 建立一个顺序堆栈,来实现中缀转后缀并实现二叉树的打印。
(2)算法设计
a.括号匹配 b 中缀转后缀 c 打印二叉树和真值表
2. 设计表示
自定义和调用的函数如下所示:
#include"value.h"
#include"Convert.h"
#include
#include
#include
#include
#include
函数说明如下
SeqStack1;
void StackInitiate1(SeqStack1 *S)
void StackPush1(SeqStack1 *S,DataType x)
void StackPop1(SeqStack1 *S,DataType *x)
int StackTop1(SeqStack1 S,DataType *d)
SeqStack2;
void StackInitiate2(SeqStack2 *S)
BiTreeNode * StackPop2(SeqStack2 *S)
BiTreeNode;
void Initiate(BiTreeNode **root)
/*定义一个堆栈 SeqStack1*/
/*初始化堆栈 1,栈底为‘#’*/
/*将元素压入堆栈 1*/
/*弹出堆栈 1 的栈顶元素*/
/*取堆栈 1 的栈顶元素*/
/*定义一个顺序堆栈 SeqStack2*/
/*初始化堆栈 2*/
/*从堆栈 2 中弹出栈顶元素*/
/*定义二叉树的结点*/
/*初始化树的根结点*/
void print(BiTreeNode *bt,int n)
void StackPush2(SeqStack2 *S,BiTreeNode *x)
int Convert(char a[500],char b[500][100],SeqStack1 *S,int n)
/*逆时针打印二叉树*/
/*将二叉树结点压入堆栈 2*/
/*将待求表达式转换为
后缀形式*/
BiTreeNode * BuildTree(char b[500][100],int n)/*根据表达式的后缀形式,构造相应
的二叉树*/
/*定义了链式堆栈用于下面检测表达式的括号匹配*/
/*初始化堆栈*/
/*检测堆栈是否为空的函数*/
LSNode;
void StackInitiate(LSNode** head)
int StackNotEmpty(LSNode* head)
int StackPush(LSNode* head,DataType x) /*将元素入栈*/
int StackPop(LSNode* head,DataType* d) /*弹出栈顶元素*/
int StackTop(LSNode* head,DataType *d) /*取栈顶元素*/
void Destroy(LSNode* head)
void ExplsCorrect(char exp[])
i
/*撤消*/
/*检测输入表达式的括号匹配函数*/
3. 详细设计
void StackInitiate(LSNode** head)
{
if((*head=(LSNode*)malloc(sizeof(LSNode)))==NULL)exit(1);
(*head)->next=NULL;
} /*初始化堆栈*/
int StackNotEmpty(LSNode* head)
{
if(head->next==NULL)return 0;
else return 1;
}
/*检测堆栈是否为空的函数,若为空,返回 0,否则返回 1*/
typedef struct snode
{
DataType data;
struct snode* next;
}LSNode;
/*定义了链表的结点用于下面检测表达式的括号匹配*/
int StackPop(LSNode* head,DataType* d)
{
LSNode* p=head->next;
if(p==NULL)
{
cout<<"堆栈已空出错"<
return 0;
}
head->next=p->next;
*d=p->data;
free(p);
return 1;
}
/*弹出栈顶元素*/
int StackPush(LSNode* head,DataType x)
{
LSNode* p;
if((p=(LSNode*)malloc(sizeof(LSNode)))==NULL)
{
cout<<"内存空间不足无法插入!"<data=x;
p->next=head->next;
head->next=p;
return 1;
}
/*将元素入栈*/
int StackTop(LSNode* head,DataType *d)
{
LSNode* p=head->next;
if(p==NULL)
{
cout<<"堆栈已空出错"<data;
return 1;
}
/*取栈顶元素*/
void Destroy(LSNode* head)
{
LSNode* p,*p1;
p=head;
while(p!=NULL)
{
p1=p;
p=p->next;
free(p1);
}
}/*撤消*/
三.调试分析
在运行程序的过程中,碰到了一些错误,其中有很多是括号和分号的问题,看来以后写
程序要更加细心才行。
四.用户手册
此程序中'&''|''~'分别代表代表'与' '或' '非'运算
首先输入一个包含变量,运算符表达式,再按 Enter 执行。再依次输入各变量的值。如
果不继续输入,按 0 退出。再按 y 继续或者 n 退出。
五.测试数据及测试结果
输入 a&b&c
六.源程序清单
typedef struct
{
DataType stack[1000];
int top;
}SeqStack1;
//用来实现将输入的中缀表达式转换为后缀表达式
void StackInitiate1(SeqStack1 *S)
//初始化,栈底为#
{
}
S->stack[0]='#';
S->top = 1;
void StackPush1(SeqStack1 *S,DataType x)
{
//将元素压入堆栈 1
S->stack[S->top] = x ;
S->top++;
}
void StackPop1(SeqStack1 *S,DataType *x)
{
S->top--;
*x = S->stack[S->top];
}
//弹出堆栈 1 的栈顶元素
int StackTop1(SeqStack1 S,DataType *d)
{
//取堆栈 1 的栈顶元素
if(S.top<=0)
{
cout<<"堆栈已空!\n"<
default:return 0;
}
}
int Convert(char a[500],char b[500][100],SeqStack1 *S,int n)//将待求表达式子转换为后缀形式
{
int i,j,k=0;
char character;
for(i=0;i
if(!IsOptr(a[i]))
{
j=0;
while(!IsOptr(a[i]))
{
b[k][j]=a[i];
j++;
i++;
}
i--;
b[k][j]=0;
k++;
}
}
return 0;
}
#include
typedef struct Node
{
DataType data[1000];
struct Node *leftChild;
struct Node *rightChild;
struct Node *parent;
}BiTreeNode;//定义二叉树的结点
typedef struct
{
BiTreeNode
* address[1000];
面构造二叉树时,对结点的保存
int top;
}SeqStack2;
void Initiate(BiTreeNode **root)
{
//当前为变量时,直接存入二维数组 b 中
//表示该行结束
//定义成树结点的指针,方便下
//初始化树的根结点
*root = (BiTreeNode * ) malloc(sizeof(BiTreeNode));
(*root)->leftChild=NULL;
(*root)->rightChild=NULL;
(*root)->parent=NULL;
}