数据结构重言式

记录一下数据结构实验课程——重言式

题目

一个逻辑表达式如果对于其变元的任一种取值都为真,则称重言式;反之,如果对于其任一种取值都为假,则称矛盾式;其它情形称为可满足式。编写程序,判断逻辑表达式属于哪种情形。

1.建立逻辑二叉树表达式
2.写一程序,根据逻辑二叉表达式对包括逻辑变量的逻辑表达式进行重言式判别

个人思路

  1. 首先由四则运算思路联想,先找到最小级运算符,然后左右两边看作整体,进行整体运算。
  2. 左右两边同样寻找最小级运算符,由此可以进行递归运算,构建二叉树
  3. 后序遍历,读取二叉树,遇到数字压栈,遇到运算符弹出所需的变量数目。
  4. 运算弹出的变量,并把结果重新压栈,继续参与计算。
  5. 值得注意,逻辑表达式需要列出真值表,我通过循环列真值表,每一次循环,计算一次。
  6. 每一次循环计算若为1,则flag1值变化,0,则flag0变化,
  7. 最终看这两变量的值判断永真永假还是可满足

代码


#include<iostream>
#include<string>
using namespace std;

typedef struct SNode{
    char data;
    struct SNode *next;
}SNode,*pSNode;//栈结点

typedef struct Stack{
    pSNode  top;
}Stack;//栈

void Push(Stack &S,int e){
    pSNode p =new SNode;
    p->data = e;
    p->next = S.top;
    S.top = p;
}//入栈

void Pop(Stack &S,int &e){
    if(S.top==NULL)
        return;
    pSNode p = S.top;
    e = p->data;
    S.top = p->next;
    delete p;
}//出栈

typedef struct TreeNode{
    char data;
    struct TreeNode *lchild,*rchild;
}TNode,*pTNode;//二叉树结点

int FindMinOper(string &T,int start,int end){//找到最小级运算符
    int min=-1;
    if(start == end){
        return start;
    }
    if(T[start]=='('&&T[end]==')'){//剩下的是括号,返回时去掉括号
        return FindMinOper(T,start+1,start-1);
    }
    for(int i = start ; i <= end ; i++){
        if(T[i]=='('){//中间的括号直接跳过
            while(T[i]!=')'){
                i++;
            }
            i++;
        }
        if(T[i]=='&'||T[i]=='|'||T[i]=='!'){
            if(T[i]=='|'&&(T[min] != '|' || min == -1)){
                min = i;
            }
            else if(T[i]=='&'&&(T[min] == '!'|| min==-1)){
                min = i;
            }
            else if(T[i]=='!'&&(min==-1)){
                min = i;
            }
        }
    }
    return min;
}
void creatTree(int start,int end,string &T,pTNode &node){//递归构造二叉树
     if(T[start]=='('&&T[end]==')'){
        start++;
        end--;
    }
    int min = FindMinOper(T,start,end);
    //cout<<"the min:";
    //cout<<min<<endl;
    node = new TNode;
    node->lchild=NULL;
    node->rchild=NULL;
    node->data = T[min];
    if(start<=min-1){//左边还有内容,可以构造左子树
        creatTree(start,min-1,T,node->lchild);
    }
    else{
        node->lchild = NULL;
    }
    if(min+1<=end){//可以构造右子树
        creatTree(min+1,end,T,node->rchild);
    }
    else{
        node->rchild = NULL;
    }
}
void VisitAndStackAndCal(pTNode &phead,Stack &stack1,int* value){//访问并且计算
    int e1;
    int e2;
    if(phead->lchild){//后序遍历
        VisitAndStackAndCal((phead->lchild),stack1,value);
    }

    if(phead->rchild){
        VisitAndStackAndCal((phead->rchild),stack1,value);
    }

    if(phead->data=='&'||phead->data=='|'||phead->data=='!'){
        if(phead->data=='!'){
            Pop(stack1,e1);
            if(e1==0){
                Push(stack1,1);
            }
            else if(e1==1){
                Push(stack1,0);
            }
        }
        else{
            if(phead->data=='&'){
                Pop(stack1,e1);
                Pop(stack1,e2);
                //cout<<e1<<"&"<<e2<<endl;
                Push(stack1,(e1&&e2));
                //cout<<"push"<<(e1&&e2)<<endl;
            }
            else if(phead->data=='|'){
                Pop(stack1,e1);
                Pop(stack1,e2);
                Push(stack1,(e1||e2));
                //cout<<"push"<<(e1||e2)<<endl;
            }
        }
    }
    else{
        Push(stack1,value[phead->data-'A']);
        //cout<<"Push"<<value[phead->data-'A']<<endl;
    }
}
void xunhuan(pTNode &phead,Stack &stack1,int* value,int n,int* flag1,int* flag0){
    int count = n;
    for(int i=0;i<2;i++){//循环列真值表
            value[n-1]=i;
            //cout<<n<<"the value:";
            //cout<<value[n-1]<<endl;
            if(count>1){
                xunhuan(phead,stack1,value,--count,flag1,flag0);
            }
            count = n;
            if(count==1){
                VisitAndStackAndCal(phead,stack1,value);
                int ans;
                Pop(stack1,ans);
                //cout<<"ans:"<<ans<<endl;
                if(ans==1){
                     (*flag1)++;
                }
                else if(ans==0){
                    (*flag0)++;
                }
            }
        }
}
void trueth(pTNode &phead,Stack &stack1,int n,int* value,int* flag1,int* flag0){
    xunhuan(phead,stack1,value,n,flag1,flag0);
    //cout<<"flag1:"<<*flag1<<endl;
    //cout<<"flag0:"<<*flag0<<endl;
        if(*flag1>-1&&*flag0>-1){
            cout<<"satisfied"<<endl;
        }
        else if(*flag1>-1&&*flag0==-1){
            cout<<"always true"<<endl;
        }
        else if(*flag1==-1&&*flag0>-1){
            cout<<"always false"<<endl;
        }
}

int main(){
    int n;//几个变量;
    int flag0= -1,flag1=-1;
    cout<<"put the number of variable"<<endl;
    cin >> n;
    int* value = new int[n];
    string str;
    Stack stack1;
    Stack stack2;

    pTNode Thead = NULL;

    stack1.top = NULL;//存放变量
    stack2.top=NULL;
    cout<<"put the logical expression"<<endl;
    cin.get();
    getline(cin,str);

    int start = 0;
    int end = str.length()-1;
    creatTree(start, end,str,Thead);//构造二叉树
    trueth(Thead,stack1,n,value,&flag1,&flag0);//后序遍历并入栈判断

    system("pause");
    return 0;
}

  • 9
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值