花了一下午在写这个重言式判别,可能是我孤陋寡闻了,总感觉这个名字怪怪的,就是判断一个永真式、永假式、可满足式了,书上面就要说是"重言式"。判断这个所谓重言式,核心算法就是用真值表啦,试过所有取值。
具体代码如下(可能有bug):有些难理解的我都有注释
/**/
/********************************************************************
created: 2007/11/09

author: 刺猬
purpose: 判断表达式的属性 永真式 永假式 可满足式
*********************************************************************/
#include
<
stdio.h
>
#include
<
stdlib.h
>


typedef
struct
exp
...
{
char data;
int weight;
}
express;


express symbolrepresent[
27
];
express originalexpression[
50
];

int
trueforever
=
0
;
int
falseforever
=
0
;
int
originalexpressionlength
=
0
;
int
symbolrepresentlength
=
0
;

//
欢迎屏幕
void
ShowWelcome()

...
{
printf(" ");
printf(" ");
printf(" ");
printf(" ");
printf(" * * * * * * * * * * * * * * * * * * * * * * * * ");
printf(" * 数据结构课程设计: * ");
printf(" * * * * * * * * * * * * * * * * * * * * * * * * ");
printf(" ");
printf(" 06052711班 ");
printf(" 刺猬 ");
printf(" ");
}

//
表达式分析器 分析权值 把 | 权值设为1 &设为2 ~设为3
//处理括号的思路是:遇见左括号 把里面权值提升4 遇见右括号 把权值减去4 这样可以处理多括号问题
int
analyse(express
*
p)

...
{
int weight=0;
int length=0;
printf("请输入表达式,并以回车符为结束: ");
printf("注意:请自行检查输入表达式的正确性 ");
while(scanf("%c",&(p->data))&&p->data!=10)

...{
if(p->data>=97&&p->data<=122)
p->data=p->data-32;
switch(p->data)

...{
case '(':
weight=weight+4; //遇见左括号 把里面权值提升4
p->weight=0; //注意括号权值为0
break;
case ')':
weight=weight-4; //遇见右括号 把权值减去4
p->weight=0;
break;
case '|':
p->weight=weight+1;
break;
case '&':
p->weight=weight+2;
break;
case '~':
p->weight=weight+3;
break;
default:
p->weight=0; //imply the data is char
break;
}
p++;
length++;
}
return length;
}

//
查找表达式中权值最小的,作为子树的根节点
int
findMin(express
*
originalexpression,
int
start,
int
end)

...
{
int key=0;
int current=start;
int location=0;
while(!originalexpression[current].weight)

...{key=originalexpression[current].weight;current++;}
key=current>end?key:originalexpression[current].weight;
location=current>end?0:current;
while(current<=end)

...{
if(originalexpression[current].weight&&originalexpression[current].weight<key)

...{
location=current;
key=originalexpression[current].weight;
}
current++;
}
return location;
}


//
分析原表达式,提取所有变量 就是把所有变量罗列在一个数组内
int
makeSymbolReprentArray(express
*
originalexpression)

...
{
int length=0;

int hashmap[26]=...{0};
while(originalexpression->data!=10)

...{
if(originalexpression->data>=65&&originalexpression->data<=90)

...{
if(!hashmap[(int)(originalexpression->data-65)])

...{
hashmap[(int)(originalexpression->data-65)]=1;
symbolrepresent[length].data=originalexpression->data;
length++;
}
}
originalexpression++;
}
return length;
}

//
查找每个变量所代表值 0或1
int
findSymbolRepresent(
char
symbol)

...
{
int location=0;
while(symbolrepresent[location].data!=symbol)

...{
location++;
}
return symbolrepresent[location].weight;
}

//
虚拟构建一个二叉树 注意并没有真正构建 不过可理解为建立一个树了 算法核心是一个类似中序遍历二叉树
int
virtualCreateTree(express
*
originalexpression,
int
start,
int
end)
//
在以start和end的范围内建子树

...
{
int key=0;
if(start==end) //start==end 表明这个是叶子节点 那么里面是个变量
return findSymbolRepresent(originalexpression[start].data);
else if(start>end)
return 1; //start>end 处理~的特殊情况
else

...{
key=findMin(originalexpression,start,end); //寻找最小权值 作为子树根节点
switch(originalexpression[key].data)

...{
case '|':
return(virtualCreateTree(originalexpression,start,key-1)||virtualCreateTree(originalexpression,key+1,end));
break;
case '&':
return(virtualCreateTree(originalexpression,start,key-1)&&virtualCreateTree(originalexpression,key+1,end));
break;
case '~': //注意~的处理 实际上我是用的(1&&!右子树)
return(virtualCreateTree(originalexpression,start,key-1)&&(!virtualCreateTree(originalexpression,key+1,end)));
}
}
}

//
递归给所有变量赋值 注意递归思想用回溯二叉树理解
void
recursion(express
*
symbolrepresent,
int
i,
int
length)

...
{
if(i<length)

...{
symbolrepresent[i].weight=1; //当前变量取1
recursion(symbolrepresent,i+1,length); //递归调用下一个变量
symbolrepresent[i].weight=0; //当前变量取0
recursion(symbolrepresent,i+1,length); //递归调用下一个变量
}
else //递归结束啦

...{
if(!trueforever||!falseforever) //注意这个处理 当表达式出现可真情况和可假情况 那么断定它是可满足式 没必要做下去了

...{
switch(virtualCreateTree(originalexpression,0,originalexpressionlength-1))

...{
case 1:
trueforever++;
break;
case 0:
falseforever++;
break;
default :
break;
}
}
else
return ;
}
}

//
结果处理 没啥说的
void
resultReturn(
int
symbolrepresentlength)

...
{
int i=0;
if(trueforever&&falseforever)

...{
printf("您输入的变量名序列为: ");
while(i<symbolrepresentlength)

...{printf("%c ",symbolrepresent[i].data);i++;}
printf(" ");
printf("satisfactible ");
}
else if(!trueforever)
printf("falseforever ");
else
printf("trueforever ");
}

//
用户自己设置值 也没啥说的
void
userSetWeight()

...
{
int i=0;
printf("请依次为变量赋值,并以回车键结束: ");
while(i<symbolrepresentlength)

...{
printf("%c: ",symbolrepresent[i].data);
scanf("%d",&symbolrepresent[i].weight);
i++;
}
if(virtualCreateTree(originalexpression,0,originalexpressionlength-1))
trueforever++;
else
falseforever++;
}

//
主目录
void
mainFunctionMenus()

...
{
int menu=0;
printf("请选择您的变量设值方式: ");
printf("1.计算机自动穷举 ");
printf("2.用户指定设置 ");
scanf("%d",&menu);
if(1==menu)
recursion(symbolrepresent,0,symbolrepresentlength);
else
userSetWeight();
}


int
main()

...
{
ShowWelcome();
originalexpressionlength = analyse(originalexpression);
symbolrepresentlength = makeSymbolReprentArray(originalexpression);
mainFunctionMenus();
resultReturn(symbolrepresentlength);
//printf("%d",analyse(exp));
//printf(" %d",findMin(exp,0,analyse(exp);))
return 0;
}