ICTCLAS代碼學習筆記之CNShortPath類

N-最短路徑算法類,這個是核心算法之一,用於進行中文詞語的粗分,算法的相關理論可參見論文《基於N-最短路方法的中文詞語粗分模型》。
類中包含的幾個成員變量依次說明如下:
m_apCost是一個動態數組的指針,用於記錄詞圖中的各結點及其路徑的權重值;
m_nValueKind是無符號整型數據,用於記錄共生成幾個結果,一般爲1,也可能生成多組結果;
m_nVertex是無符號整型數據,用於記錄詞圖中結點的個數,取值爲詞圖的行列值中較大的一個再加1。
m_pParent和m_pWeight都是二維數組指針,前者用於記錄每組結果中的每個結點的前驅後者記錄N個最短路徑值。例如傳入的詞圖爲5*4,只要求生成一組結果,則m_pParent爲[5][1]的Cqueue二維數組,而m_pWeight爲[5][1]的double二維數組。前者記錄每個結點處的父結點及相關信息,後者記錄相應的權重值。
最短路徑算法主要調用的函數是int CNShortPath::ShortPath()。這個函數根據成員變量m_apCost中記錄的詞圖中的各個邊的相關信息計算出路徑並保存在m_pParent和m_pWeight中。
從第一個結點開始(0結點爲起始結點),對每個結點
讀取列值爲當前結點的邊鏈表,該邊的行值記爲前一個結點,該邊的value值記爲權重。然後產
生所需要的m_nValueKind個結果,如果前一個結點已經是起始結點(爲0)則將這個結點及其當前權重值壓入隊列;如果還沒有回到起始結點則將這個結點以及當前權重與前一個結點的權重值相加的新權重值壓入。需要注意的是,如果前一個結點已經無路可走,即權重爲無限值INFINITE_VALUE則跳出生成過程。生成結果之後,對當前結點的前一個結點的權重值都置爲無限值,然後按權重從小到大依次取出每個結點,如果前一個位置的權重值爲無限即沒有被走到過則置爲當前讀出的這個權值,否則如果前一個位置的權重值比讀出的這個還要小,那就記錄到後面去。記錄權值的同時不要忘記還要把前驅結點記錄到m_pParent中去。這裏要說明的另一點是,由於隊列中的結果是按權值從小到大排序的,因此不會再現已記錄的結果比後面的結果權值大的情況。相等的情況也會在前驅表中有相應的記錄。
GetPaths是另一個重要的函數,雖然其類型爲private的只供內部使用。函數的聲明如下:
void CNShortPath::GetPaths(unsigned int nNode,unsigned int nIndex,int **nResult,bool bBest)
第一個參數是結點id,第二個參數是結果索引,第三個參數是用來存儲路徑的二維數組,bBest爲真時只取最好結果忽略其他。算法是回溯從nNode處往前找到起點的路徑。
首先將傳入的nNode及其結果索引nIndex壓入隊列,從這個結點開始往前走,即每次讀當前結點的父結點中的第一個侯選(即前驅結點中的第一個候選),只要有前驅就更新當前結點並注意將合法的前驅結點及其索引值保存起來,直到到達起始始點,注意這時是瀏覽狀態。如果最後得到的這個結點是起始結點(結點值爲0)則認爲找到了一條路徑,記錄這條路徑在nResult中。達到最大結果個數或者只要求一個最好結果就返回,否則回溯找下一條路徑,直到隊列爲空或者達到了最大結果個數。
Output用於將路徑結果寫入二維數組中,如果結點數不超過2,那麼只有唯一的路徑,即只生成了一個結果;否則的話從尾結點回溯調用getpaths來獲得路徑值。最終要幾個結果就循環幾次,需要注意的一個地方是參數bBest用於控制是否只生成一個最優結果即返回。同樣,每個結果中的路徑候選不超過MAX_SEGMENT_NUM(10)個。
CshortPath類總結:
利用已有的詞圖信息求最短路徑,是改進的最短路徑算法。核心的兩個函數是GetPaths和ShortPath。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章