树和二叉树的应用.docx
《树和二叉树的应用.docx》由会员分享,可在线阅读,更多相关《树和二叉树的应用.docx(12页珍藏版)》请在冰豆网上搜索。
树和二叉树的应用
数据结构实验报告
实验题目:
树和二叉树的应用
实验内容:
重言式判别
实验目的:
掌握树和二叉树的概念及工作原理,运用其原理及概念完成上述实验题中的内容。
实验要求:
为了使学生更好的掌握与理解课堂上老师所讲的概念与原理,实验前每个学生要认真预习所做的实验内容及编写源程序伪码(写在纸上及盘中均可)以便在实验课中完成老师所布置的实验内容。
设计原理:
1.一个逻辑表达式如果对于其变元的任一种取值均为真,则成为重言式;反之,如果对于其变元的任一种取值都为假,则称为矛盾式,然而,更多的情况下,既非重言式,也非矛盾式。
写一个程序通过真值表判别一个逻辑表达式属于上述哪一类。
基本要求如下:
(1)逻辑表达式从终端输入,长度不超过一行。
逻辑运算符包括“|”、“&”和“~”,分别表示或、与和非,运算优先程度递增,但可有括号改变,即括号内的运算优先。
逻辑变元为大写字母。
表达式中任何地方都可以含有多个空格符。
(2)若是重言式或矛盾式,可以只显示“TrueForever”或“FalseForever”,否则显示“Statisfactible”以及变量名序列,与用户交互。
若用户对表达式变元取定一组值,程序就求出并显示逻辑表达式的值。
(3)本程序先使用栈将逻辑表达式的变量进行存储,然后将栈中的元素作为二叉树的结点结构,然后根据优先级读取表达式建立二叉树,并通过逐个判断根实现对重言式的判别。
2.程序执行的命令
(1)输入逻辑表达式
(2)判断表达式是重言式还是矛盾式(3)若既不是重言式也不是矛盾式,则对变元取定值,并显示逻辑表达式的值(4)结束
3.测试数据
(1)(A|~A)&(B|~B)
(2)(A&~A)&C
(3)A|B|C|D|E|~A
(4)A&B&C&~B
(5)(A|B)&(A|~B)
(6)A&~B|~A&B;
输出结果
TrueForever
FalseForever
TrueForever
FalseForever
Statisfactible
Statisfactible
4.本程序主要分为六个模块
(1)主程序模块
voidmain()
{初始化
While{
接受命令
处理命令}
if(choice==0)退出
}
(2)对栈的操作模块。
(3)二叉树的建立模块,采用自底向上根据运算符地优先级来建立子树函数,读取逻辑表达式。
(4)逻辑运算符的优先级判别模块。
(5)重言式的识别函数模块。
(6)求值模块。
5.各个模块之间的调用关系具体如下图:
主函数模块调用:
对操作符栈和变量栈的操作模块initstack()pop()push()geittop(),逻辑运算符的优先级判别模块compa(),二叉树的建立模块creattree(),重言式的判别模块judge(),用户为变量赋值模块user(),求值模块getvalue()。
三.详细程序:
//函数头
#include
#include
#include
#include
//函数状态码定义
#defineTRUE1
#defineFALSE0
#defineOK1
#defineERROR0
#defineINFEASIBLE-2
#defineNULL0
typedefintStatus;
#defineinitstackmax100;
typedefstructbittree{
chardata;
bittree*left;//左孩子指针
bittree*right;//右孩子指针
}bittree,*bit;//二叉树类型
structstack{
bit*base;//在栈构造之前和销毁之后,base的值为NULL
inttop;//栈顶指针
intstacksize;//当前已分配的存储空间,以元素为单位
};//栈类型
//其中函数操作的伪码算法如下:
voidinitstack(stack&s)
{//构造一个空栈s
s.base=newbit[100];
s.top=-1;
s.stacksize=initstackmax;
}
voidpush(stack&s,bit&s1)
{
//插入元素s1为新的栈顶元素
s.top++;
s.base[s.top]=s1;
}
chargettop(stack&s)
{
//用s返回栈顶元素
returns.base[s.top]->data;
}
bitpop(stack&s)
{
//删除是栈顶元素,并用s返回其值
s.top--;
returns.base[s.top+1];
}
charcompa(chara,charb)
{
//按优先级的高低顺序输出运算符
charpri[6][7]={
'','|','&','~','(',')','#',
'|','>','<','<','<','>','>',
'&','>','>','<','<','>','>',
'~','>','>','>','<','>','>',
'(','<','<','<','<','=','',
'#','<','<','<','<','','='//第一次进栈时进行比对
};
for(intl=0;l<6;l++)
if(pri[l][0]==a)
break;
for(intj=0;j<7;j++)
if(pri[0][j]==b)
break;
returnpri[l][j];
}
bitcreattree(char*p,stack&vari,stack&symbol)
{
//构造二叉树
initstack(vari);
initstack(symbol);
bitm,n;
bitexam;
exam=newbittree;
exam->data='#';
push(symbol,exam);
while(*p!
='#'||(gettop(symbol)!
='#'))//第一次生成树时,*P!
=#而(gettop()->data=='#')以后则相反
{
if((int(*p)>=65)&&(int(*p)<=90))//是变量
{
exam=newbittree;
exam->data=*p;
exam->left=NULL;
exam->right=NULL;
push(vari,exam);
p++;
}
else
{
switch(compa(gettop(symbol),*p)){
case'<':
exam=newbittree;
exam->data=*p;
exam->left=NULL;
exam->right=NULL;
push(symbol,exam);
p++;
break;
case'=':
exam=pop(symbol);
p++;
break;
case'>':
exam=pop(symbol);
n=pop(vari);
exam->left=n;
exam->right=NULL;
if(exam->data!
='~')
{
m=pop(vari);
exam->right=m;
}
push(vari,exam);
break;
}//switch
}//else
}//while
bittemp=pop(symbol);
deletetemp;
returnexam;
}
intgetvalue(bitroot,intnum[])
{
//根据变量的取值组合并利用逻辑表达式的性质对树进行求值
if((root->data>=65)&&(root->data<=90))
returnnum[root->data-65];
else{
switch(root->data){
case'|':
returngetvalue(root->left,num)||getvalue(root->right,num);
case'&':
returngetvalue(root->left,num)&&getvalue(root->right,num);
case'~':
return!
getvalue(root->left,num);
}
}
}
voiduser(bitroot,intm,charb[])
{
//若用户对表达式变元取定一组值,程序就求出并显示逻辑表达式的值
inta[30];intn;
for(intk=0;k<=m;k++)
{
printf("请输入n的值\n");
scanf("%d",&n);
a[b[k]-65]=n;
}
if(getvalue(root,a))
printf("True");
else
printf("False");
}
voidjudge(bitroot,charbo[],intnu)
{
//重言式的判别
intsample[30];charbl[20],t;intm=0,lzq,value,count=0,tu=0,fa=0,sat=0;
for(intk=0;kif(bo[k]>=65&&bo[k]<=90)
{
intmark=0;
for(intj=0;jif(bl[j]==bo[k]){
mark=1;break;
}
if(mark==0){
bl[m]=bo[k];
m++;
}
}
intnumall=(int)pow(2,m);
m--;
for(inti=0;i{lzq=m;
for(intj=0;j{
sample[bl[lzq]-65]=(i>>j)%2;
lzq--;
}
value=getvalue(root,sample);
if(value)
{
tu++;
if(fa>0){
printf("satisfactible");
sat=1;
break;
}
if(tu==numall){
printf("Tureforever\n");
}
}
else
{fa++;
if(tu>0){
printf("satisfactible\n");
sat=1;
break;
}
else{
if(fa==numall)
printf("Falseforever\n");
}
}
}
if(sat==1){
printf("请给变量赋值,c代表继续,e代表停止");
scanf("%c",&t);
while(t){
if(t=='c')
{
for(i=0;i<=m;i++)
printf("%c",&bl[i]);
user(root,m,bl);
}
else
break;
}
}
}
//3.主函数
intmain(intargc,char*argv[])
{
charstr[300],str1[100],*p;intn,len=0,j;intk=0,m,count=0;
stackvari,symbol;
bitroot;
printf("请输入0或1,0--终止程序1--继续程序\n");
scanf("%d",&m);
while(m)
{
count++;
if(m==1)
{
if(count>1)delete[]vari.base;
k=0;
printf("请输入表达式(变量以大写形式输入)");
gets(str);
len=strlen(str);
for(j=0;jif(str[j]!
='')
{
str1[k]=str[j];
k++;
}
str1[k]='#';
len=strlen(str1);
p=str1;
root=creattree(p,vari,symbol);
judge(root,str1,len);
}
else
{
if(count>1)delete[]vari.base;
break;
}
}
return0;
}
问题及解决方法:
1.开始时,将栈中元素作为二叉树的结点结构很是复杂,建立二叉树后,只需按照遍历逐个进行判断即可顺利实现重言式的判别。
2.模块设计包括结构体模块,操作算法模块和主函数模块,操作算法模块主要包括了栈和树的函数。
3.本程序先使用栈将逻辑表达式的变量进行存储,然后将栈中的元素作为二叉树的结点结构,然后根据优先级读取表达式建立二叉树,并通过逐个判断根实现对重言式的判别,实现时调试顺利。