最近终于用Java写出一个算法程序——编译中用到的NFA到DFA的转换。修修改改用了几天时间,能力有限,希望读者朋友们提出各种学习意见。 源码如下: package com.neuq.june20; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.HashSet; import java.util.Set; public class NFAToDFA20 { int NFAnum; // NFA的状态个数,即二维数组的长度 String[][] NFA; // 二维数组(邻接矩阵)表示NFA static char[] chNFA; ArrayList NFAList = new ArrayList(); static String[][] DFATemp; // 二维数组(邻接矩阵)表示DFATemp,长度和NFA一样 static String[][] DFA; // 二维数组(邻接矩阵)表示DFA,长度为 static char[] start; static ArrayList startList = new ArrayList(); static ArrayList PP = new ArrayList(); static ArrayList MOVEP = new ArrayList(); static ArrayList EcloList = new ArrayList(); // 初使化NFA public void initNFA() { System.out.print("请输入NFA的状态个数:"); boolean inputInt = true; while (inputInt) { BufferedReader br = new BufferedReader(new InputStreamReader( System.in)); try { String nfanum = br.readLine(); NFAnum = Integer.parseInt(nfanum); inputInt = false; // 输入正确,是整数 } catch (IOException e) { System.out.print("输入有误,请重新输入一个整数:"); e.printStackTrace(); } } System.out.println("请输入NFA的各状态名(以“,”分开):"); boolean input = true; while (input) { BufferedReader br = new BufferedReader(new InputStreamReader( System.in)); try { String inputdfa = br.readLine(); String[] strdfa = inputdfa.split(","); chNFA = new char[strdfa.length]; for (int i = 0; i < strdfa.length; i++) { chNFA[i] = strdfa[i].charAt(0); NFAList.add(chNFA[i]); } input = false; // 输入正确,是整数 } catch (IOException e) { System.out.print("输入有误,请重新输入"); e.printStackTrace(); } } boolean inputstart = true; System.out.println("请输入初始状态(以“,”分开,如:0,1,2):"); while (inputstart) { BufferedReader br = new BufferedReader(new InputStreamReader( System.in)); try { String inputfir = br.readLine(); String[] temstart = inputfir.split(","); start = new char[temstart.length]; for (int i = 0; i < temstart.length; i++) { start[i] = temstart[i].charAt(0); startList.add(start[i]); } inputstart = false; } catch (IOException e) { System.out.print("输入有误,请重新输入"); e.printStackTrace(); } } NFA = new String[NFAnum][NFAnum]; DFATemp = new String[2 * NFAnum][2 * NFAnum]; for (int i = 0; i < NFAnum; i++) { for (int j = 0; j < NFAnum; j++) { NFA[i][j] = "#"; } } for (int i = 0; i < 2 * NFAnum; i++) { for (int j = 0; j < 2 * NFAnum; j++) { DFATemp[i][j] = "#"; } } // --------------输入各状态间的转换-------- int rin = 0; boolean inputOver = false; System.out .println("请输入各状态间的转换,状态和转换条件间以”-“隔开"); System.out.println("空弧用E表示(如:1-a-2,1-E-3,2-ab-3说明2到3有两条弧到达,两状态之间的转换只能输入一次!):"); while (!inputOver) { try { BufferedReader br = new BufferedReader(new InputStreamReader( System.in)); String str = br.readLine(); if (str.equals("over")) { inputOver = true; System.out.println("over执行"); } else { String[] arrstr = str.split("-"); System.out.println(arrstr.length); if (arrstr.length == 3) { try { char sf1 = arrstr[0].charAt(0); int f1 = NFAList.indexOf(sf1); char sf2 = arrstr[2].charAt(0); int f2 = NFAList.indexOf(sf2); String p = arrstr[1]; NFA[f1][f2] = p; addP(p); } catch (Exception e) { System.out.println("输入的状态转换有错,请重新输入"); // TODO: handle exception } } } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } for (int i = 0; i < NFA.length; i++) { for (int j = 0; j < NFA.length; j++) { System.out.print(NFA[i][j] + " "); } System.out.println(); } } // 打印String[][]类型二维数组 public void showNDFA(String[][] a) { for (int i = 0; i < a.length; i++) { for (int j = 0; j < a.length; j++) { System.out.print(a[i][j] + " "); } System.out.println(); } } // 打印数组 public void show(char[] a) { for (int i = 0; i < a.length; i++) { System.out.print(a[i] + " "); } System.out.println(); } // Arryalist 转化为int[] public char[] listTochar(ArrayList li) { ArrayList list = li; int len = list.size(); char[] aint = new char[len]; for (int i = 0; i < len; i++) { aint[i] = list.get(i).toString().charAt(0); } return aint; } public Set charToset(char[] chs) { Set setT = new HashSet(); for (int i = 0; i < chs.length; i++) { setT.add(chs[i]); } return setT; } // 查看P集合中是否含有当前状态,如果没有,就加入 public boolean Pexist(String cp) { for (int i = 0; i < PP.size(); i++) { if (PP.get(i).equals(cp)) { return true; } } return false; } // 查看T集合中是否存在e public boolean Texist(char e) { for (int i = 0; i < EcloList.size(); i++) { if (EcloList.get(i).equals(e)) { return true; } } return false; // 该T集合中说明不存在e } // 查看两个状态之间的p弧中,是否包含指定的弧cp public boolean PcontP(String p, char cp) { for (int i = 0; i < p.length(); i++) { char b = p.charAt(i); if (b == cp) return true; } return false; } // 查看状态是否存在,若不存在,则将其放到状态集里 public void addP(String sp) { for (int i = 0; i < sp.length(); i++) { if (!sp.equals("E")) { char b = sp.charAt(i); String cp = b + ""; if (!Pexist(cp) && !cp.equals("E")) { PP.add(cp); } } } } // 找到下一个空孤对应的状态,并加入到EcloList中 public void findNextE(char c) { int n = NFAList.indexOf(c); for (int i = 0; i < NFA.length; i++) { if (PcontP(NFA[n][i], 'E')) { char x = NFAList.get(i).toString().charAt(0); if (!Texist(x)) ; { EcloList.add(x); // E-closure暂存放在Eclosure中 findNextE(x); } } } } // 求m的E-closure(),即T public char[] E_closure(char[] m) { ArrayList tempList; for (int i = 0; i < m.length; i++) { if (!Texist(m[i])) { EcloList.add(m[i]); // 把当前状态加入list中 } findNextE(m[i]); } tempList = EcloList; EcloList = new ArrayList(); MOVEP = new ArrayList(); return listTochar(tempList); } // 找到P孤的闭包,c为当前的点,cp为转换弧 public void findP(char c, char cp) { System.out.println(cp); int n = NFAList.indexOf(c); System.out.println("n==============" + n); // System.out.println(NFA.length); for (int i = 0; i < NFA.length; i++) { if (PcontP(NFA[n][i], 'E')) { System.out.println(""); System.out.println(NFAList.get(i).toString().charAt(0)); System.out.println(); findP(NFAList.get(i).toString().charAt(0), cp); } if (PcontP(NFA[n][i], cp)) // 两状态之间的所有弧(NFA[n][i])中包含cp弧 { System.out.println(NFA[n][i] + " " + cp); System.out.println("包含cp"); boolean mpContP = false; for (int j = 0; j < MOVEP.size(); j++) { if (MOVEP.get(j).equals(NFAList.get(i))) { mpContP = true; } } if (mpContP == false) { System.out.println("MOVEP新加入一个状态"); MOVEP.add(NFAList.get(i)); } } } } // 求出(Move(T,cp)),可以得到moveP public void moveP(char[] t, char cp) { for (int i = 0; i < t.length; i++) { findP(t[i], cp); } } public static void main(String[] args) { NFAToDFA20 nfa = new NFAToDFA20(); nfa.initNFA(); long a = System.currentTimeMillis(); ArrayList ArraySetT = new ArrayList(); // 以set集合形式存放所有DFA状态,直到有重复 ArrayList ArrayIntT = new ArrayList(); int fin = 0; int in = 0; // 初始状态: EcloList = startList; char[] T0 = nfa.E_closure(start); nfa.show(T0); // T0转成Set类型,便于比较 Set setT0 = new HashSet(); setT0 = nfa.charToset(T0); ArraySetT.add(setT0); // DFA中加入setT0,以set形式放在ArraySetT中 ArrayIntT.add(T0); // DFA中加入T0,以int[]形式放在ArrayIntT中 in++; // 状态集里加上T0 char[] Tnow = T0; // 从状态T0开始找 int x = 0; while (fin < in) { for (int i = 0; i < PP.size(); i++) { char pp = PP.get(i).toString().charAt(0); // System.out.println("ppPPPPPPPPPPPpppppppppppooooooooooooooooooooPPPPPPPPPP "+pp); nfa.moveP(Tnow, pp); // System.out.println("moveP的size "+MOVEP.size()); // System.out.println(MOVEP.isEmpty()); if (!MOVEP.isEmpty()) { char[] T = nfa.E_closure(nfa.listTochar(MOVEP)); Set setT = new HashSet(); // setTa为一个新的状态 boolean nothas_setT = true; setT = nfa.charToset(T); // System.out.println("showT"); nfa.show(T); // 判断状态集中是否存在该状态setTa,没有则加入,有则不加 for (int j = 0; j < ArraySetT.size(); j++) { if (ArraySetT.get(j).equals(setT)) { System.out.println(setT); System.out.println("存在T状态"); int pri; int next; pri = fin; next = j; nothas_setT = false; if (DFATemp[pri][next].equals("#")) { String sp = pp + ""; DFATemp[pri][next] = sp; } else if (!nfa.PcontP(DFATemp[pri][next], pp)) { String tempP = DFATemp[pri][next]; DFATemp[pri][next] = tempP + pp; } } } if (nothas_setT) { //System.out.println("in+++++++++"); int pri; int next; ArraySetT.add(setT); ArrayIntT.add(T); pri = fin; next = ArrayIntT.size() - 1; in++; if (DFATemp[pri][next].equals("#")) { String sp = pp + ""; DFATemp[pri][next] = sp; } else if (!nfa.PcontP(DFATemp[pri][next], pp)) { String tempP = DFATemp[pri][next]; DFATemp[pri][next] = tempP + pp; } } } } fin++; // System.out.println("fin=====" + fin); // System.out.println("in==========" + in); // System.out // .println("IntSetSize=================" + ArrayIntT.size()); if (fin < in) { Tnow = (char[]) ArrayIntT.get(fin); } nfa.show(Tnow); // nfa.show(Tnow); // for (int i = 0; i < ArraySetT.size(); i++) // { // System.out.println(ArraySetT.get(i)); // } System.out .println("----------------------------------------------------------"); } // 打印DFA所有状态 for (int i = 0; i < ArraySetT.size(); i++) { System.out.println(ArraySetT.get(i)); } for (int i = 0; i < DFATemp.length; i++) { for (int j = 0; j < DFATemp.length; j++) { System.out.print(DFATemp[i][j] + " "); } System.out.println(); } long b = System.currentTimeMillis(); System.out.println(b - a); } }