1. 程式人生 > >資料結構(一)——資料結構初識及演算法複雜度介紹

資料結構(一)——資料結構初識及演算法複雜度介紹

    資料結構,毋庸置疑,在程式設計中是極其重要的存在,在電腦科學中,不只是一般程式設計的基礎,而且是設計和實現編譯程式、作業系統、資料庫系統及其他系統程式和大型應用程式的重要基礎。

    因此,CSDN的第一篇文章就選擇了資料結構(也是打算再次補習可憐的基礎),本次資料結構的總結參考的書籍完全是清華大學出版的嚴奶奶的《資料結構》。(後續可能會補充寫黑皮書的資料結構部分,然現在基礎還不到那個程度,慚愧。。)

 

                                                                   基礎概念及基本術語

    資料    總的來說在電腦科學中所有能輸入到計算機中並被計算機程式處理的符號的總稱,而實際上由於現在的技術,幾乎任何可以輸入到計算機的格式都可以稱為資料,如影象,聲音等。

    資料元素   資料的基本單位,在計算機程式中通常作為一個整體進行考慮和處理。同時由資料項組成。

    資料項    資料的不可分割的最小單位。

    資料物件   性質相同的資料元素的集合

    資料結構   

相互之間存在的一種或多種特定關係的資料元素的集合。其有4類基本結構:

                 (1)集合

                 (2)線性結構

                 (3)樹形結構

                 (4)圖狀結構或網狀結構                                       

    其定義形式為一個二元組:Data_Structure=(D,S)   其中:D是資料元素的有限集,S則是D上關係的有限集

    而正因為結構定義的“關係”是資料元素之間的邏輯關係,因此又被稱為資料的邏輯結構。

    與之對比的是資料結構在計算機中的表示,稱為資料的物理結構,又稱儲存結構,如位,位元組等。

    資料元素之間的關係在計算機中有兩種不同的表示方法:順序映像非順序映像

    而因此我們也能夠得到兩種不同的儲存結構:順序儲存結構鏈式儲存結構,與之代表的首先便能想到順序表和連結串列了。

    資料型別  可以認為是一個值的集合和定義在這個值集上的一組操作的總稱。在高階程式設計語言中資料型別可以分為兩類:

                    原子型別   其值不可再次分解

                    結構型別   一般由若干成分按某種結構組成的,可以再次分解

    抽象資料型別(ADT)     指一個數學模型以及定義在該模型上的一組操作

定義用一個三元組表示:Abstract_Data-Structure=(D,S,P)  其中:D是資料物件,S是D上關係的有限集,P是對D的基本操作集

                    關鍵:使用它的人可以只關心它的邏輯特徵,不需要了解它的儲存方式。定義它的人同樣不必要關心它如何儲存。

                    作用:抽象資料型別可以使我們更容易描述現實世界。例:用線性表描述學生成績表,用樹或圖描述遺傳關係。

                                               

                                                                        演算法複雜度介紹

      引入演算法:演算法是對特定問題求解步驟的一種描述,是指令的有限序列。同時,演算法具有以下5個重要特性:

                   (1)有窮性      演算法在有窮步之後結束,且每一步都在有窮時間完成

                   (2)確定性      演算法的每條指令沒有二義性,同時針對相同輸入只能得出相同輸出

                   (3)可行性       演算法執行的任何計算步驟都是可以被分解為基本的可執行的操作步,即每個計算步都可以在有限時間內完成(也稱之為有效性)。 

                   (4)輸入           一個演算法有零個或多個輸入

                   (5)輸出            一個演算法有一個或多個輸出

     演算法的評定:

                    (1)正確性:   即演算法應當滿足具體問題的需求

                    (2)可讀性:   主要為了便於程式碼的閱讀以便後續除錯和修改

                    (3)健壯性:    當輸入資料非法時,演算法也能夠適當進行反應與處理,而不會產生莫名其妙的輸出結果,便於以後對非法資料輸出的處理。

                    (4)效率與低儲存量需求:    效率與演算法執行時間按有關,而儲存量需求指演算法執行過程中需要的最大儲存空間。

                                                                      效率與低儲存量需求兩者都與問題的規模有關。

     正式介紹演算法複雜度:

                      同一問題可用不同演算法解決,而一個演算法的質量優劣將影響到演算法乃至程式的效率。演算法分析的目的在於選擇合適的演算法和改進演算法。一個演算法的評價主要從時間複雜度和空間複雜度來考慮。

                      1.時間複雜度

                      一般情況下,演算法中基本操作重複執行的次數是問題規模n的某個函式f(n),演算法的時間度量記作:

                                 T(n)=O(f(n))   

                       它表示隨問題規模n的增大,演算法執行時間的增長率和f(n)的增長率相同  

                       稱作演算法的漸近時間複雜度,簡稱時間複雜度

                       按數量級遞增排列,常見的時間複雜度有:

                       常數階O(1),對數階O(logn),線性階O(n),

                       線性對數階O(nlogn),平方階O(n^2),立方階O(n^3),...,

                       k次方階O(n^k),指數階O(2^n)。隨著問題規模n的不斷增大,上述時間複雜度不斷增大,演算法的執行效率越低。

                      而計算時間複雜度則是計算語句頻度:

                                    例如此程式段:

                                          for(i=2;i<=n;++i)

                                                  for(j=2;j<=i-1;++j)

                                                   {

                                                      ++x;

                                                      a[i][j]=x;

                                                    }

                      語句++x的執行次數為1+2+3+...n-2,即(n-1)*(n-2)/2,應用數學知識我們可以知道當n充分大時,其值受一次項與常數項影響很小,因此可以認為T(n)~O(n^2)

                      時間複雜度的計算只與最高次項有關,之後用O表示即可

                      而在有些情況下,演算法的時間複雜度不僅僅依賴於問題的規模,還與輸入例項的初始狀態有關:

                                    例如在氣泡排序中,輸入資料若與所需排序次序相同,則基本操作的執行次數為0,若輸入資料與所需排序次序完全相反,則基本操作的執行次數為n*(n-1)/2。而在考慮演算法的時間複雜度時,我們一般考慮的是 輸入情況最壞的狀態,計算在最壞情況下的時間複雜度。畢竟輸入不是固定的,輸入資料很好節省許多操作次數固然很好,但遇到最壞的情況我們也能夠從容應對。

                      2.空間複雜度

                      與時間複雜度類似,空間複雜度是指演算法在計算機內執行時所需儲存空間的度量。記作:

                                 S(n)=O(f(n))       其中n為問題的規模(或大小)

                      演算法執行期間所需要的儲存空間包括3部分: 

                                         演算法程式所佔的空間;

                                         輸入的初始資料所佔的儲存空間;

                                         演算法執行過程中所需要的額外空間。

                       在許多實際問題中,為了減少演算法所佔的儲存空間,通常採用壓縮儲存技術。