《我的第一本算法书》 - 学习记录
目錄
- 0. 算法基礎(chǔ)知識(shí)
- 0-1. 什么是算法
- 0.1.1 算法和程序的區(qū)別
- 0.1.2 排列整數(shù)的算法:排序
- 0.1.3 如何選擇算法
- 0-2. 運(yùn)行時(shí)間的計(jì)算方法
- 0.2.1 輸入數(shù)據(jù)的量和運(yùn)行時(shí)間之間的關(guān)系
- 0.2.2 求運(yùn)行時(shí)間
- 0.2.3 運(yùn)行時(shí)間的表示
- 一. 數(shù)據(jù)結(jié)構(gòu)
- 1-1. 什么是數(shù)據(jù)結(jié)構(gòu)
- 1-2 鏈表
- 1-3 數(shù)組
- 1-4 棧
- 1-5 隊(duì)列
- 1-6 哈希表
- 1-7 堆
- 未完待續(xù)~
0. 算法基礎(chǔ)知識(shí)
0-1. 什么是算法
算法就是計(jì)算或者解決問題的步驟。
0.1.1 算法和程序的區(qū)別
????????算法和程序有些相似,區(qū)別在于程序是以計(jì)算機(jī)能夠理解的編程語言編寫而成的,可以在計(jì)算機(jī)上運(yùn)行,而算法是以人類能夠理解的方式描述的,用于編寫程序之前。不過,在這個(gè)過程中到哪里為止是算法、從哪里開始是程序,并沒有明確的界限。
????????就算使用同一個(gè)算法,編程語言不同,寫出來的程序也不同;即便使用相同的編程語言,寫程序的人不同,那么寫出來的程序也是不同的。
0.1.2 排列整數(shù)的算法:排序
- 查找最小的數(shù)字并交換:選擇排序;
- 用計(jì)算機(jī)能理解的方式構(gòu)思解法:算法的設(shè)計(jì)。
0.1.3 如何選擇算法
???????在算法的評判上,考量的標(biāo)準(zhǔn)各有不同。
???????如,簡單的算法對人來說易于理解,也容易被寫成程序,而在運(yùn)行過程中不需要耗費(fèi)太多空間資源的算法適用于內(nèi)存小的計(jì)算機(jī)。
???????不過,一般都是注重算法的運(yùn)行時(shí)間,即從輸入數(shù)據(jù)到輸出結(jié)果這個(gè)過程所花費(fèi)的時(shí)間。
0-2. 運(yùn)行時(shí)間的計(jì)算方法
0.2.1 輸入數(shù)據(jù)的量和運(yùn)行時(shí)間之間的關(guān)系
???????對 10 個(gè)數(shù)字排序和對 1 000 000 個(gè)數(shù)字排序,我們很容易想到后者的運(yùn)行時(shí)間更長。那么,實(shí)際上運(yùn)行時(shí)間會(huì)長多少呢?后者是前者的100 倍,還是1 000 000 倍?
????????就像這樣,不光要理解不同算法在運(yùn)行時(shí)間上的區(qū)別,還要了解根據(jù)輸入數(shù)據(jù)量的大小,算法的運(yùn)行時(shí)間具體會(huì)產(chǎn)生多大的變化。
0.2.2 求運(yùn)行時(shí)間
???????最為現(xiàn)實(shí)的方法就是在計(jì)算機(jī)上運(yùn)行一下程序,測試其實(shí)際花費(fèi)的時(shí)間。但是,由于計(jì)算機(jī)的不同會(huì)產(chǎn)生偏差。
所以通常用 “步數(shù)” 來描述運(yùn)行時(shí)間。“1 步”就是計(jì)算的基本單位。
0.2.3 運(yùn)行時(shí)間的表示
???????如,理論上選擇排序的運(yùn)行時(shí)間,計(jì)算并簡化后如下:
???????從上式可知,排序算法的運(yùn)行時(shí)間與輸入數(shù)據(jù)量 n 的平方成正比。假設(shè)某個(gè)算法的運(yùn)行時(shí)間如下:
???????那么,這個(gè)結(jié)果就可以用O(n^3) 來表示。如果運(yùn)行時(shí)間為:
???????這個(gè)結(jié)果就可以用O(nlogn) 來表示。
???????通過這種表示方法,我們可以直觀地了解算法的 時(shí)間復(fù)雜度(常用大O 符號來表述)。
O 這個(gè)符號的意思是“忽略重要項(xiàng)以外的內(nèi)容”,讀音同Order。O(n^2) 的含義就是“算法的運(yùn)行時(shí)間最長也就是n平方 的常數(shù)倍”,準(zhǔn)確的定義請參考相關(guān)專業(yè)書籍。
一. 數(shù)據(jù)結(jié)構(gòu)
1-1. 什么是數(shù)據(jù)結(jié)構(gòu)
???????數(shù)據(jù)存儲(chǔ)于 內(nèi)存 時(shí),決定了 數(shù)據(jù)順序* 和 位置關(guān)系 的便是 “數(shù)據(jù)結(jié)構(gòu)”。
???????通常,數(shù)據(jù)在內(nèi)存中是呈線性排列的,但是也可使用指針構(gòu)造出類似 “樹形” 的復(fù)雜結(jié)構(gòu)。
1-2 鏈表
鏈表 是數(shù)據(jù)結(jié)構(gòu)之一,數(shù)據(jù)呈線性排列:
-
單向鏈表:每個(gè)數(shù)據(jù)都有1 個(gè) “指針”,它指向下一個(gè)數(shù)據(jù)的內(nèi)存地址;
鏈表中,數(shù)據(jù)一般都是分散存儲(chǔ)于內(nèi)存中的,無需存儲(chǔ)在連續(xù)空間內(nèi)。
???????因?yàn)閿?shù)據(jù)都是分散存儲(chǔ)的,所以如果想要訪問數(shù)據(jù),只能從第1 個(gè)數(shù)據(jù)開始,順著指針的指向 順序訪問。比如,想要找到Red 這一數(shù)據(jù),就得從Blue 開始訪問。
-
循環(huán)鏈表:在鏈表 尾部使用指針,并且讓它指向鏈表頭部的數(shù)據(jù);
-
雙向鏈表:為數(shù)據(jù)設(shè)定 兩個(gè)指針,并且讓它們分別 指向前、后數(shù)據(jù)。
雙向鏈表存在的缺點(diǎn):
1-3 數(shù)組
???????數(shù)組: 數(shù)據(jù)呈線性排列。與前面的鏈表不同,在數(shù)組中,訪問數(shù)據(jù)十分簡單,而添加和刪除數(shù)據(jù)比較耗工夫。
???????數(shù)據(jù) 按順序存儲(chǔ) 在內(nèi)存的 連續(xù)空間內(nèi)。
???????由于數(shù)據(jù)是存儲(chǔ)在連續(xù)空間,所以每個(gè)數(shù)據(jù)的內(nèi)存地址,都可以通過數(shù)組下標(biāo)算出,并借此直接訪問目標(biāo)數(shù)據(jù)(即隨機(jī)訪問)。
【數(shù)組內(nèi)存操作】
???????如果要向數(shù)組中添加新數(shù)據(jù),必須把目標(biāo)位置后面的數(shù)據(jù)一個(gè)個(gè)移開。所以,如果在數(shù)組頭部添加數(shù)據(jù),就需要 O(n) 的時(shí)間,刪除操作同理。
補(bǔ)充說明:
???????在鏈表和數(shù)組中,數(shù)據(jù)都是線性地排成一列。在鏈表中訪問數(shù)據(jù)較為復(fù)雜,添加和刪除數(shù)據(jù)較為簡單;
???????而在數(shù)組中訪問數(shù)據(jù)比較簡單,添加和刪除數(shù)據(jù)卻比較復(fù)雜。我們可以根據(jù)哪種操作較為頻繁來決定使用哪種數(shù)據(jù)結(jié)構(gòu)。
| 鏈表 | 慢 | 快 | 快 |
| 數(shù)組 | 快 | 慢 | 慢 |
1-4 棧
棧:數(shù)據(jù)呈線性排列,是一種最后添加的數(shù)據(jù)最先被取出(即“后進(jìn)先出”)的結(jié)構(gòu),我們稱為Last In First Out,簡稱LIFO。
應(yīng)用: 深度優(yōu)先搜索算法
想要訪問中間的數(shù)據(jù)時(shí),就必須通過出棧操作將目標(biāo)數(shù)據(jù)移到棧頂才行。
在只需要訪問最新數(shù)據(jù)時(shí),使用它就比較方便了
1-5 隊(duì)列
也呈線性排列,與 棧 有些相似。“先進(jìn)先出”的結(jié)構(gòu),稱為First In First Out,簡稱FIFO。
應(yīng)用: 廣度優(yōu)先搜索算法
區(qū)別: 隊(duì)列中 添加 和 刪除 數(shù)據(jù)的操作分別是 在兩端進(jìn)行 的。
往隊(duì)列中添加數(shù)據(jù)時(shí),數(shù)據(jù)被加在最后面。
從隊(duì)列中取出(刪除)數(shù)據(jù)時(shí),是從最前面,也就是最早入隊(duì)的數(shù)據(jù)開始的。不能直接訪問位于中間的數(shù)據(jù)。
1-6 哈希表
在哈希表這種數(shù)據(jù)結(jié)構(gòu)中,使用“哈希函數(shù)”,可以使數(shù)據(jù)的查詢效率得到顯著提升。
哈希表存儲(chǔ)的是由鍵(key)和值(value)組成的數(shù)據(jù)。
一般來說,可以把 鍵 當(dāng)成數(shù)據(jù)的標(biāo)識(shí)符,把 值 當(dāng)成數(shù)據(jù)的內(nèi)容。
總結(jié):
???????在哈希表中,可以利用哈希函數(shù)快速訪問到數(shù)組中的目標(biāo)數(shù)據(jù)。
???????如果發(fā)生哈希沖突,就使用鏈表進(jìn)行存儲(chǔ)(這樣一來,不管數(shù)據(jù)量為多少,都能夠靈活應(yīng)對)。
???????如果數(shù)組的空間太小,使用哈希表的時(shí)候容易發(fā)生沖突,線性查找的使用頻率也會(huì)更高;反過來,如果數(shù)組的空間太大,就會(huì)出現(xiàn)很多空箱子,造成內(nèi)存的浪費(fèi)(因此,給數(shù)組設(shè)定合適的空間非常重要)。
1-7 堆
堆 是一種圖的樹形結(jié)構(gòu),被用于實(shí)現(xiàn)“優(yōu)先隊(duì)列”(priority queues)
???????優(yōu)先隊(duì)列是一種數(shù)據(jù)結(jié)構(gòu),可以自由添加數(shù)據(jù),但取出數(shù)據(jù)時(shí)要從最小值開始按順序取出。
???????在堆的樹形結(jié)構(gòu)中,各個(gè)頂點(diǎn)被稱為“結(jié)點(diǎn)”(node),數(shù)據(jù)就存儲(chǔ)在這些結(jié)點(diǎn)中。
~~~
未完待續(xù)~
總結(jié)
以上是生活随笔為你收集整理的《我的第一本算法书》 - 学习记录的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java-数组的使用
- 下一篇: IO-Day1