重言式判别 (数据结构课程设计)

花了一下午在写这个重言式判别,可能是我孤陋寡闻了,总感觉这个名字怪怪的,就是判断一个永真式、永假式、可满足式了,书上面就要说是"重言式"。判断这个所谓重言式,核心算法就是用真值表啦,试过所有取值。

具体代码如下(可能有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;
}
 
  • 7
    点赞
  • 48
    收藏
    觉得还不错? 一键收藏
  • 20
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 20
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值