數據結構與算法——學習整理記錄
===註:此文由本人結合網上資源整理總結而來,僅代表個人的學習與理解,如有錯漏,歡迎指正!===
# 1. 數據結構
## 1.1 數據結構是什麽?
數據結構,直白地理解,就是研究數據的邏輯關系與存儲方式的一門學科。
可以簡單的分為:數據的邏輯結構(邏輯關系)和數據的存儲結構(物理結構)。
它是以某種形式將數據組織在一起的集合,它不僅存儲數據,還支持訪問和處理數據的操作。
### 1.1.1 數據的邏輯結構
數據的邏輯結構,簡單地理解,就是指的數據之間的邏輯關系。
數據之間的邏輯關系可簡單的分為三類:
- 一對一
- 一對多
- 多對多
### 1.1.1 數據的存儲結構
數據的存儲結構,也就是物理結構,指的是數據在物理存儲空間上的存放方式,可以選擇集中存放
,還是分散存放。
假設要存儲大小為 10M 的數據,則集中存放就如圖1(a)所示,分散存放就如圖1(b)所示。
圖1(a) 數據的集中存放
圖1(b) 數據的分散存放
## 1.2 為什麽要用數據結構?
使用數據結構的目的,即方便對數據的利用和操作。
## 1.3 數據結構有哪些?
根據數據的邏輯結構和存儲結構,可以把數據結構分為三大類:
- 第一類:線性表,用於存儲具有“一對一”邏輯關系的數據。包括順序表、鏈表、棧和隊列;
- 第二類:樹結構,用於存儲具有“一對多”邏輯關系的數據。包括普通樹,二叉樹,線索二叉樹等;
- 第三類:圖結構,用於存儲具有“多對多”邏輯關系的數據;
## 1.4 如何使用數據結構?
可以通過分析數據之間的邏輯關系來決定使用哪種存儲結構,但具體使用順序存儲還是鏈式存儲,還要通過數據的物理結構來決定。
如果選擇集中存儲,就使用順序存儲結構;反之,就使用鏈式存儲。至於如何選擇,主要取決於存儲設備的狀態以及數據的用途。
數據的用途不同,選擇的存儲結構也不同。將數據進行集中存儲有利於後期對數據進行遍歷操作,而分散存儲更有利於後期增加或刪除數據。因此,如果後期需要對數據進行大量的檢索(遍歷),就選擇集中存儲;反之,若後期需要對數據做進一步更新(增加或刪除),則選擇分散存儲。
# 2. 算法
## 2.1 算法是什麽:
算法,從表面意思來理解,即解決問題的方法。
算法是為求解一個問題需要遵循的、被清楚指定的簡單指令的集合。
在計算機中,算法是指解決方案的準確而完整的描述。
### 2.1.1 算法與程序
算法是解決某個問題的想法、思路;而程序是在心中有算法的前提下編寫出來的可以運行的代碼。
某種程度上,算法相當於是程序的雛形。
當解決問題時,首先心中要有解決問題的算法,圍繞算法編寫出程序代碼。
## 2.2 算法設計的要求
準確性、健壯性、運行效率(復雜度)
對於一個問題,想出解決的算法,不一定就能解決這個問題。為了避免這種情況的發生,要充分全面地思考問題,盡可能地考慮到所有地可能情況,慎重選擇算法(需要在實踐中不斷地積累經驗)。
### 2.2.1 算法的運行效率(復雜度)
算法的運行效率(復雜度)體現在兩方面:
- 算法的運行時間。(稱為“時間復雜度”)
- 運行算法所需的內存空間大小。(稱為“空間復雜度”)
#### 拿時間換空間,用空間換時間
算法的時間復雜度和空間復雜度是可以相互轉化的。
比如:谷歌瀏覽器相比於其他的瀏覽器,運行速度要快。是因為它占用了更多的內存空間,以空間換取了時間。
## 2.3 一個好算法的標準
在符合算法本身的要求(準確性和健壯性)的基礎上,使用算法編寫的程序運行的時間短,運行過程中占用的內存空間少,就可以稱這個算法是“好算法”。
## 2.4 算法時間復雜度計算
計算一個算法的時間復雜度,不可能把所有的算法都編寫出實際的程序出來讓計算機跑,這樣會做很多無用功,效率太低。實際采用的方法是估算算法的時間復雜度。
程序(C語言)一般由三種結構構成:順序結構、分支結構和循環結構。順序結構和分支結構中的每段代碼只運行一次;循環結構中的代碼的運行時間要看循環的次數。
由於是估算算法的時間復雜度,相比而言,循環結構對算法的執行時間影響更大。所以,算法的時間復雜度,主要看算法中使用到的循環結構中代碼循環的次數(稱為“頻度”)。次數越少,算法的時間復雜度越低。
### 2.4.1 時間復雜度的表示
算法的時間復雜度的表示方式為:
O(頻度)
這種表示方式稱為大“O”記法。
——註意,是大寫的字母O,不是數字0。
例如:
a) ++x; s=0;
b) for (int i=1; i<=n; i++) { ++x; s+=x; }
c) for (int i=1; i<=n; i++) { for (int j=1; i<=n; j++) { ++x; s+=x; } }
上邊這個例子中,a 代碼的運行了 1 次,b 代碼的運行了 n 次,c 代碼運行了 n*n 次。
所以使用算法的時間復雜度表示為:
a 的時間復雜度為O(1),b 的時間復雜度為O(n),c 的時間復雜度為為O(n2)。
如果把a、b、c三個例子組成一段程序,那麽算法的時間復雜度為O(n2+n+1)。但這麽表示是不對的,還需要對n2+n+1進行簡化。
簡化的過程總結為3步:
- 去掉運行時間中的所有加法常數。(例如 n2+n+1,直接變為 n2+n)
- 只保留最高項。(例如 n2+n 變成 n2)
- 如果最高項存在但是系數不是1,去掉系數。(例如 n2 系數為 1)
所以,最終a、b和c合並而成的代碼的時間復雜度為O(n2)。
## 2.5 常用的時間復雜度的排序
列舉了幾種常見的算法時間復雜度的比較(又小到大):
O(1)常數階 < O(logn)對數階 < O(n)線性階 < O(n2)平方階 < O(n3)(立方階) < O(2n) (指數階)
3. 數據結構與算法關系
可以從分析問題的角度去理清數據結構和算法之間的關系。
通常,每個問題的解決都經過以下兩個步驟:
- 第一步:分析問題,從問題中提取出有價值的數據,將其存儲;
- 第二步:對存儲的數據進行處理,最終得出問題的答案;
數據結構負責解決第一個問題,即數據的存儲問題。針對數據不同的邏輯結構和物理結構,可以選出最優的數據存儲結構來存儲數據。而算法負責為剩下的第二個問題提供解決方案。
總而言之,數據結構用於解決數據存儲問題,而算法用於處理和分析數據,它們是完全不同的兩類學科。
# 參考
- 《數據結構與算法教程,數據結構C語言版教程!》
- 《數據結構與算法常見筆試題》
數據結構與算法——學習整理記錄