离散数学exp

真值表法求取主析取范式及主合取范式的实现

+++

1.明确思路

将中缀表达式转换为无需考虑优先级的后缀表达式便于机器阅读(stack实现),然后dfs(递归枚举)所有不同的真值情况,位运算给变元赋值,最后输出。

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

using namespace std;

map m = { { '!', 5 },{ '&', 4 },{ '|', 3 },{ '>', 2 },{ '=', 1 } };//通过映射来标明运算符优先级
map mm;//存放命题变元的映射
stack temp;//临时栈,处理符号入栈优先次序
string Nocal_Suffix_Formula;//未计算前的后缀表达式
set Set;
string formula;//存放输入
int num;//命题变元个数
string element;//存放命题变元

//多开一列是为了标记,如果真值情况为真则在最后一列标记为true
bool st[260][9];//存放不同情况下的真值情况

int Dfs_Cnt(int n);//返回所有情况的个数
void In_Stack(string);//中缀转后缀,入栈
void Dfs_Process();//运算后缀表达式
void Print_conjunction();//打印主合取范式
void Print_extraction();//打印主析取范式

int main()
{
	//更改dos窗口标题
	SetConsoleTitleW(L"利用真值表法求取主析取范式以及主合取范式的实现---SCL");
	cout << "支持格式: '!' 非 -- '&' 合取 -- '|' 析取 -- '>' 单条件 '=' 双条件" << endl;

	cout << "请输入命题变元个数 (字母大写): " << endl;
	cin >> num;
	cout << "Input your formula : " << endl;
	cin >> formula;

	In_Stack(formula);

	Dfs_Process();

	cout << "主析取范式: " << endl;
	Print_extraction();
	cout << endl;

	cout << "主合取范式: " << endl;
	Print_conjunction();
	cout << endl;

	system("pause");
	return 0;
}

int Dfs_Cnt(int n)
{
	return 1 << n;
}

void In_Stack(string s)
{
	for (unsigned int i = 0; i < s.size(); i++)
	{
		char x = s[i];

		if (x >= 65 && x <= 90)
		{
			Nocal_Suffix_Formula += x;
			Set.insert(x);
		}
		else if (x != '(' && x != ')')
		{
			if (temp.empty() || temp.top() == '(') temp.push(x);
			else if (m[x] > m[temp.top()]) temp.push(x);
			else
			{
				while (m[x] <= m[temp.top()] && !temp.empty())
				{
					Nocal_Suffix_Formula += temp.top();
					temp.pop();
				}

				temp.push(x);
			}
		}
		else
		{
			if (x == '(') temp.push(x);
			else
			{
				while (temp.top() != '(')
				{
					Nocal_Suffix_Formula += temp.top();
					temp.pop();
				}

				temp.pop();
			}
		}
	}

	while (!temp.empty())//最后把栈中剩余符号压入后缀表达式
	{
		Nocal_Suffix_Formula += temp.top();
		temp.pop();
	}
}

void Dfs_Process()
{
	int i = 0;
	for (auto x : Set)
	{
		element += x;//从集合中读取命题变元到element中
		mm.insert({ x, i++ });
	}

	for (int op = 0; op < Dfs_Cnt(num); op++)//所有情况
	{
		for (int i = 0; i < num; i++) st[op][i] = (op >> i & 1);//位运算取不同真值情况

		stack Cal_Suffix_Formula;//计算过的后缀表达式,只有一个元素且栈顶为'0' or '1'

		for (unsigned int i = 0; i < Nocal_Suffix_Formula.size(); i++)
		{
			char t = Nocal_Suffix_Formula[i];

			if (t >= 65 && t <= 90)//如果是命题变元,赋值后入栈
			{
				int j = st[op][mm[t]];
				Cal_Suffix_Formula.push(j);
			}
			else if (t == '!')//非运算
			{
				Cal_Suffix_Formula.top() ^= 1;
			}
			else
			{
				int r = Cal_Suffix_Formula.top();
				Cal_Suffix_Formula.pop();
				int l = Cal_Suffix_Formula.top();
				Cal_Suffix_Formula.pop();

				if (t == '&')//合取运算
				{
					if (l + r == 2) Cal_Suffix_Formula.push(1);
					else Cal_Suffix_Formula.push(0);
				}
				else if (t == '|')//析取运算
				{
					if (l + r == 0) Cal_Suffix_Formula.push(0);
					else Cal_Suffix_Formula.push(1);
				}
				else if (t == '>')//单条件
				{
					if (l == 1 && r == 0) Cal_Suffix_Formula.push(0);
					else Cal_Suffix_Formula.push(1);
				}
				else//双条件
				{
					if (l == r) Cal_Suffix_Formula.push(1);
					else Cal_Suffix_Formula.push(0);
				}
			}
		}

		st[op][num] = Cal_Suffix_Formula.top();
	}
}

void Print_extraction()
{
	int flag1 = 1;
	for (int i = 0; i < Dfs_Cnt(num); i++)//所有情况
	{
		if (st[i][num])//如果真值情况为真
		{
			if (flag1)
			{
				flag1 = 0;
				cout << '(';

				int flag2 = 1;
				for (int j = 0; j < num; j ++ )//变元真值情况
				{
					if (flag2)
					{
						flag2 = 0;
						if (!st[i][j]) cout << '!';
						cout << element[j];

						continue;
					}
					
					cout << '&';
					if (!st[i][j]) cout << '!';
					cout << element[j];
				}
				cout << ')';
			}
			else
			{
				cout << "|(";

				int flag2 = 1;
				for (int j = 0; j < num; j++)//变元真值情况
				{
					if (flag2)
					{
						flag2 = 0;
						if (!st[i][j]) cout << '!';
						cout << element[j];

						continue;
					}

					cout << '&';
					if (!st[i][j]) cout << '!';
					cout << element[j];
				}

				cout << ')';
			}
		}
	}
}

void Print_conjunction()
{
	int flag1 = 1;
	for (int i = 0; i < Dfs_Cnt(num); i++)//所有情况
	{
		if (!st[i][num])//如果真值情况为假
		{
			if (flag1)
			{
				flag1 = 0;
				cout << '(';

				int flag2 = 1;
				for (int j = 0; j < num; j++)//变元真值情况
				{
					if (flag2)
					{
						flag2 = 0;
						if (st[i][j]) cout << '!';
						cout << element[j];

						continue;
					}

					cout << '|';
					if (st[i][j]) cout << '!';
					cout << element[j];
				}
				cout << ')';
			}
			else
			{
				cout << "&(";

				int flag2 = 1;
				for (int j = 0; j < num; j++)//变元真值情况
				{
					if (flag2)
					{
						flag2 = 0;
						if (st[i][j]) cout << '!';
						cout << element[j];

						continue;
					}

					cout << '|';
					if (st[i][j]) cout << '!';
					cout << element[j];
				}

				cout << ')';
			}
		}
	}
}

你可能感兴趣的:(离散数学exp)