演算法與資料結構的一些學習體會

2021-05-08 02:39:39 字數 2884 閱讀 8021

一篇以前的演算法版的版主,大牛starfish的學習資料結構的文章  

發信人:   starfish   (金盆洗手,退隱江湖),   信區:   algorithm  

標     題:   演算法與資料結構的一些學習體會  

發信站:   南京大學小百合站   (sat   apr     5   16:04:19   2003)   

計算機,顧名思義,是用來計算的機器,它本身並不具有思維能力,將它叫做電腦實在是言過其實。無論多麼複雜的程式,所從事的都是比較、賦值、迴圈等基本的運算。我們要程式設計序解決實際問題,就是要將實際問題的解題步驟用這些基本運算描述出來,這種描述就是演算法。   

如何才能將實際問題的解題步驟描述出來呢?這就要建立數學模型。有些問題的數學模型非常明顯,有些問題則比較含蓄。比如說,崗哨設定問題,這個問題可以建立明顯的數學模型,也就是圖論模型。有了這個模型,就可以用圖論中的相關定理來解決此問題,計算   

機所起的作用不過是按照演算法計算結果。對於像走迷宮之類的問題,看上去沒有明顯的數學模型,只能用回溯法搜尋,但實際上這種搜尋法本身就是乙個數學模型,這個模型叫做狀態空間模型,即在某乙個狀態空間(狀態的集合)內,從某個初始狀態開始,通過某種規則或運算,轉移到目標狀態。如果狀態a可以通過狀態轉移規則轉移到狀態b,則從a到b連一條有向邊,這樣整個狀態空間構成乙個網路,只要找到從初始狀態到目標狀態的路徑即可,於是搜尋法又轉化為圖論模型。也許對有些問題建立嚴格的數學模型並不能簡化問題的求解,但是可以通過該模型將特殊的問題轉化為一般的問題,至少具有理論分析(比如複雜性分析)上的意義。   

要建立數學模型,首先要將問題中的物件以及它們之間的相互關係用數學語言描述,這就涉及到物件如何表示的問題,也就是採用什麼樣的抽象資料型別(adt)來描述物件。所採用的adt應該能夠方便清晰地表現出物件之間的相互關係(包括顯式的和隱式的)。然後在adt上定義一些運算(可以暫時不關心運算的實現),將問題的解決步驟轉化為adt的運算的序列。至於adt的運算,可以轉化為更小的子adt運算來實現。轉化到最後,分解到最小了,就必須考慮抽象資料型別adt如何儲存在計算機的儲存器中,即資料的描述方法。最常見的資料描述方法有:公式化描述、鏈結描述、間接定址和模擬指標。   

1。公式化描述借助數學公式來確定元素表中的每個元素分別儲存在何處   (儲存器位址)。最簡單的情形就是把所有元素依次連續儲存在一片連續的儲存空間中,這時採用的公式是location(i)=location(1)+(i-1),其中location(i)表示第i個元素的位址,並假設每個元  

素占用乙個記憶體單元。這也就是通常所說的連續線性表,即陣列。    

2。在鏈結描述中,元素表中的每個元素可以儲存在儲存器的不同區域中,每個元素都包含乙個指向下乙個元素的指標(即記憶體中的位址)。    

3。在間接定址方式中,元素表中的每個元素也可以儲存在儲存器的不同區域中,不同的是,此時必須儲存一張表,該錶的第i項指向元素表中的第i個元素,所以這張表是乙個用來儲存元素位址的表。    

4。模擬指標非常類似於鏈結描述,區別在於它用整數代替了指標,整數所扮演的角色與指標所扮演的角色完全相同。如果所有模擬指標分配的記憶體單元是一片連續的記憶體位址,則稱其為游標描述或靜態鍊錶描述。    

所有的基本adt,比如說圖、樹、線性表等,最後都要用以上四種描述方法中的一種或幾種描述方法儲存在儲存器中。至於選擇哪一種描述方法,要根據adt上定義的運算來確定,總的原則是使運算易於實現並且占用的資源盡量少。對於某些複雜的adt,比如堆、優先佇列等,則是用基本adt來實現。因此adt呈現出一種層次繼承關係。  

在構造演算法的過程中還有乙個難點,就是如何將解決問題的步驟用adt的運算描述。這個過程沒有固定的方法,只能靠經驗的積累和一時的靈感。但是一般可以採取以下幾個策略:遞迴策略,分治策略,貪心策略,動態規劃策略,搜尋策略,隨機策略,模擬策略等。這些演算法設計策略只是一種演算法設計思想,並非固定的法則。必須分清楚各種策略的適用條件和相互間的聯絡區別,在考慮問題時才能夠正確地選擇演算法策略。  

另外,熟悉常用抽象資料型別的各種實現方法和一些常用演算法也很大幫助。因為許多問題可以轉化為類似的經典問題,或者可以分解為若干子問題,而這些子問題可以用經典的演算法和抽象資料型別解決。其中,最常用的演算法策略應該是搜尋策略,幾乎所有的問題都可以用此策略解決(但是未必可行)。這種策略充分利用了計算機計算速度快的特性,在許多情況下可以在合理的時間內找到問題的最優解。但是,對於有些問題,雖然可以用搜尋法解決,但是時間複雜性無法忍受,所以不可以濫用搜尋法,在使用搜尋法之前要先估計時間複雜性。即使使用了搜尋法,也要根據實際情況進行優化,通常採用啟發式搜尋、a演算法、a*演算法或界限剪枝法,目的是為了減少搜尋的時間複雜性。還有一些看上去只能用搜尋法或窮舉法的問題可以考慮用動態規劃法和貪心法。值得注意的是,對於有些問題,比如np-完全問題,用任何演算法都無法在多項式時間內解決,這時可以考慮尋找近似解法,得到較優解或最優解的上下界,一般是採用貪心演算法策略構造近似解法。  

以上是我的學習體會,下面說說我對學習演算法和資料結構這門課的建議。  

對於程式設計的初學者,可以先通過簡單的排序演算法了解最簡單的adt線性表的常用操作;然後要重點掌握遞迴技術,包括遞迴和遞推的相互轉換。遞迴技術非常重要,可以通過遞迴技術了解adt棧的操作;接著學習搜尋法的初步——回溯法,研究經典問題八皇后問題和走迷宮問題,通過這些經典問題了解深度優先搜尋法(dfs)和寬度優先搜尋法(bfs)以及adt棧、adt佇列的操作,要學會利用人工設定堆疊模擬遞迴;接著可以學習分治法、貪心法這兩種常用的策略,並應用到排序、搜尋等簡單的演算法中;這時再開始學習圖和樹這兩種抽象資料型別就應該沒有什麼難度了。在學習adt圖和adt樹時,要注意結合離散數學中的圖論理論知識和搜尋法中的dfs,bfs方法,要學會將實際問題轉化為圖論模型;再下去可以學習各種搜尋法的優化演算法,啟發式搜尋、a演算法、a*演算法或界限剪枝法等;然後是網路流演算法,要注意模型的建立;最後學習最優化問題的解法,包括線性規劃、動態規劃、非線性規劃等演算法策略,這部分內容主要側重模型的建立和分析,演算法本身並沒有難度。這樣基本的演算法就學習完了。再深入一點可以學習問題的計算複雜性,計算模型,並行演算法,神經網路以及各個領域中的具體演算法。  

關於資料結構學習的一些心得體會

在此我只想向大家介紹下,我最近幾個月學習資料結構的心得體會,同時也當練練打字和自我鞏固複習了吧!其實我複習的不算特別完善,也只能算乙個從小白到菜鳥的乙個階段,所以請大神們不要見笑啦。我接下來說的,對於專業不算太了解的有可能聽得索然無味,在此先說聲謝謝 好了,不扯太遠了,回到正題吧!在我複習的這段時間...

一些資料結構

dir heapq about all builtins cached doc file loader name package spec heapify max heapreplace max siftdown siftdown max siftup siftup max heapify heap...

資料結構與演算法 一些常用的演算法技巧總結

陣列的下標是乙個隱含的很有用的陣列,特別是在統計一些數字,或者判斷一些整型數是否出現過的時候。例如,給你一串字母,讓你判斷這些字母出現的次數時,我們就可以把這些字母作為下標,在遍歷的時候,如果字母a遍歷到,則arr a 就可以加1了,即 arr a 通過這種巧用下標的方法,我們不需要逐個字母去判斷。...