文章目錄
- 資料結構描述
- Regex轉換NFA演算法
- NFA的顯示
最近一直在忙著寫大作業,考試複習,複習演算法的時候寫了一些隨筆,現在忙起來都落下了部落格,這裡有一個VC++寫的大作業,主要是Regex轉NFA並顯示。內容如下。
資料結構描述
介紹一下NFA在表示的結構設計,由於NFA本身是一種有向圖,所以這裡的儲存結構設計和鄰接表相似,圖中的每個節點後面是一些與其串連的節點的值,具體設計4.1。
圖4.1
a) Graph由若干個GraphLine組成,其中start和end標識了NFA的初始狀態和終止狀態的下標;
b) GraphLine的由一個節點和以該節點為起點所指向的節點群組成,而所指向的節點利用EdgeLink表示,其中有指向邊上的轉移字元和指向的節點群組成;
c) GraphNode表示圖的基本組成節點,其中節點有唯一的ID和位置;
Regex轉換NFA演算法
基礎的Regex,4.2所示
圖4.2
對於Regex應用運算子部分構造方法4.3
圖4.3
- 符號棧,即運算的符號,其儲存的為wchar_t類型,為串連,左括弧,選擇3種運算子。
- NFA棧,即儲存的NFA,這裡因為整個計算過程都是更新一個Graph結構,所以這裡的NFA棧保留的其實是當前NFA的開始和結束資訊,即start和end。
具體的主要演算法執行流程:
- 遍曆輸入的Regex,這裡Regex的儲存在CString變數中,可以通過下標訪問
- 首先初始化一張儲存NFA的Graph結構,演算法過程中的節點的數量不會超過Regex長度的2倍,所以這裡直接開闢一個大小為Regex長度為2倍的Graph結構
- 遇到非運算子,及Regex裡面的轉移符號的時候,這裡就需要構造一個基本的NFA, 一個初始狀態,一個終止狀態,然後由初始狀態至終止狀態有一條為該轉移符號的邊,此時仍然需要檢查Regex的下一個符號,如果不是運算子或者為左括弧,此時應該運算棧中添加一個串連運算子,然後將構造的基本NFA添加入NFA棧中,方便以後將基本的NFA進行其他選擇,重複,串連運算
- 遇到非運算子時,需要分一下四種運算子的情況
- 如果是運算子“)”,即右括弧,此符號屬於運算級最高的符號了,所以它要在符號棧中彈出所有符號運算,直到遇到“)”匹配,運算過程中根據符號棧中彈出的符號計算
- 如果是運算子“(”,即左括弧,此符號只是用來和右括弧結合的,所以直接將該運算子壓入符號棧中即可
- 如果是運算子“*”,即重複符號,這個在Regex中運算級最高,直接進行計算,計算方法就是從NFA棧中彈出一張圖,然後得到兩個未分配的新節點,添加4條上面圖表示的那樣的邊,然後重新設定NFA的start和end之後將新的NFA壓入NFA棧中即可,運算後檢查其後跟隨的元素,如果是轉移符號或者左括弧,則必須要向符號棧中添加串連符號
- 如果是運算子“+”,即選擇符號,由於此符號的優先順序沒有串連符號高,所以此時應該彈出符號棧中優先順序高於它的符號,但是“(”不參與彈出,所以這裡只是彈出串連符號和自身“+”符號運算,然後將該符號壓入符號棧等候計算
- Regex遍曆完畢之後,需要彈出所有的符號棧進行計算,最後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
Regex輸入對話方塊
GraphNode
EdgeLink
GraphLine
Graph
TranslateModel
原始碼:http://files.cnblogs.com/weixliu/RextoNFA.rar
轉載請註明出處,謝謝,