最优二叉树
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
#include
#include
typedef struct exp{
char data;
int weight;
int leftclild;
int rightchild;
}express;
express symbolrepresent[27];
express originalexpression[50];
int trueforever=0;
int falseforever=0;
int originalexpressionlength =0;
int symbolrepresentlength=0;
//欢迎屏幕
void ShowWelcome()
{
printf(" * * * * * * * * * * * * * * * * * * * * * * * * \n");
printf(" * 数据结构课程设计: 重言式判别 * \n");
printf(" * * * * * * * * * * * * * * * * * * * * * * * *\n ");
printf("\n ");
printf("计算机科学与技术 ");
printf(" 邢秋双1012119 ");
printf("\n ");
}
//表达式分析器 分析权值 把 | 权值设为1 &设为2 ~设为3
//处理括号的思路是:遇见左括号 把里面权值提升4 遇见右括号 把权值减去4 这样可以处理多括号问题
int analyse(express *p)
{
int weight=0;
int length=0;
printf("请输入表达式,并以回车符为结束:\n ");
printf("(注意:请自行检查输入表达式的正确性)\n ");
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; //意味着数据是字符型
break;
}
p++;
length++;
}
return length;
}
//查找表达式中权值最小的,作为子树的根节点
int findMin(express *originalexpression,int leftchild,int rightchild)
{
int key=0;
int current=leftchild;
int location=0;
while(!originalexpression[current].weight)
{key=originalexpression[current].weight;current++;}
key=current>rightchild?key:originalexpression[current].weight;
location=current>rightchild?0:current;
while(current<=rightchild)
{
if(originalexpression[current].weight&&originalexpression[current].weight
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 leftchild,int rightchild) //在以leftchild和rightchild的范围内建子树
{
int key=0;
if(leftchild==rightchild) //leftchild==rightchild 表明这个是叶子节点 那么里面是个变量
return findSymbolRepresent(originalexpression[leftchild].data);
else if(leftchild>rightchild)
return 1; //leftchild>rightchild 处理~的特殊情况
else
{
key=findMin(originalexpression,leftchild,rightchild); //寻找最小权值 作为子树根节点
switch(originalexpression[key].data)
{
case '|':
return(virtualCreateTree(originalexpression,leftchild,rightchild-1)||virtualCreateTree(originalexpression,key+1,rightchild));
break;
case '&':
return(virtualCreateTree(originalexpression,leftchild,rightchild-1)&&virtualCreateTree(originalexpression,key+1,rightchild));
break;
case '~': //实际上我是用的(1&&!右子树)
return(virtualCreateTree(originalexpression,leftchild,rightchild-1)&&(!virtualCreateTree(originalexpression,key+1,rightchild)));
}
}
}
//递归给所有变量赋值 注意递归思想用回溯二叉树理解
void recursion(express *symbolrepresent,int i,int length)
{
if(i
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,originalexpressionl
ength-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
printf(" ");
printf("satisfactible\n ");
}
else if(!trueforever)
printf("falseforever\n ");
else
printf("trueforever \n");
}
//用户自己设置值
void userSetWeight()
{
int i=0;
printf("请依次为变量赋值,并以回车键结束: ");
while(i
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);
return 0;
}