Coursera北大《資料結構基礎》之概論
刷書有點看不下去了,打算換課程試試。
Mooc上有一樣的內容,更喜歡Coursera。
本文基於Coursera北大課程《資料結構基礎》,所有文中非標註圖片均來自課件,侵刪
程式 = 資料結構 + 演算法
1. 問題求解
資料結構與演算法是圍繞問題求解進行的。那麼什麼是問題求解的過程呢?
我們要明確編寫計算機程式的目的是為了解決實際應用問題。面對一個問題,首先,我們要將其抽象出來,抓住問題的核心,建立問題模型;伴隨著問題會有一些資料出現,我們需要使用合適的資料結構來表示數學模型;在資料模型的基礎上,我們使用合理的演算法進行設計。
這裡要注意的一點是,資料結構是離不開演算法的,其由邏輯、儲存和運算三個方面組成。通常來說這裡的“運算”就是指演算法。通常程式設計中的演算法和資料結構抽象是可以一同進行的。
課程中舉了一個《過河遊戲》的例子,剛好是我小時候很愛玩的一個遊戲(第二關怪獸吃人簡直是童年陰影),每一關都挺好玩的,值得嘗試,連結如下:
http://www.e-bobo.net/php/game1.php?ID=472&Page=6&Name=%E9%81%8E%E6%B2%B3%E9%81%8A%E6%88%B2
第一關如下:
狼不能和羊單獨在一起;羊不能和選單獨一起;人作為限制條件可以阻止A被B吃掉(人必須在船上)。目標是一頓操作要把狼羊菜都運到對岸。
這個問題中,模型就是人-狼-羊-菜的圖模型:
不合理狀態有:人狼、狼羊、羊菜、人菜、狼羊菜、人。
最終狀態為(右岸)空。
步驟如下:
我們可以把它轉化為一個矩陣求最短路徑的問題:
因為這個問題以後會詳細說,這裡就不展開了。
2. 資料結構與抽象資料型別
結構=實體+關係
資料結構=邏輯關係+資料儲存方法+運算【三者缺一不可】
整個資料結構以邏輯關係為主線來組織。
2.1 資料結構的邏輯關係
2.1.1 線性結構
線性表(表、棧、佇列、串等):最簡單最通用的結構
2.1.2 非線性結構
樹(二叉樹,Huffman樹,二叉檢索樹等)
圖(有向圖,無向圖等)
2.2 資料結構的儲存結構
是從邏輯結構到物理儲存空間的對映,主要有順序(陣列形式,連續儲存)、連結(指標的地址指向關係,十分重要,尤其對非線性結構)、索引(對資料建立索引表,通過表找到資料儲存地址)、雜湊(特殊的索引結構,通過關鍵碼對映快速找到儲存空間)四種形式組成,其中前兩種形式是基礎。
這裡注意一點,訪問記憶體任意一個地址所需要的時間都是相同的。
對於邏輯結構(K,r),其中r∈R,對結點集K建立一個從K到儲存器M的單元的對映:K→M,對於每一個結點j∈K都對應一個唯一的連續儲存區域c∈M。
具體例子如上圖所示,有一個長度為3的整型陣列a,如果a[0]的起始地址是4,那麼相對應地,a[1]就是8,a[2]是12(每一個整型數值佔4位元組)。
2.3 抽象資料型別(Abstract Data Type, ADT)
資料如何存放在記憶體裡並不是重點,重點是如何表示。抽象資料型別是隨著模組化和物件導向方法發展起來的。
ADT主要關乎邏輯和運算兩個方面,和物理儲存沒有關係。
一個抽象資料結構二元組可以表達為:<資料物件D,資料操作P>。
通常我們先定義邏輯結構(資料物件及其關係),再定義運算(資料操作)。
這裡舉了一個棧的ADT的例子:
棧的邏輯結構是線性表,操作特點是限制訪問埠,也就是說,棧必須是按照一定邏輯順序排列(如下圖所示)。棧遵循的是先進後出(出棧:讀pop;入棧:寫push),不允許從中間地址進行資料操作。
3. 演算法特性及分類
演算法是對特定問題求解過程的描述,是有限的指令。
3.1 演算法特性
(1)通用性
演算法對這一類問題都適用。例如求取1+2+3+4的和,我們可以用(1+4)*(4/2)=10求得,那麼推廣至:n個從a開始到b結束的整數的連加(n為偶數)則為(a+b)*(n/2)。
(2)有效性
演算法是有限條指令序列,由一系列具體步驟組成。每一步都必須是有效的。
(3)確定性
每一步都必須是明確的,可以獲得明確的結果,而不是模稜兩可的描述。
(4)有窮性
有限步數內結束。
3.2 演算法的分類
(1)窮舉法
就是挨個訪問、搜尋尋找答案
(2)回溯、搜尋
樹和圖遍歷。通過一些已知的不可能情況排除窮舉法中的一些例子,避免資源浪費
(3)遞迴分治
二分法、快排、歸併排序
(4)貪心法
前提是資料必須具有貪心特質,在每次一求解中都貪心最優解,得到的解的集合也是最優的。例如Huffman編碼樹、最短路徑Dijkstra演算法和最小生成樹Prim演算法等
(5)動態規劃
初高中學的那個
4. 演算法效率與度量
設計一個演算法後,我們要關注演算法的時間和空間效率,尤其是時間效率(即該演算法能不能在規定時間內完成任務)。
4.1 大O表式法(時間效率)
(1)定義
設f和g是定義域為自然數、值域為非負實數集的函式。如果存在正數c和n0,使得對於任意n>=n0,都有f(n)<=cg(n)【即f(n)總在集合O(g(n))中】,則稱f(n)是O(g(n))的,或f(n)=O(g(n))。
(2)相關符號
大O表示一個函式增長率的上限,這裡需要注意一個函式的增長率上限可能不止一個,我們需要儘量尋找最逼近的那個。
除了大O表式法,我們還用Ω來表示一個函式增長率的下限,有大Ω表式法。當同時表示上限和下限時,我們用Θ。在很多資料結構教材裡,人們會把ΩΘ混用。一般教材中只會介紹大O表式法,當遇到其它兩種時,用類比思想考慮即可【即找到最緊的下界用大Ω表式法;當上限和下限相同時,用大Θ表式法:有c1和c2把f夾在中間】。
(3)關於n<n0的部分
我們預設n0之前的n是小樣本的,因此並不關心n0之前的效率問題。
(4)大O表式法的單位時間
以下簡單的語句可以被視為單位時間:
- 簡單boolean或算術運算
- 簡單函式I/O(不包括耗時、不可控的外設I/O)
- 函式返回
(5)大O表式法運演算法則
加法規則:
例如
中,O(f(n))=n^3
加法規則在順序結構(如if, switch)中適用
乘法規則:
適用於for, while, do-while結構
例如如下程式碼塊的大O複雜度就是n*n。
for(i=0;i<n;i++){
for(j=0;j<n;j++){
}
}
4.2 增長率函式曲線
如圖所示【上圖摘自Coursera北京大學《資料結構與演算法》】,如果能找到log2n的增長率演算法就很好了。但是在做搜尋引擎等演算法時,我們希望O(f)=O(1)的,需要特殊的演算法。
通常在設計一個演算法時,我們需要考慮最好(例如排序中的插入排序)、最壞(壓力測試)和平均情況(統計意義下演算法大致效能,例如概率期望值),然後進行組合考慮。
4.3 二分法檢索效能分析
在決策樹下,每下降一層的效能都用log以2為底來衡量。
在上圖【摘自Coursera北京大學《資料結構與演算法》】的例子中,我們使用二分法檢索,用到了二叉樹。最大檢索長度為log2(n+1)
二分查詢的基本思想是將n個元素分成大致相等的兩部分,去a[n/2]與x做比較,如果x=a[n/2],則找到x,演算法中止;如果x<a[n/2],則只要在陣列a的左半部分繼續搜尋x,如果x>a[n/2],則只要在陣列a的右半部搜尋x.
時間複雜度無非就是while迴圈的次數!
總共有n個元素,
漸漸跟下去就是n,n/2,n/4,....n/2^k,其中k就是迴圈的次數
由於你n/2^k取整後>=1
即令n/2^k=1【二分只能到1,之後要結束】
可得k=log2n,(是以2為底,n的對數)
所以時間複雜度可以表示O()=O(logn)
---------------------
作者:frances_han
來源:CSDN
原文:https://blog.csdn.net/frances_han/article/details/6458067
版權宣告:本文為博主原創文章,轉載請附上博文連結!
4.4 資料結構和演算法的選擇
大多數時候資料結構的設計是先於演算法設計的,但是也有特殊情況,例如某些經典問題需要特定演算法解決,我們可能為了能實現這種演算法而用特定資料結構來表示。
在設計資料結構時,要注意資料結構的可擴充套件性,即在資料輸入規模發生變化時,資料結構是否能夠適應並依然能夠進行問題求解。
相關文章
- 資料結構基礎學習之緒論資料結構
- Redis基礎資料結構之字串Redis資料結構字串
- Redis基礎資料結構之MapRedis資料結構
- Redis基礎資料結構之SkipListRedis資料結構
- 基礎資料結構之陣列資料結構陣列
- 基礎資料結構之遞迴資料結構遞迴
- Redis基礎資料結構之連結串列Redis資料結構
- 實戰PHP資料結構基礎之棧PHP資料結構
- Python基礎之os和資料結構Python資料結構
- 實戰PHP資料結構基礎之雙連結串列PHP資料結構
- Redis基礎資料結構Redis資料結構
- 實戰PHP資料結構基礎之遞迴PHP資料結構遞迴
- 資料結構基礎學習之線性表資料結構
- Python基礎之:Python的資料結構Python資料結構
- 實戰PHP資料結構基礎之佇列PHP資料結構佇列
- 實戰 PHP 資料結構基礎之遞迴PHP資料結構遞迴
- 資料結構基礎 連結串列資料結構
- 實戰PHP資料結構基礎之單連結串列PHP資料結構
- 探索Redis設計與實現1:Redis 的基礎資料結構概覽Redis資料結構
- 資料結構基礎知識資料結構
- 基礎資料結構大賞資料結構
- Redis基礎——剖析基礎資料結構及其用法Redis資料結構
- 資料結構基礎學習之(棧和佇列)資料結構佇列
- 資料結構基礎學習之(串與陣列)資料結構陣列
- 資料結構與演算法之基礎知識資料結構演算法
- Redis原始碼學習——基礎資料結構之SDSRedis原始碼資料結構
- .NET基礎之資料繫結
- 大資料基礎架構總結大資料架構
- 資料結構基礎--雜湊表資料結構
- 淺析Redis基礎資料結構Redis資料結構
- 資料結構基礎第4講資料結構
- 資料結構基礎第3講資料結構
- 資料結構 & 演算法 in Swift (一):Swift基礎和資料結構資料結構演算法Swift
- 大資料概論(2)大資料
- 資料倉儲概論
- 前端基礎系列(三) -- 演算法 + 資料結構基礎前端演算法資料結構
- 04-論證基礎:論證結構的梳理
- 演算法資料結構 | 圖論基礎演算法——拓撲排序演算法資料結構圖論排序