正规式转NFA

#include<iostream>
#include<cstring>
#include<string>
#include<stack>
#include<vector>
#include<set>
#include<queue>

#define MAX 128

using namespace std;

typedef set<int> IntSet;
typedef set<char> CharSet;

/********************表达式转NFA********************/

struct NfaState				/*定义NFA状态*/
{

	int index;				/*NFA状态的状态号*/

	char input;				/*NFA状态弧上的值*/
	int chTrans;			/*NFA状态弧转移到的状态号*/

	IntSet epTrans;			/*当前状态通过ε转移到的状态号集合*/
};

struct NFA
{

	NfaState* head;			/*NFA的头指针*/
	NfaState* tail;			/*NFA的尾指针*/
};

NfaState NfaStates[MAX];	/*NFA状态数组*/
int nfaStateNum = 0;		/*NFA状态总数*/

/*从状态n1到状态n2添加一条弧,弧上的值为ch*/
void add(NfaState* n1, NfaState* n2, char ch)
{

	n1->input = ch;
	n1->chTrans = n2->index;
}

/*从状态n1到状态n2添加一条弧,弧上的值为ε*/
void add(NfaState* n1, NfaState* n2)
{

	n1->epTrans.insert(n2->index);
}

/*新建一个NFA(即从NFA状态数组中取出两个状态)*/
NFA creatNFA(int sum)
{

	NFA n;

	n.head = &NfaStates[sum];
	n.tail = &NfaStates[sum + 1];

	return n;
}

/*在字符串s第n位后面插入字符ch*/
void insert(string& s, int n, char ch)
{

	s += '#';

	for (int i = s.size() - 1; i > n; i--)
	{
		s[i] = s[i - 1];
	}

	s[n] = ch;
}

/*对字符串s进行预处理,在第一位是操作数、‘*’或‘)’且第二位是操作数或‘(’之间加入连接符‘&’*/
void preprocess(string& s)
{

	int i = 0, length = s.size();

	while (i < length)
	{
		if ((s[i] >= 'a' && s[i] <= 'z') || (s[i] == '*') || (s[i] == ')'))
		{
			if ((s[i + 1] >= 'a' && s[i + 1] <= 'z') || s[i + 1] == '(')
			{

				insert(s, i + 1, '&');
				length++;
			}
		}

		i++;
	}
}

/*中缀转后缀时用到的优先级比较,即为每个操作符赋一个权重,通过权重大小比较优先级*/
int priority(char ch)
{

	if (ch == '*')
	{
		return 3;
	}

	if (ch == '&')
	{
		return 2;
	}

	if (ch == '|')
	{
		return 1;
	}

	if (ch == '(')
	{
		return 0;
	}
}

/*中缀表达式转后缀表达式*/
string infixToSuffix(string s)
{

	preprocess(s);			/*对字符串进行预处理*/

	string str;				/*要输出的后缀字符串*/
	stack<char> oper;		/*运算符栈*/

	for (int i = 0; i < s.size(); i++)
	{

		if (s[i] >= 'a' && s[i] <= 'z')	/*如果是操作数直接输出*/
		{
			str += s[i];
		}
		else							/*遇到运算符时*/
		{

			if (s[i] == '(')			/*遇到左括号压入栈中*/
			{
				oper.push(s[i]);
			}

			else if (s[i] == ')')	/*遇到右括号时*/
			{

				char ch = oper.top();
				while (ch != '(')		/*将栈中元素出栈,直到栈顶为左括号*/
				{

					str += ch;

					oper.pop();
					ch = oper.top();
				}

				oper.pop();				/*最后将左括号出栈*/
			}
			else					/*遇到其他操作符时*/
			{

				if (!oper.empty())			/*如果栈不为空*/
				{

					char ch = oper.top();
					while (priority(ch) >= priority(s[i]))	/*弹出栈中优先级大于等于当前运算符的运算符*/
					{

						str += ch;
						oper.pop();

						if (oper.empty())	/*如果栈为空则结束循环*/
						{
							break;
						}
						else ch = oper.top();
					}

					oper.push(s[i]);		/*再将当前运算符入栈*/
				}

				else				/*如果栈为空,直接将运算符入栈*/
				{
					oper.push(s[i]);
				}
			}
		}
	}

	/*最后如果栈不为空,则出栈并输出到字符串*/
	while (!oper.empty())
	{

		char ch = oper.top();
		oper.pop();

		str += ch;
	}

	cout << "*******************************************" << endl << endl;
	cout << "中缀表达式为:" << s << endl << endl;
	cout << "后缀表达式为:" << str << endl << endl;

	return str;
}

/*后缀表达式转nfa*/
NFA strToNfa(string s)
{

	stack<NFA> NfaStack;		/*定义一个NFA栈*/

	for (int i = 0; i < s.size(); i++)		/*读取后缀表达式,每次读一个字符*/
	{

		if (s[i] >= 'a' && s[i] <= 'z')		/*遇到操作数*/
		{

			NFA n = creatNFA(nfaStateNum);		/*新建一个NFA*/
			nfaStateNum += 2;					/*NFA状态总数加2*/

			add(n.head, n.tail, s[i]);			/*NFA的头指向尾,弧上的值为s[i]*/

			NfaStack.push(n);					/*将该NFA入栈*/
		}

		else if (s[i] == '*')		/*遇到闭包运算符*/
		{

			NFA n1 = creatNFA(nfaStateNum);		/*新建一个NFA*/
			nfaStateNum += 2;					/*NFA状态总数加2*/

			NFA n2 = NfaStack.top();			/*从栈中弹出一个NFA*/
			NfaStack.pop();

			add(n2.tail, n1.head);				/*n2的尾通过ε指向n1的头*/
			add(n2.tail, n1.tail);				/*n2的尾通过ε指向n1的尾*/
			add(n1.head, n2.head);				/*n1的头通过ε指向n2的头*/
			add(n1.head, n1.tail);				/*n1的头通过ε指向n1的尾*/

			NfaStack.push(n1);					/*最后将新生成的NFA入栈*/
		}

		else if (s[i] == '|')		/*遇到或运算符*/
		{

			NFA n1, n2;							/*从栈中弹出两个NFA,栈顶为n2,次栈顶为n1*/
			n2 = NfaStack.top();
			NfaStack.pop();

			n1 = NfaStack.top();
			NfaStack.pop();

			NFA n = creatNFA(nfaStateNum);		/*新建一个NFA*/
			nfaStateNum += 2;					/*NFA状态总数加2*/

			add(n.head, n1.head);				/*n的头通过ε指向n1的头*/
			add(n.head, n2.head);				/*n的头通过ε指向n2的头*/
			add(n1.tail, n.tail);				/*n1的尾通过ε指向n的尾*/
			add(n2.tail, n.tail);				/*n2的尾通过ε指向n的尾*/

			NfaStack.push(n);					/*最后将新生成的NFA入栈*/
		}

		else if (s[i] == '&')		/*遇到连接运算符*/
		{

			NFA n1, n2, n;				/*定义一个新的NFA n*/

			n2 = NfaStack.top();				/*从栈中弹出两个NFA,栈顶为n2,次栈顶为n1*/
			NfaStack.pop();

			n1 = NfaStack.top();
			NfaStack.pop();

			add(n1.tail, n2.head);				/*n1的尾通过ε指向n2的尾*/

			n.head = n1.head;					/*n的头为n1的头*/
			n.tail = n2.tail;					/*n的尾为n2的尾*/

			NfaStack.push(n);					/*最后将新生成的NFA入栈*/
		}
	}

	return NfaStack.top();		/*最后的栈顶元素即为生成好的NFA*/
}

/*打印NFA函数*/
void printNFA(NFA nfa)
{

	cout << "***************     NFA     ***************" << endl << endl;
	cout << "NFA总共有" << nfaStateNum << "个状态," << endl;
	cout << "初态为" << nfa.head->index << ",终态为" << nfa.tail->index << "。" << endl << endl << "转移函数为:" << endl;

	for (int i = 0; i < nfaStateNum; i++)		/*遍历NFA状态数组*/
	{

		if (NfaStates[i].input != '#')			/*如果弧上的值不是初始时的‘#’则输出*/
		{
			cout << NfaStates[i].index << "-->'" << NfaStates[i].input << "'-->" << NfaStates[i].chTrans << '\t';
		}

		IntSet::iterator it;					/*输出该状态经过ε到达的状态*/
		for (it = NfaStates[i].epTrans.begin(); it != NfaStates[i].epTrans.end(); it++)
		{
			cout << NfaStates[i].index << "-->'" << ' ' << "'-->" << *it << '\t';
		}

		cout << endl;
	}
}


int main()
{

	//测试样例1
	//string str = "(a|b)*abb";
	string str;
	cin>>str;
	str = infixToSuffix(str);		/*将中缀表达式转换为后缀表达式*/

	/***初始化所有的数组***/
	int i, j;
	for (i = 0; i < MAX; i++)
	{

		NfaStates[i].index = i;
		NfaStates[i].input = '#';
		NfaStates[i].chTrans = -1;
	}

	NFA n = strToNfa(str);
	printNFA(n);

	return 0;
}



  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值