C# 使用VS实现NFA转DFA功能:将NFA文件数据转换为DFA并显示在容器中
由于不能定义其他函数或类,所以需要在button7_Click函数中实现NFA转DFA的功能。以下是实现思路:
-
定义一个List<List
>类型的变量'nfaStates'来存储NFA中的状态集合,其中'nfaStates[i]'表示第i个状态所能到达的状态集合。 -
定义一个List
类型的变量'symbols'来存储NFA中的符号集合。 -
定义一个List
类型的变量'startStates'来存储NFA中的开始状态。 -
定义一个List
类型的变量'acceptStates'来存储NFA中的接受状态。 -
根据读取到的NFA数据,初始化'nfaStates'、'symbols'、'startStates'、'acceptStates'。
-
定义一个List<List
>类型的变量'dfaStates'来存储DFA中的状态集合,其中'dfaStates[i]'表示DFA中第i个状态所能到达的状态集合。 -
定义一个List
类型的变量'dfaStartState'来存储DFA中的开始状态。 -
定义一个List
类型的变量'dfaAcceptStates'来存储DFA中的接受状态。 -
根据初始化的'nfaStates'、'symbols'、'startStates'、'acceptStates',计算出DFA中的状态集合'dfaStates'、开始状态'dfaStartState'、接受状态'dfaAcceptStates'。
-
将计算出的DFA中的状态集合、开始状态、接受状态显示在'listView2'中。
以下是代码实现:
private void button7_Click(object sender, EventArgs e)
{
// 初始化NFA数据
List<List<int>> nfaStates = new List<List<int>>();
List<char> symbols = new List<char>();
List<int> startStates = new List<int>();
List<int> acceptStates = new List<int>();
int lineIndex = 0;
while (lineIndex < lines.Length)
{
string line = lines[lineIndex];
if (line.StartsWith("开始符:"))
{
startStates.Add(int.Parse(line.Substring(4)));
}
else if (line.StartsWith("终结符:"))
{
string[] symbolStrs = line.Substring(4).Split(';');
foreach (string symbolStr in symbolStrs)
{
if (!string.IsNullOrEmpty(symbolStr))
{
symbols.Add(symbolStr[0]);
}
}
}
else
{
string[] parts = line.Split(' ');
int fromState = int.Parse(parts[0]);
char symbol = parts[1][0];
int toState = int.Parse(parts[2]);
while (nfaStates.Count <= fromState)
{
nfaStates.Add(new List<int>());
}
nfaStates[fromState].Add(toState);
if (symbol == '#')
{
acceptStates.Add(fromState);
}
}
lineIndex++;
}
// 计算DFA数据
List<List<int>> dfaStates = new List<List<int>>();
List<int> dfaStartState = new List<int>();
List<int> dfaAcceptStates = new List<int>();
List<List<int>> dfaTransitions = new List<List<int>>();
List<int> currentStates = new List<int>();
foreach (int startState in startStates)
{
currentStates.Add(startState);
}
dfaStartState = currentStates;
dfaStates.Add(currentStates);
while (currentStates.Count > 0)
{
List<int> newStates = new List<int>();
List<int> newDfaTransitions = new List<int>();
foreach (char symbol in symbols)
{
newStates.Clear();
foreach (int currentState in currentStates)
{
List<int> toStates = nfaStates[currentState];
foreach (int toState in toStates)
{
if (symbol == '#' && acceptStates.Contains(toState))
{
newStates.Add(toState);
}
else if (symbol != '#' && lines[startState + symbol - 'a' + 2].Contains(toState.ToString()))
{
newStates.Add(toState);
}
}
}
if (newStates.Count > 0)
{
int newStateIndex = dfaStates.IndexOf(newStates);
if (newStateIndex < 0)
{
newStateIndex = dfaStates.Count;
dfaStates.Add(newStates);
}
newDfaTransitions.Add(newStateIndex);
}
else
{
newDfaTransitions.Add(-1);
}
}
dfaTransitions.Add(newDfaTransitions);
currentStates = newStates;
}
for (int i = 0; i < dfaStates.Count; i++)
{
if (dfaStates[i].Intersect(acceptStates).Count() > 0)
{
dfaAcceptStates.Add(i);
}
}
// 显示DFA数据
listView2.Clear();
listView2.Columns.Add("初始状态", 80);
listView2.Columns.Add("接受符号", 80);
listView2.Columns.Add("到达状态", 80);
for (int i = 0; i < dfaStates.Count; i++)
{
for (int j = 0; j < symbols.Count; j++)
{
int toState = dfaTransitions[i][j];
if (toState >= 0)
{
listView2.Items.Add(new ListViewItem(new string[] { string.Join(",", dfaStates[i]), symbols[j].ToString(), string.Join(",", dfaStates[toState]) }));
}
}
}
foreach (int acceptState in dfaAcceptStates)
{
listView2.Items.Add(new ListViewItem(new string[] { string.Join(",", dfaStates[acceptState]), "#", "" }));
}
}
NFA数据格式如下:
开始符:7
终结符:26
符号集:a;b;
1 a 2
3 b 4
5 # 3
5 # 1
4 # 6
2 # 6
7 # 5
6 # 8
6 # 5
7 # 8
9 a 10
11 a 12
10 # 11
13 b 14
15 b 16
14 # 15
17 # 13
17 # 9
16 # 18
12 # 18
8 # 17
19 a 20
21 b 22
23 # 21
23 # 19
22 # 24
20 # 24
25 # 23
24 # 26
24 # 23
25 # 26
18 # 25
原文地址: https://www.cveoy.top/t/topic/jNA3 著作权归作者所有。请勿转载和采集!