1. 程式人生 > 其它 >1.資料結構與演算法概念詳解

1.資料結構與演算法概念詳解

技術標籤:各個擊破資料結構和演算法演算法資料結構java程式語言

資料結構與演算法

資料結構

資料結構是計算機儲存、組織資料的方式。資料結構是指相互之間存在一種或多種特定關係的資料元素的集合。通常情況下,精心選擇的資料結構可以帶來更高的執行或者儲存效率。資料結構往往同高效的檢索演算法和索引技術有關。

定義

資料結構(data structure)是帶有結構特性的資料元素的集合,它研究的是資料的邏輯結構和資料的物理結構以及它們之間的相互關係,並對這種結構定義相適應的運算,設計出相應的演算法,並確保經過這些運算以後所得到的新結構仍保持原來的結構型別。簡而言之,資料結構是相互之間存在一種或多種特定關係的資料元素的集合,即帶“結構”的資料元素的集合。“結構”就是指資料元素之間存在的關係,分為邏輯結構和儲存結構。

資料結構的研究內容是構造複雜軟體系統的基礎,它的核心技術是分解與抽象。通過分解可以劃分出資料的層次;再通過抽象,捨棄資料元素的具體內容,就得到邏輯結構。類似地,通過分解將處理要求劃分成各種功能,再通過抽象捨棄實現細節,就得到運算的定義。上述兩個方面的結合可以將問題變換為資料結構。這是一個從具體(即具體問題)到抽象(即資料結構)的過程。然後,通過增加對實現細節的考慮進一步得到儲存結構和實現運算,從而完成設計任務。這是一個從抽象(即資料結構)到具體(即具體實現)的過程。

研究物件

資料的邏輯結構

指反映資料元素之間的邏輯關係的資料結構,其中的邏輯關係是指資料元素之間的前後間關係,而與他們在計算機中的儲存位置無關。邏輯結構包括:

1.集合:資料結構中的元素之間除了“同屬一個集合” 的相互關係外,別無其他關係;
2.線性結構:資料結構中的元素存在一對一的相互關係;
3.樹形結構:資料結構中的元素存在一對多的相互關係;
4.圖形結構:資料結構中的元素存在多對多的相互關係。

資料的物理結構

指資料的邏輯結構在計算機儲存空間的存放形式。
資料的物理結構是資料結構在計算機中的表示(又稱映像),它包括資料元素的機內表示和關係的機內表示。由於具體實現的方法有順序、連結、索引、雜湊等多種,所以,一種資料結構可表示成一種或多種儲存結構。
資料元素的機內表示(映像方法): 用二進位制位(bit)的位串表示資料元素。通常稱這種位串為節點(node)。當資料元素有若干個資料項組成時,位串中與各個資料項對應的子位串稱為資料域(data field)。因此,節點是資料元素的機內表示(或機內映像)。
關係的機內表示(映像方法):資料元素之間的關係的機內表示可以分為順序映像和非順序映像,常用兩種儲存結構:順序儲存結構和鏈式儲存結構。順序映像藉助元素在儲存器中的相對位置來表示資料元素之間的邏輯關係。非順序映像藉助指示元素儲存位置的指標(pointer)來表示資料元素之間的邏輯關係。

資料儲存結構

資料的邏輯結構在計算機儲存空間中的存放形式稱為資料的物理結構(也稱為儲存結構)。一般來說,一種資料結構的邏輯結構根據需要可以表示成多種儲存結構,常用的儲存結構有順序儲存、鏈式儲存、索引儲存和雜湊儲存等。
資料的順序儲存結構的特點是:藉助元素在儲存器中的相對位置來表示資料元素之間的邏輯關係;非順序儲存的特點是:藉助指示元素儲存地址的指標表示資料元素之間的邏輯關係。

常用的資料結構

在電腦科學的發展過程中,資料結構也隨之發展。程式設計中常用的資料結構包括如下幾個。
在這裡插入圖片描述

陣列(Array)

陣列是一種聚合資料型別,它是將具有相同型別的若干變數有序地組織在一起的集合。陣列可以說是最基本的資料結構,在各種程式語言中都有對應。一個數組可以分解為多個數組元素,按照資料元素的型別,陣列可以分為整型陣列、字元型陣列、浮點型陣列、指標陣列和結構陣列等。陣列還可以有一維、二維以及多維等表現形式。

棧( Stack)

棧是一種特殊的線性表,它只能在一個表的一個固定端進行資料結點的插入和刪除操作。棧按照後進先出的原則來儲存資料,也就是說,先插入的資料將被壓入棧底,最後插入的資料在棧頂,讀出資料時,從棧頂開始逐個讀出。棧在組合語言程式中,經常用於重要資料的現場保護。棧中沒有資料時,稱為空棧。

佇列(Queue)

佇列和棧類似,也是一種特殊的線性表。和棧不同的是,佇列只允許在表的一端進行插入操作,而在另一端進行刪除操作。一般來說,進行插入操作的一端稱為隊尾,進行刪除操作的一端稱為隊頭。佇列中沒有元素時,稱為空佇列。

連結串列( Linked List)

連結串列是一種資料元素按照鏈式儲存結構進行儲存的資料結構,這種儲存結構具有在物理上存在非連續的特點。連結串列由一系列資料結點構成,每個資料結點包括資料域和指標域兩部分。其中,指標域儲存了資料結構中下一個元素存放的地址。連結串列結構中資料元素的邏輯順序是通過連結串列中的指標連結次序來實現的。

樹( Tree)

樹是典型的非線性結構,它是包括,2個結點的有窮集合K。在樹結構中,有且僅有一個根結點,該結點沒有前驅結點。在樹結構中的其他結點都有且僅有一個前驅結點,而且可以有兩個後繼結點,m≥0。

圖(Graph)

圖是另一種非線性資料結構。在圖結構中,資料結點一般稱為頂點,而邊是頂點的有序偶對。如果兩個頂點之間存在一條邊,那麼就表示這兩個頂點具有相鄰關係。

堆(Heap)

堆是一種特殊的樹形資料結構,一般討論的堆都是二叉堆。堆的特點是根結點的值是所有結點中最小的或者最大的,並且根結點的兩個子樹也是一個堆結構。

散列表(Hash)

散列表源自於雜湊函式(Hash function),其思想是如果在結構中存在關鍵字和T相等的記錄,那麼必定在F(T)的儲存位置可以找到該記錄,這樣就可以不用進行比較操作而直接取得所查記錄。

常用演算法

資料結構研究的內容:就是如何按一定的邏輯結構,把資料組織起來,並選擇適當的儲存表示方法把邏輯結構組織好的資料儲存到計算機的儲存器裡。演算法研究的目的是為了更有效的處理資料,提高資料運算效率。資料的運算是定義在資料的邏輯結構上,但運算的具體實現要在儲存結構上進行。一般有以下幾種常用運算:
(1)檢索。檢索就是在資料結構裡查詢滿足一定條件的節點。一般是給定一個某欄位的值,找具有該欄位值的節點。
(2)插入。往資料結構中增加新的節點。
(3)刪除。把指定的結點從資料結構中去掉。
(4)更新。改變指定節點的一個或多個欄位的值。
(5)排序。把節點按某種指定的順序重新排列。例如遞增或遞減。

演算法

演算法(Algorithm)是指解題方案的準確而完整的描述,是一系列解決問題的清晰指令,演算法代表著用系統的方法描述解決問題的策略機制。也就是說,能夠對一定規範的輸入,在有限時間內獲得所要求的輸出。如果一個演算法有缺陷,或不適合於某個問題,執行這個演算法將不會解決這個問題。不同的演算法可能用不同的時間、空間或效率來完成同樣的任務。一個演算法的優劣可以用空間複雜度與時間複雜度來衡量。

特徵

一個演算法應該具有以下五個重要的特徵:

有窮性(Finiteness)

演算法的有窮性是指演算法必須能在執行有限個步驟之後終止;

確切性(Definiteness)

演算法的每一步驟必須有確切的定義;

輸入項(Input)

一個演算法有0個或多個輸入,以刻畫運算物件的初始情況,所謂0個輸入是指演算法本身定出了初始條件;

輸出項(Output)

一個演算法有一個或多個輸出,以反映對輸入資料加工後的結果。沒有輸出的演算法是毫無意義的;

可行性(Effectiveness)

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

要素

一、資料物件的運算和操作

計算機可以執行的基本操作是以指令的形式描述的。一個計算機系統能執行的所有指令的集合,成為該計算機系統的指令系統。一個計算機的基本運算和操作有如下四類:
1.算術運算:加減乘除等運算
2.邏輯運算:或、且、非等運算
3.關係運算:大於、小於、等於、不等於等運算
4.資料傳輸:輸入、輸出、賦值等運算

二、演算法的控制結構

一個演算法的功能結構不僅取決於所選用的操作,而且還與各操作之間的執行順序有關。

評定

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

時間複雜度

演算法的時間複雜度是指執行演算法所需要的計算工作量。一般來說,計算機演算法是問題規模n 的函式f(n),演算法的時間複雜度也因此記做。
T(n)=Ο(f(n))
因此,問題的規模n 越大,演算法執行的時間的增長率與f(n) 的增長率正相關,稱作漸進時間複雜度(Asymptotic Time Complexity)。

空間複雜度

演算法的空間複雜度是指演算法需要消耗的記憶體空間。其計算和表示方法與時間複雜度類似,一般都用複雜度的漸近性來表示。同時間複雜度相比,空間複雜度的分析要簡單得多。

演算法的時間複雜度和空間複雜度是衡量一個演算法優劣的重要指標,也是面試常問的問題。

正確性

演算法的正確性是評價一個演算法優劣的最重要的標準。

可讀性

演算法的可讀性是指一個演算法可供人們閱讀的容易程度。

健壯性

健壯性是指一個演算法對不合理資料輸入的反應能力和處理能力,也稱為容錯性。

方法

遞推法

遞推是序列計算機中的一種常用演算法。它是按照一定的規律來計算序列中的每個項,通常是通過計算機前面的一些項來得出序列中的指定項的值。其思想是把一個複雜的龐大的計算過程轉化為簡單過程的多次重複,該演算法利用了計算機速度快和不知疲倦的機器特點。

遞迴法

程式呼叫自身的程式設計技巧稱為遞迴(recursion)。一個過程或函式在其定義或說明中有直接或間接呼叫自身的一種方法,它通常把一個大型複雜的問題層層轉化為一個與原問題相似的規模較小的問題來求解,遞迴策略只需少量的程式就可描述出解題過程所需要的多次重複計算,大大地減少了程式的程式碼量。遞迴的能力在於用有限的語句來定義物件的無限集合。一般來說,遞迴需要有邊界條件、遞迴前進段和遞迴返回段。當邊界條件不滿足時,遞迴前進;當邊界條件滿足時,遞迴返回。
注意:
(1) 遞迴就是在過程或函式裡呼叫自身;
(2) 在使用遞迴策略時,必須有一個明確的遞迴結束條件,稱為遞迴出口。

窮舉法

窮舉法,或稱為暴力破解法,其基本思路是:對於要解決的問題,列舉出它的所有可能的情況,逐個判斷有哪些是符合問題所要求的條件,從而得到問題的解。它也常用於對於密碼的破譯,即將密碼進行逐個推算直到找出真正的密碼為止。例如一個已知是四位並且全部由數字組成的密碼,其可能共有10000種組合,因此最多嘗試10000次就能找到正確的密碼。理論上利用這種方法可以破解任何一種密碼,問題只在於如何縮短試誤時間。因此有些人運用計算機來增加效率,有些人輔以字典來縮小密碼組合的範圍。

貪心演算法

貪心演算法是一種對某些求最優解問題的更簡單、更迅速的設計技術。
用貪心法設計演算法的特點是一步一步地進行,常以當前情況為基礎根據某個優化測度作最優選擇,而不考慮各種可能的整體情況,它省去了為找最優解要窮盡所有可能而必須耗費的大量時間,它採用自頂向下,以迭代的方法做出相繼的貪心選擇,每做一次貪心選擇就將所求問題簡化為一個規模更小的子問題, 通過每一步貪心選擇,可得到問題的一個最優解,雖然每一步上都要保證能獲得區域性最優解,但由此產生的全域性解有時不一定是最優的,所以貪婪法不要回溯。
貪婪演算法是一種改進了的分級處理方法,其核心是根據題意選取一種量度標準,然後將這多個輸入排成這種量度標準所要求的順序,按這種順序一次輸入一個量,如果這個輸入和當前已構成在這種量度意義下的部分最佳解加在一起不能產生一個可行解,則不把此輸入加到這部分解中。這種能夠得到某種量度意義下最優解的分級處理方法稱為貪婪演算法。
對於一個給定的問題,往往可能有好幾種量度標準。初看起來,這些量度標準似乎都是可取的,但實際上,用其中的大多數量度標準作貪婪處理所得到該量度意義下的最優解並不是問題的最優解,而是次優解。因此,選擇能產生問題最優解的最優量度標準是使用貪婪演算法的核心。
一般情況下,要選出最優量度標準並不是一件容易的事,但對某問題能選擇出最優量度標準後,用貪婪演算法求解則特別有效。

分治法

分治法是把一個複雜的問題分成兩個或更多的相同或相似的子問題,再把子問題分成更小的子問題……直到最後子問題可以簡單的直接求解,原問題的解即子問題的解的合併。
分治法所能解決的問題一般具有以下幾個特徵:
(1) 該問題的規模縮小到一定的程度就可以容易地解決;
(2) 該問題可以分解為若干個規模較小的相同問題,即該問題具有最優子結構性質;
(3) 利用該問題分解出的子問題的解可以合併為該問題的解;
(4) 該問題所分解出的各個子問題是相互獨立的,即子問題之間不包含公共的子子問題。

動態規劃法

動態規劃是一種在數學和電腦科學中使用的,用於求解包含重疊子問題的最優化問題的方法。其基本思想是,將原問題分解為相似的子問題,在求解的過程中通過子問題的解求出原問題的解。動態規劃的思想是多種演算法的基礎,被廣泛應用於電腦科學和工程領域。
動態規劃程式設計是對解最優化問題的一種途徑、一種方法,而不是一種特殊演算法。不象前面所述的那些搜尋或數值計算那樣,具有一個標準的數學表示式和明確清晰的解題方法。動態規劃程式設計往往是針對一種最優化問題,由於各種問題的性質不同,確定最優解的條件也互不相同,因而動態規劃的設計方法對不同的問題,有各具特色的解題方法,而不存在一種萬能的動態規劃演算法,可以解決各類最優化問題。因此讀者在學習時,除了要對基本概念和方法正確理解外,必須具體問題具體分析處理,以豐富的想象力去建立模型,用創造性的技巧去求解。

迭代法

迭代法也稱輾轉法,是一種不斷用變數的舊值遞推新值的過程,跟迭代法相對應的是直接法(或者稱為一次解法),即一次性解決問題。迭代法又分為精確迭代和近似迭代。“二分法”和“牛頓迭代法”屬於近似迭代法。迭代演算法是用計算機解決問題的一種基本方法。它利用計算機運算速度快、適合做重複性操作的特點,讓計算機對一組指令(或一定步驟)進行重複執行,在每次執行這組指令(或這些步驟)時,都從變數的原值推出它的一個新值。

分支界限法

分枝界限法是一個用途十分廣泛的演算法,運用這種演算法的技巧性很強,不同型別的問題解法也各不相同。
分支定界法的基本思想是對有約束條件的最優化問題的所有可行解(數目有限)空間進行搜尋。該演算法在具體執行時,把全部可行的解空間不斷分割為越來越小的子集(稱為分支),併為每個子集內的解的值計算一個下界或上界(稱為定界)。在每次分支後,對凡是界限超出已知可行解值那些子集不再做進一步分支,這樣,解的許多子集(即搜尋樹上的許多結點)就可以不予考慮了,從而縮小了搜尋範圍。這一過程一直進行到找出可行解為止,該可行解的值不大於任何子集的界限。因此這種演算法一般可以求得最優解。
與貪心演算法一樣,這種方法也是用來為組合優化問題設計求解演算法的,所不同的是它在問題的整個可能解空間搜尋,所設計出來的演算法雖其時間複雜度比貪婪演算法高,但它的優點是與窮舉法類似,都能保證求出問題的最佳解,而且這種方法不是盲目的窮舉搜尋,而是在搜尋過程中通過限界,可以中途停止對某些不可能得到最優解的子空間進一步搜尋(類似於人工智慧中的剪枝),故它比窮舉法效率更高。

回溯法

回溯法(探索與回溯法)是一種選優搜尋法,按選優條件向前搜尋,以達到目標。但當探索到某一步時,發現原先選擇並不優或達不到目標,就退回一步重新選擇,這種走不通就退回再走的技術為回溯法,而滿足回溯條件的某個狀態的點稱為“回溯點”。
其基本思想是,在包含問題的所有解的解空間樹中,按照深度優先搜尋的策略,從根結點出發深度探索解空間樹。當探索到某一結點時,要先判斷該結點是否包含問題的解,如果包含,就從該結點出發繼續探索下去,如果該結點不包含問題的解,則逐層向其祖先結點回溯。(其實回溯法就是對隱式圖的深度優先搜尋演算法)。 若用回溯法求問題的所有解時,要回溯到根,且根結點的所有可行的子樹都要已被搜尋遍才結束。 而若使用回溯法求任一個解時,只要搜尋到問題的一個解就可以結束。