我不是天才,但我相信,通過有效方法和訓練,以及持之以恒地積累,完全是可以成為一名出色的開發人員的。那麼,到目前為止,掌握了多少思想、方法和技術可以用於開發程式、處理軟體開發過程中所遇到的問題呢?不妨作下總結,以備後用。
1. 抽象:
萃取出主要特徵,而摒棄次要不相關的特徵;無需瞭解物質的內部實現細節而基於其提供的抽象來構造應用;聲明與實現相分離。電腦科學中的抽象俯拾即是,比如組合語言是對機器硬體的抽象,編譯器是對進階程式語言的抽象,進程是對程式一次執行的抽象,線程是對任務執行流的抽象等。
2. 封裝:
由抽象直接引出的重要概念就是封裝。函數是演算法的良好封裝,對象是狀態與邏輯的良好封裝, 封裝是實現軟體模組化、提高軟體可維護性的重要技術。封裝是實現許多軟體工程思想的溯源。比如,隔離變化, 將變化的影響局部化等
3. 複用:
不要重複發明輪子。複用是軟體工程領域的重要技術。從標準庫函數,STL,JDK這樣的代碼級複用,到 Struts, hibernate 這樣的應用程式框架複用, 以及 設計模式的複用, 解決方案的複用, 複用無處不在。 複用是站在巨人的肩膀上, 能夠直接利用專家級的知識和經驗,何樂而不為?
4. 分層:
將系統分解為多個層次,精確定義每層所提供的服務及層次之間提供的服務介面;處於某個層次的層依賴於下一層提供的服務,並為上一層提供服務;各層之間無需知道彼此的細節。典型例子是網路通訊協定棧及作業系統虛擬機器的概念。
5. 模式:
在《水平思考的力量》一書中談到,大腦的運作機制主要是模式機制,即通過模式儲存、識別、串連和提取來實現思考。生活中無時不刻使用著模式,模式提高了人們的適應能力和反應能力。設計模式是模式思想在軟體設計中的運用。
6. 緩衝:
將一部分已求解值儲存起來以備後用;或者將一次性儲存一部分資料(包括但不僅含有當前所需資料),以便之後緊隨著訪問。動態規劃法是使用緩衝思想的典型例子。
儲存空間快取是緩衝思想的又一典型例子,與程式局部性原理密切相關。要想達到更好的程式效能,則必須採用一定手段,使得訪問資料的順序與資料在儲存空間中的儲存順序保持一致,這樣才能提高命中率,防止大量的缺頁中斷帶來的低效。
7. 中斷:
儲存現場, 。。。, 恢複現場。 中斷是實現許多電腦制的重要基礎。子程式,進程切換, I/0讀寫…… 思想是簡單的, 影響是深遠的。
8. 科學原理和性質
深刻理解科學原理和性質,往往能夠催生非常簡潔高效的演算法和技術,這可能就是電腦科學家與開發人員之間的一大區別吧。比如向量的旋轉問題,將ab轉換為ba, 也是基於對逆置性質的深刻理解上。R(R(a)R(b)) = ba ; 問題: 將 abc 轉換為 cba 呢?
向量的旋轉問題: http://blog.csdn.net/shuqin1984/article/details/6331772
9. 二分搜尋技術:
用於在有序數組(連續實體儲存體塊)中尋找給定關鍵字,時間複雜度為O(logn)。
例子: 在有序數組裡找出給定關鍵字出現的次數;在不重複的若干整數中找出不存在的整數; 程式調試技巧。
10. 分區技術:
給定一個列表,從中選定一個主軸元素,將它置於某個位置,並將列表中的元素分為兩個部分:使前半部分的所有元素都不大於該元素,後半部分的元素都不小於該元素。例子:快速排序,找出第k大的元素(順序統計量),請參閱《演算法導論》第7章(快速排序)和第9章(順序統計量)。
11. 分治技術:
將一個任務分解為多個子任務,然後分別求出這些子任務的解,最後綜合這些子任務的解,得到總任務的解。時間複雜度是T(n) = aT(n/b) + G(n),主要因素取決於a, b , G(n)。 例子: 最近對問題,歸併排序。
12. 遞迴技術:
一個規模為N的問題的解可以由規模為S(S<=N)的同樣性質的問題的解來構造。T(N) = T(S) + G(N). 遞迴技術是一種非常有效程式設計技術。
例子: 漢諾塔,二叉樹操作
遞迴技術在二叉樹操作的實現:
http://blog.csdn.net/shuqin1984/article/details/6260499
二叉樹的 Java 實現: http://blog.csdn.net/shuqin1984/article/details/6256415
13. 時空權衡技術:
通過額外操作以時間換空間,或者額外空間儲存以空間換時間。在PC機上,通常是以空間換時間,例如,雜湊表就是一個典型例子。
以時間換空間的例子,比如說在記憶體不足的情形下進行海量資料處理,可以採用k 趟遍曆,每趟遍曆解決一部分資料,得到一些子結果,最後將子結果合并。這樣在I/O讀寫上可能耗費較大量的時間。當k比較小時,採取k趟排序是一個較好的選擇。
14. 數組結構: 高效隨機訪問的下標集到值集的映射。
a) 下標集是儲存連續的,即最簡單的數組形式;
b) 下標集是非連續的, 例如儲存疏鬆陣列的元組集合
15. 鏈表:
a) 單鏈表: 在列表中高效地插入、刪除;
b) 多重棧、多重隊列實現;
16. 棧: 先進後出型資料結構,僅允許在一端進行插入和刪除。
a) 深度優先搜尋的輔助資料結構,比如回溯技術
b) 典型用例: 運算式計算,走迷宮
17. 隊列: 先進先出型資料結構,僅允許在一端進行插入,在另一端進行刪除。
a) FIFO服務的最佳選擇,比如作業系統中各種就緒、阻塞隊列
b) 廣度優先搜尋的輔助資料結構,比如二叉樹的層序遍曆
18. 二叉尋找樹:
在平均情形下,尋找、插入、刪除、最大元素、最小元素、前驅元素、後繼元素的操作均為O(logn),最差情形是O(n)。中序遍曆可用於排序。
二叉尋找樹的 Java 實現: http://blog.csdn.net/shuqin1984/article/details/6246615
19. 散列表:
通常主要支援尋找、插入和刪除操作,散列表是實現高效檢索的重要資料結構;在平均情形下,這些操作可以在O(1)內完成;在最差情形下,在O(n)內完成。
散列表的C語言實現: http://blog.csdn.net/shuqin1984/article/details/6587503
20. 位元影像技術:
將給定元素標識成一個位,從而在後續處理中標識該元素的存在。可用於稠密集合的排序,節省空間的資源。
位元影像排序: http://blog.csdn.net/shuqin1984/article/details/6204224
21. 堆結構:
在大量資料中用來尋找前K大的元素,實現優先順序隊列以及排序。請查閱演算法導論第八章(堆排序)
使用堆尋找前K個最大值
22. 表結構:
表結構是電腦領域的常用結構,比如編譯器符號表, 中斷處理常式表, 資料庫表等。 表結構也可以看作是 “空間換時間” 的例子, 通過表項事先儲存一定資訊,然後通過下標就可以迅速找到相應的程式入口地址或者資料項目。表結構通常與索引技術結合使用。
23. 演算法分析: Ο(n), Ω(n), Θ(n)
通過統計基本操作的次數,並取主項,可以得到演算法啟動並執行時間複雜度。
a) Ο(n): 演算法的上界,即至多要啟動並執行時間近似;
b) Ω(n): 演算法的下界,即至少要啟動並執行時間近似;
c) Θ(n): 演算法的精確界,不大於O(n),不小於Ω(n)
NOTE: 這裡通俗地說明三種界,精確定義請參考相關的演算法書籍。
通過取階、無窮小可以快速判斷演算法複雜度。比如
3n^2 + 2nlogn = O(n^2) 這是因為:
(3n^2 +2nlogn)/(n^2) 對 n 取極限(當n趨於無窮大時)為零,而
(3n^2 +2nlogn)/(nlogn) 取極限為無窮大,因此,
3n^2 + 2nlogn = O(n^2), 3n^2 + 2nlogn =Ω(nlogn)
通過對程式中的嵌套迴圈層數可以快速判斷演算法的時間複雜度;但有些情況是例外,比如外層迴圈的下標根據內層迴圈的下標進行跳躍性前進。
常見演算法技術總結: http://blog.csdn.net/shuqin1984/article/details/5859534
24. 演算法的三種情況分析:
a) 最優情況分析: 即找出一組輸入,使該演算法在最短的時間內完成。比如插入排序的最優情況是輸入基本有序,時間複雜度為O(n)
b) 最差情況分析: 即找出一組輸入,使該演算法在最長的時間內完成。比如快速排序的最差情況是輸入基本有序,時間複雜度為O(n^2)
c) 平均效能分析: 通過比較精確的數學分析方法,求出該演算法在一般輸入下的演算法已耗用時間。比如快速排序的平均效能在O(nlogn), 插入排序的平均效能在O(n^2)
25. 索引:
通過標識並避免移動大容量記錄從而提升時間效率的方法;也可用於共用記憶體空間,比如Linux中的檔案分享權限設定就是用索引技術來實現的。
26. 記法與解譯器:
通過記法來表達問題空間,然後,編寫解譯器來解析記法,得出結果。
例子: 圖案列印。先建立一套記法或指令,描述圖案的畫法,然後編寫解析器來解析這些記法或指令,從而列印出圖案。
圖案列印實現: http://blog.csdn.net/shuqin1984/article/details/6602369
27. Regex
Regex是用來描述字串的模式結構的,比如 \\d{4} 可以描述4個數字組成的字串。Regex是文本處理的強有力工具。
Regex基礎: http://blog.csdn.net/shuqin1984/article/details/6422258
28. 異或妙用:
0^0 = 0,0^1 = 1, 1^0=1, 1^1 = 0. 異或滿足交換律和結合律,即a^b^c = a^c^b = b^a^c = b^c^a = c^a^b = c^b^a ;對於整數a,b來說,若a = b,則 a^b =0 ; 若 a^b = 0, 則 a = b ; a^0 = a, a^a = 0, 因此 b^a^b = a 異或可以消去偶數次重複出現的數。
① 不用臨時儲存空間交換兩個整數。a = a^b, b = b^a, a =a^b, 實際上就是 a = a^b, b = b^(a^b) = b^b^a = a , a =(a^b)^a = b
② 有2k+1 個數,其中 k 個數出現了2次,一個數出現了1次,請找出這個只出現了一次的數。
29. “哨兵元素”:
在連續儲存塊(比如數組)的邊界設定一個哨兵元素,從而減少比較次數,或者防止越界。
30. 斷言與不變式:
使用斷言來檢測函數參數的有效性,驗證前置條件是否成立;在程式的適當位置插入斷言,驗證程式執行狀態是否正常;在程式的結尾插入斷言,驗證程式的後置條件是否成立。
不變式可以用來證明程式的正確性。通過設定合理的不變式,並證明在順序、選擇和迴圈中不變式總成立,從而證明程式的正確性。
【未完待續】