主要思想是:先求真值表,再根據真值表輸出主析取正規化和主合取正規化。
用!來表示非,用小寫v表示析取,用^來表示合取,用~來表示雙條件,用-來表示條件,用大寫字母來表示命題變元。
真值表的求解
① 根據命題的個數n,得出所有命題變元賦值的情況個數sum,例如n=4個命題變元,則有sum=2^4種情況,並將所有情況存入二維陣列a[i][j]中,a[i]代表第i種情況。
② 建立兩個棧,乙個用來存放操作符operator,先自己在棧裡面存放字元『#』(輸入命題公式時要最後應該加乙個字元『#』);乙個存放運算元operand。
③ 根據表示式求值的思想,讀取表示式,若是操作符,則與之前的操作符相比優先順序,若大於前者,則讀取下乙個;若相等,則說明兩者為()則彈出前者,讀取下乙個;若小於前者,則可以進行運算;
④ 若讀取的是運算元,則在陣列a中讀取運算元所對應的數,存入棧中;
⑤ 將最後的運算結果存入陣列result中,再次迴圈步驟③,迴圈sum次即可
⑥ 根據result的結果,當輸出主析取正規化時,當result[i]==1時,則輸出相應的命題變元(當命題變元為1則輸出p,為0則輸出!p),把result都遍歷一遍,將結果為1的都連在一起即可;求取主合取正規化就將result=0的輸出連在一起即可;
二、源**
第乙個標頭檔案const.h//預定義常量標頭檔案
#pragma once
#define true 1
#define false 0
#define ok 1
#define error 1
#define infeasible -1
#define overflow -2
typedef int status;
第二個標頭檔案prefunction.h//變數型別的定義與函式的宣告
#pragma once
#include"const.h"
#define stack_init_size 100
#define stackincrement 10
typedef char selemtype;
typedef int selemtype_1;
typedef struct sqstack;//操作符棧
typedef struct intstack;//運算元棧
status initstack(sqstack &s);//初始化
status gettop(sqstack s, selemtype &e);//讀棧頂
status push(sqstack &s, selemtype e);//入棧
status pop(sqstack &s, selemtype &e);//出棧
status initstack(intstack &s);// 初始化
status pop(intstack &s, selemtype_1 &e);// 出棧
status push(intstack &s, selemtype_1 e);// 入棧
char precede(selemtype e1, selemtype e2);//判斷運算元的優先順序
status bothway(int &a, selemtype b, int c);//雙向運算子操作
status truthtable(int a[65][6], int count,char ch[6]);//真值表
status proposition(char a[50], char ch[6]);//求命題的個數
第二個標頭檔案function.h
#pragma once
#include
#include
#include
#include"prefunction.h"
status initstack(sqstack &s)
status gettop(sqstack s, selemtype &e)
status push(sqstack &s, selemtype e)
*s.top++ = e;
return ok;
}status pop(sqstack &s, selemtype &e)
status initstack(intstack &s)
status pop(intstack &s, selemtype_1 &e)
status push(intstack &s, selemtype_1 e)
*s.inttop++ = e;
return ok;
}char precede(selemtype e1, selemtype e2)//判斷運算元的優先順序
//用小寫的v來表示析取;用^來表示合取;用-來表示條件;用~來表示雙條件;
status bothway(int &a, selemtype b, int c)
if (b 『^』)
if (b == 『-』)
if (b == 『~』)
return ok;
}status truthtable(int a[65][6], int count,char ch[6])//真值表
else
for (k = 0; k < s; k++)
}i++;
}
return ok;
}
status proposition(char a[50], char ch[6])//求命題的個數
if (flag == 0)
flag = 0;
j = 0;
}i++;
}return ok;
}第四個檔案是cpp檔案:xiquhequ.cpp
#include"function.h"
using namespace std;
int main() ;
printf_s("請輸入命題的個數:");
scanf("%d", &n);
printf_s("請輸入命題表示式:");
scanf("%s", exqu);
for (s = 0; s < n; s++) //求所有的情況個數sum
proposition(exqu,ch);//將n個變數變元提取出來存入字元陣列ch
truthtable(a, n, ch);//將所有情況存入陣列a中
sqstack operator;//操作符棧
intstack operand;//運算元棧
initstack(operator);//初始化
initstack(operand);//初始化
selemtype e;
int k = 0,result[65];
int i = 0,j=0;
selemtype_1 p, q;
selemtype e;
while (k < sum)
push(operand, a[k][j]);
//print(operand);
//*operand.inttop = a[k][j];// printf_s("%d", a[k][j]);
j = 0;
i++;
} else
else
break;
default:printf_s("precede函式返回值錯誤\n");
}} gettop(operator, e);
} pop(operand, q);
//printf("%d\n", q);
result[k] = q;
k++;
pop(operator, e);
//pop(operator, e);
}for (i = 0; i < n; i++)
i = 0;
while (exqu[i]!='#')
printf_s("\n");
for (k = 0; k < sum; k++)
printf_s("%d", result[k]);
printf_s("\n");
}//輸出主析取正規化
printf_s("主析取正規化\n");
for (k = 0; k < sum; k++)
printf_s("\b)v");
} }printf_s("\b \n");
//輸出主合取正規化
printf_s("主合取正規化\n");
for (k = 0; k < sum; k++)
printf_s("\b)v"); }}
printf_s("\b ");
getchar();
getchar();
return 0;}
三,輸入輸出結果
析取正規化 合取正規化 主析取和主合取
了解一下簡單析取式和簡單合取式,簡單析取式說白了就是有限個命題變項或者他們的否定用符號v連線起來的式子,比如p,p,pvq,pv q等,簡單合取式類似,但它用的符號是 析取正規化簡單來說就是幾個簡單析取式的組合,合取正規化類似。而主合取和主析取略微有些不同,主析取是由極小項及符號v組成,極小項就是簡...
C 實現求主析取正規化 主合取正規化
離散數學第一次上機實驗,突擊學完什麼是主析取正規化和主合取正規化之後粗略地想了下實現的思路。第一步自然是把輸入的式子轉換成字尾表示式。結合資料結構書上對基本四則運算的 和前人的思路勉強寫出來乙個,但還是有很多地方可能一轉頭就會忘了怎麼實現。轉換成字尾表示式之後的事情就顯得輕鬆多了。下面貼 inclu...
大二(上)離散數學 主析取正規化與主合取正規化
include include include include include define n 50 void panduan int b n int f 賦值函式 inttkh char sz n char ccu n int icu n int h0 分級運算函式 intfkh char sz...