0.前言
剛從北京回來,恰逢周末,好友近日也不在武漢。又因在博客中的一些交流,恰好看見微軟鄒欣老師關於《現代軟件工程作業 -- 計算最長英語單詞鏈》的博文。因此得空,按照需求分析到設計到實現以及測試和效能分析的流程,編寫程序,分析程序並攥寫一篇博文。考慮到時間比較有限,隨筆之中難免出現語句不通,錯別字,以及一些錯誤分析等等現象,還望見諒。
周末時間只有一天,此篇博文包括代碼均有很多坑!嘿嘿~
《計算最長英語單詞鏈》 https://www.cnblogs.com/xinz/p/7119695.html
Github地址: https://github.com/yuan574954352/WordChain
1.需求分析(略)
英語的接龍吧:一個文本文件中有N 個不同的英語單詞, 我們能否寫一個程序,快速找出最長的能首尾相連的英語單詞鏈,每個單詞最多只能用一次。最長的定義是:最多單詞數量,和單詞中字母的數量無關。
例如, 文件里有:
Apple
Zoo
Elephant
Under
Fox
Dog
Moon
Leaf
Tree
Pseudopseudohypoparathyroidism
最長的相連英語單詞串為: apple - elephant – tree, 輸出到文件里面,是這樣的:
Apple
Elephant
Tree
- 設計以及主要實現過程
【PSP】
PSP2.1 |
Personal Software Process Stages |
預估耗時(分鍾) |
實際耗時(分鍾) |
Planning |
計划 |
10 |
8 |
· Estimate |
· 估計這個任務需要多少時間 |
960 |
- |
Development |
開發 |
720 |
700 |
· Analysis |
· 需求分析 (包括學習新技術) |
15 |
10 |
· Design Spec |
· 生成設計文檔 |
10 |
15 |
· Design Review |
· 設計復審 (和同事審核設計文檔) |
10 |
12 |
· Coding Standard |
· 代碼規范 (為目前的開發制定合適的規范) |
10 |
15 |
· Design |
· 具體設計 |
20 |
22 |
· Coding |
· 具體編碼 |
480 |
500 |
· Code Review |
· 代碼復審 |
15 |
20 |
· Test |
· 測試(自我測試,修改代碼,提交修改) |
60 |
30 |
Reporting |
報告 |
30 |
35 |
· Test Report |
· 測試報告 |
20 |
22 |
· Size Measurement |
· 計算工作量 |
5 |
7 |
· Postmortem & Process Improvement Plan |
· 事后總結, 並提出過程改進計划 |
20 |
20 |
合計 |
|
695 |
708 |
二、解題思路
這個題的解題思路其實很簡單啦,也就是說Make it work的實現方式很容易想到,但如何使程序高效率的實現就需要深入考慮了。首先,思考一個基本的方向,核心算法就是使用圖論的相關知識,OK。這里關於圖論就不詳細敘述,簡單地以個人的語言來敘述一下:
【圖論】
圖論的起源就可以追溯到歐拉(Leonhard Euler)所處的那個年代。1736年,歐拉來到了普魯士的Konigsberg(哈哈,康德老家),發現當地人就有一項消遣活動,就是試圖將下圖中的每座橋恰好走過一遍並回到原出發點。但從來沒有成功過。
歐拉呢,就想着證明為什么一直沒成功啦~~~~
歐拉就把這個問題抽象成 點與線的構造,這不就是圖嘛!
至於為什么不可能。可以百度搜索【歐拉七橋問題的證明】
- 圖的分類
(1)無向圖:就是說兩個頂點沒有明確的指向關系,只有一條邊相連。就我目前的知識而言,我所了解的關於圖論的大部分算法都是基於無向連通圖的。
(2)有向圖:說白了,就是有方向的圖唄!!嘿嘿,但是有方向,一定要記清幾個定義!這也是順理成章的定義,就是In與out!在無向圖中,一個頂點有多少條可以出去的路,就這個頂點的度。顯然,在有向圖就會分為 出度與入度。
事實上,度與邊是有數學關系的,出度與入度也是一樣。度與邊的關系也是【歐拉七橋問題】關鍵點啦。
(3)連通圖:任意兩個頂點之間是連通的。
(4)非連通圖:無向圖中,存在兩個頂點之間是不連通的
(5)強連通圖:針對有向圖而言的,A->B 而B 不能 ->A
(6)非強連通圖:有向圖中存在兩個頂點之間是不連通
到后面反過來思考,其實我們求解的最長單詞鏈就是非強連通圖哦,那么如果有算法將非強連通圖轉成類似於無向圖的連通圖的,會不會提高效率呢~,哈哈。遐想遐想!
好啦。一口氣簡單介紹了圖的來歷與分類。那么現實抽象成圖,圖抽象成數字!就可以成為兩個向量:
Vertice={結點1,結點2,.....}
Edge={(1,2),(2,3),(4,6)........}
這兩個向量就能描述一張圖嘛。而且也好對圖進行運算。
OK!我們說提高程序效率從兩方面入手,一個是程序輸入參數的數據組織結構,也就是數據結構啦,另一個就是算法。
第一:數據結構
關於圖的數據結構,常規的有:鄰接矩陣,壓縮表呀,十字鏈表呀等等,我也記不清啦。這里就牽扯到 這種數據結構一方面提高程序效率,另一方面要盡可能的減小存儲空間,這也就是大多數《數據結構》的書,都分析時間需求,存儲空間。
第二:算法
就我了解的呀,大的思想類似於貪婪算法,分而治之,動態規划。好像克瑞斯托,以及Prim算法都是基於貪婪算法的啦,但是好像這些都是基於無向連通圖的,我也一直沒把我實際需要解決的問題(計算最長單詞鏈)直接套用某個算法的,所以掌握這些算法的思想最重要啦,嘿嘿! 就像室內定位的研究領域,想找某個算法直接套用根本不可能啦,但是運用類似於隱馬爾科夫,條件隨機場呀的思想還是可以的~~~扯遠了。。。哈哈
【核心思想】
假設結點是:Apple,Elephant,tree.等等,結點與結點的邊就是根據首尾字母是否相同來構造的。這邊就能得到V,E。構成一個圖。請注意:我們一定要構造的是一個非強連通的有向圖!
利用圖去生成樹,利用樹去生成路徑!
這個思想還是很重要的,據說有一個中國人就發現了一種樹,改進了一個算法。我印象在本科階段上《數據挖掘與分析》的時候,提及過。韓嘉煒老師的FP-Tree.
所以,我也在遐想,能不能也搞一個專用於處理非強連通的有向圖生成的樹,這個樹便於獲取最長/最短路徑~~~當然是遐想啦,還是務實!其實有時候國內就是這樣,很多想法不敢去實施,因為一旦實施失敗便意味着你的論文將空盪盪,這個以論文數量論成績的環境里,我還是要隨下大流~~【笑哭】
說到FP-Tree又在聯想我這個實際問題,所謂的FP就是頻繁模式(frequent pattern),那么我能否也構造一個FP-Tree去找出input.txt中哪些單詞總是相伴出現的呢?這又牽扯到關聯規則啦,我可沒有那么多時間在去扯別的領域的知識啦,“啤酒與尿布”故事總會讓我以為關聯規則很簡單,事實上可不是這樣,有時需要用更嚴格的統計學知識來控制規則的增殖!
OK!運用“敏捷”思想,第一個想到的當然是深度優先生成樹。生成n(結點數)個樹,獲取每個樹的最長鏈!最后排序這些最長鏈,也就得到我們想要最最長鏈!
這是“敏捷”思想在促使我這樣做,因為我知道這樣做,I can make it work!至於后面如何改進就是后話了!
【核心思想圖】
三、其他遐想
其實關於圖論在工程上實現要考慮的細節很多,那么考慮到我實際的問題,我想。
第一,是用BFS還是DFS?
BFS就是廣度優先生成樹,當然有些書籍把它稱之為寬度優先生成樹。DFS是深度優先生成樹。說實在的,在以前本科階段的學習,我只知道有這兩種方案可以生成樹。生成的樹可能只是遍歷的順序不同吧,對此也沒有什么好的印象。那個時候,就想着混學分。恨不得早點考完,哈哈。
從理論上講,這兩個算法都能夠在大致相同的時間里生成整個單詞森林!【這個時間是節點數量V和邊的數量E之和的線性函數,即O(V+E)】。那BFS和DFS的在工程上的區別又是如何呢!就拿目前這個問題來說吧,深度優先,他可以比廣度優先,提前生成某棵樹的一個鏈路。 這樣是不是可以運用多線程的思想,來提前后面的后續操作呢? 當然,這只是遐想,而且這種操作應該需要單詞量很多的情況。
四、效率圖,考慮到已經到晚上10點啦,下班啦,要去跑步啦啦.....就做了幾個就不粘貼上來了。哈哈~~~ 下次有周末再補上來。。嘻嘻。有興趣的讀者也可以自行測試。代碼已上傳Github。
五、網頁版的程序,使用Spring MVC框架,control層調用程序里的lib()即可
寫於 地大(武漢)工程研究中心 2018/7/15 (周日)