【离散数学】计算主析取范式(基于真值表)

本文介绍了如何根据给定的命题公式计算主析取范式。通过二进制赋值模拟和处理中缀表达式,对命题变元进行赋值并构建二叉表达树,以后序遍历方式求解。样例输入和算法分析帮助理解过程。
摘要由CSDN通过智能技术生成

【问题描述】
请根据给定的命题公式,计算其真值为T的小项,列出主析取范式,并输出结果。
【输入形式】
输入一个字符串(字符串长度<=50)形式的命题公式,以回车表示输入结束。其中的命题公式为仅包含原子命题、联结词和括号的合式公式。联结词仅包含下述5中联结词:
1、否定,表示为“!”
2、合取,表示为“*”
3、析取,表示为“|”
4、条件,表示为“-”
5、双条件,表示为“=”
例如:
(P-Q)-R
注意:输入符号均采用英文输入。
【输出形式】
输出一个以单个空格分隔的字符串,字符串中各项分别对应主析取范式中小项的序号。
如(P-Q)- R对应的小项为
则输出1 3 4 5 7
注意:其中的原子命题按字母表排序。

【样例输入】

(P-Q)-R

【样例输出】

1 3 4 5 7

算法分析
显然将给出的公式中提取出它的n个不同命题变元,显然每个变元的赋值非真即假,而他们的组合情况恰有2^n种情况,故而可用二进制的形式来模拟,对n个变元进行赋值。在二进制赋值中我们采用模拟二进制过程的算法,从0000开始,从最后一位开始加1,直至最后结果为1111;显然这就包含了2 n种情况。
具体实现代码如下

void truth(int times)
{
   
    int i = argument.size() - 1;
    while (times)
    {
   
        a[i] = (times & 1);
        times >>= 1;
        --i;
    }
    int len = argument.size();
    for (i = 0; i < len; ++i)
        mp[argument[i]] = a[i];
    // display
    for (int i = 0; i < len; ++i)
        cout << a[i] << '\t';
    cout << endl;
}

再者,显然该命题公式就是一个中缀表达式的式子,故而在有了对命题变元的赋值后,我们可以采用处理计算中缀表达式的值的算法来做。首先最一般的算法就是写一个模拟过程,采用栈存储,利用运算符的优先级大小关系进行运算。但值得注意的是,中缀表达式可以处理成二叉表达树的形式,如下图
在这里插入图片描述
显然,运算符都将会是分支结点,而命题变元将会是叶子结点,因此在构建出二叉表达树后,我们采用后序遍历进行运算直至根节点,便可得出一组赋值的情况,而二叉树的建立也是采用栈的存储,利用优先级关系进行建树。
具体解释将在代码中给出。

/*
 * @Author: csc
 * @Date: 2020-12-08 14:12:16
 * @LastEditTime: 2020-12-11 00:02:42
 * @LastEditors: Please set LastEditors
 * @Description: In User Settings Edit
 * @FilePath: \code\data structure\ls_tree.cpp
 */
#include <iostream>
#include <algorithm>
#include <string>
#include <string.h>
#include <cmath>
#include <map>
#include <vector>
#include <stack>
using namespace std;
// 联结词优先 ! * | - =  高到低
unsigned char prior[7][7] = {
    //比较大小关系
    '>', '<', '<', '<', '<', '<', '>', 
    '>', '>', '<', '<', '<', '<', '>', 
    '>', '>', '>', '<', '<', '<', '>', 
    '>', '>', '>', '>', '<', '<', '>', 
    '>', '>', '>', '>', '<', '>', '>', 
    '<', '<', '<', '<', '<', '<', '=', 
    '>', '>', '>', '>', '>', ' ', '>', };
char opset[7] = {
   '=', '-', '/', '*', '!', '(', ')'};
/**
 * @description: 假设有两个变量x,y;不妨设x为先出现的变量,则它对应的
 * 应为行数,y则对应列数,此时便可列优先级方阵,其中‘<'代表x的优先级小于y
 */
int returnOpOrd(char op, char *TestOp) // 返回运算符对应的下标
{
   
    int i;
    for (i = 0; i < 7; i++)
    {
   
        if (op == TestOp[
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值