最近一直在忙着寫大作業,考試復習,復習算法的時候寫了一些隨筆,現在忙起來都落下了博客,這里有一個VC++寫的大作業,主要是正則表達式轉NFA並顯示。內容如下。
數據結構描述
介紹一下NFA在表示的結構設計,由於NFA本身是一種有向圖,所以這里的存儲結構設計和鄰接表相似,圖中的每個節點后面是一些與其連接的節點的值,具體設計如圖4.1。
圖4.1
a) Graph由若干個GraphLine組成,其中start和end標識了NFA的初始狀態和終止狀態的下標;
b) GraphLine的由一個節點和以該節點為起點所指向的節點組成,而所指向的節點利用EdgeLink表示,其中有指向邊上的轉移字符和指向的節點組成;
c) GraphNode表示圖的基本組成節點,其中節點有唯一的ID和位置;
正則表達式轉換NFA算法
基礎的正則表達式,如圖4.2所示
圖4.2
對於正則表達式應用運算符部分構造方法如圖4.3
圖4.3
- 符號棧,即運算的符號,其存儲的為wchar_t類型,為連接,左括號,選擇3種運算符。
- NFA棧,即保存的NFA,這里因為整個計算過程都是更新一個Graph結構,所以這里的NFA棧保留的其實是當前NFA的開始和結束信息,即start和end。
具體的主要算法執行流程:
- 遍歷輸入的正則表達式,這里正則表達式的保存在CString變量中,可以通過下標訪問
- 首先初始化一張保存NFA的Graph結構,算法過程中的節點的數量不會超過正則表達式長度的2倍,所以這里直接開辟一個大小為正則表達式長度為2倍的Graph結構
- 遇到非運算符,及正則表達式里面的轉移符號的時候,這里就需要構造一個基本的NFA, 一個初始狀態,一個終止狀態,然后由初始狀態至終止狀態有一條為該轉移符號的邊,此時仍然需要檢查正則表達式的下一個符號,如果不是運算符或者為左括號,此時應該運算棧中添加一個連接運算符,然后將構造的基本NFA添加入NFA棧中,方便以后將基本的NFA進行其他選擇,重復,連接運算
- 遇到非運算符時,需要分一下四種運算符的情況
- 如果是運算符“)”,即右括號,此符號屬於運算級最高的符號了,所以它要在符號棧中彈出所有符號運算,直到遇到“)”匹配,運算過程中根據符號棧中彈出的符號計算
- 如果是運算符“(”,即左括號,此符號只是用來和右括號結合的,所以直接將該運算符壓入符號棧中即可
- 如果是運算符“*”,即重復符號,這個在正則表達式中運算級最高,直接進行計算,計算方法就是從NFA棧中彈出一張圖,然后得到兩個未分配的新節點,添加4條上面圖表示的那樣的邊,然后重新設定NFA的start和end之后將新的NFA壓入NFA棧中即可,運算后檢查其后跟隨的元素,如果是轉移符號或者左括號,則必須要向符號棧中添加連接符號
- 如果是運算符“+”,即選擇符號,由於此符號的優先級沒有連接符號高,所以此時應該彈出符號棧中優先級高於它的符號,但是“(”不參與彈出,所以這里只是彈出連接符號和自身“+”符號運算,然后將該符號壓入符號棧等候計算
- 正則表達式遍歷完畢之后,需要彈出所有的符號棧進行計算,最后NFA棧中的唯一NFA就是所求的NFA
接下來就是具體的運算的算法,這里點與點的連接通過更新Graph中相應的點的鄰接鏈表即可
- 連接運算,此時需要彈出NFA棧中的兩個NFA,然后將其中一個的end連接至另一個的start,然后更新新的NFA的start和end,壓入NFA棧中。
- 選擇運算,此時需要彈出NFA棧中的兩個NFA,然后Graph重新分配兩個節點,作為新的NFA的start和end,然后新的start分別連接彈出的兩個NFA的start,彈出的兩個NFA的end分別連接新的end即構成新的NFA,壓入NFA棧中。
- 閉包運算,此時需要彈出NFA棧中的一個NFA,然后Graph重新分配兩個節點,作為新的NFA的start和end,然后新的start連接彈出NFA的start,彈出NFA的end連接新的end,然后添加一條新的start到新的end的一條空邊和一條舊的end到舊的start的一條空邊,將新的NFA壓入NFA棧中。
最終的運行Graph的結果輸出樣式如圖4.4
圖4.4
NFA的顯示
NFA的顯示是根據上面算法生成的Graph的結構進行顯示顯示結果如圖4.5
具體的顯示方法是從Graph的start節點開始調用繪制函數,該繪制函數的功能是首先檢查該節點是否繪制,如果未繪制則進行繪制,如果已經繪制則不進行繪制,然后根據自己的位置確定他鄰接點的位置,然后繪制至其他點的邊,然后遞歸的調用其鄰接點,函數的結束條件是繪制到end或者其鄰接點已經繪制。
這里對代碼類和函數的作用進行主要的說明,代碼的實現細節可以參看代碼中的注釋
代碼主要類視圖如圖5.1
圖5.1
CInputExpDlg
正則表達式輸入對話框
GraphNode
EdgeLink
GraphLine
Graph
TranslateModel
源代碼下載地址:http://files.cnblogs.com/weixliu/RextoNFA.rar
轉載請注明出處,謝謝,