從零開始的算法入門科普(一),你應該知道的數據結構類型·其一

壹 ❀ 引

算法,對於大多數開發者而言,是一個既陌生又熟悉的詞彙。陌生在於它很高格調,學好算法彷佛很難;而熟悉在於,開發中的一次排序,一次查找甚至一次計算都與算法脫不開關係。前端

不能否認,無論你使用的是哪一種開發語言,學好算法是成爲高級開發的必經之路。而像博主這種非計算機專業出身,大學沒學過數學的人而言,學算法尤其痛苦(苦笑)...算法

我以前打算經過刷LeetCode來提高算法能力,但由於缺少算法基礎知識,啃得過慢。若是你有關注過個人博客更新,就能發現我以前有寫過三篇排序文章,很尷尬,寫了忘忘了寫反覆之間我選擇暫停刷題。數組

最近我從公司借了一本不錯的算法入門圖書《演算法圖鑑》,大體翻閱,本書主要圍繞數據結構,排序,查找,安全算法等幾個章節展開,圖解的形式很是適合我這種小白。因此我打算花半個月左右時間將本書啃完,而這片文章算是我讀此書的開端。安全

學習不是一兩天,算法提高也是如此。有志者事竟成,願你我都能在算法上勇敢跨出第一步,那麼本文開始。數據結構

貳 ❀ 算法與數據結構

數據結構(data structure)用於決定數據的存放順序與位置。有同窗確定納悶,說算法怎麼又扯到數據結構了,讓咱們經過一個例子來解釋算法與數據結構的緊密關係。學習

假設咱們如今須要存儲一些用戶的電話號碼,信息就包括用戶名與用戶的手機號碼,咱們首先想到的天然是以下結構:3d

姓名 電話號碼
張三 136****1734
李四 130****3312
王五 130****7213
李星星 135****1535
西西 173****9797

這樣存儲其實沒問題,若是再有新增,咱們只需在結尾再加一行便可。好了,如今咱們要查詢王五的電話號碼,因爲存儲並沒有規則,因此咱們只能從頭至尾查一遍,或者隨機性的查閱,運氣好一眼看到了。但若是數量過大,可能這個運氣就很難好起來了。指針

如何改進?有同窗立馬想到手機通信錄存儲方式,按照姓名首字母排序,這樣很棒,以下:code

姓名 電話號碼
(L)李四 130****3312
(L)李星星 135****1535
(W)王五 130****7213
(X)西西 173****9797
(Z)張三 136****1734

如今要找到王五就很是簡單了,只要熟悉字母表順序,掃一眼就能快速定位到W開頭的姓氏,大大下降了查找難度。可問題又來了,如今要新增一條用戶數據汪倫,因爲也屬於W開頭,因此得緊跟王五以後,但因爲沒了空間,因此咱們只能將西西與張三統一日後挪騰出空間,假設這個行爲都是咱們手動完成,想一想就以爲麻煩。blog

還能再改進嗎?讓咱們回顧上面兩種存儲方式,方式一查找麻煩可是新增方便,方式二查找方便可是新增麻煩,那要不咱們將兩種方式結合下?以下:

姓名(L) 電話號碼
李四 130****3312
李星星 135****1535
姓名(W) 電話號碼
王五 130****7213
汪倫 130****3312
姓名(X) 電話號碼
西西 173****9797
姓名(Z) 電話號碼
張三 136****1734

如今咱們將不一樣字母開頭的姓氏分別存在不一樣的表中,這樣查找和新增都很是方便了。你看,咱們先不談算法,好的數據結構本質上就能大大提高算法效率,因此瞭解常見的數據結構頗有必要。

叄 ❀ 常見數據結構類型

叄 ✿ 壹 鏈表List

鏈表是數據結構中的一種,這類結構的數據排成一條直線,便於查找和刪除,但存放數據比較費時。鏈表每每由數據和指針構成:

這是一個理想中的鏈表結構,每一個數據都有指針指向下一個數據所在的位置。實際存儲可能沒有這麼乖巧,由於有指針起到指向做用,所以即使數據分散開來也不影響鏈表存儲數據。

鏈表一大特色就是查找某個數據時,必須按照指針依次讀取數據,好比上圖中想要找到Red,必須先找到Blue再找到Yellow依次查找才行。

鏈表結構追加數據時,要作的就是將插入數據前的指針指向本身,並將新數據的指針指向本來緊接的數據便可,好比如今咱們在Yellow與Red之間新增一個Purple:

假設咱們如今要刪除Purple數據也很簡單,將Yellow指向Purple的指針指向Red便可:

雖然圖解上來看,Purple還有指針指向Red數據,但實際Purple已經變成了沒法讀取的數據。

以上鍊表一大特色是做爲數據結尾的Red並沒有指針,有沒有Red也有指針的狀況呢?有,好比循環鏈表(circular list),循環鏈表並無頭尾的概念,每一個數據都扮演着頭尾的角色。

除此以外,上面的鏈表數據都只有一個指針,事實上也存在兩個指針的狀況,也就是雙向鏈表(bidirectional list),雙向鏈表的特色就是沒有先後之分,從數據讀取上來講比單向更方便,缺點是若是要新增數據或者刪除時,須要修改的指針會大大增多:

鏈表在查找上因爲須要從頭開始找,數量越多查找時間越長,因此查找執行時間與數據個數n有關,所以查找時間爲O(n),而新增數據時只須要修改制定的箭頭指向,這與數據個數無關,所以修改數據的執行時間爲O(1)。

叄 ✿ 貳 數組Array

數組也是數據結構的一種,像我這種前端開發,與數組打交道的次數就多到數不清。數組結構的數據在追加數據以及讀取時會很是便利,但在插入數據以及刪除數據會耗時耗力。一個理想的數組結構以下:

上圖展現的其實就是一個包含了Blue、Yellow、Red三個字符串的數組a。數組中的數據具備連續性,因此咱們能夠經過索引訪問指定位置的數據。好比如今要找到Red鏈表得從頭開始查,而數組只用經過索引a[2]便可訪問,很是方便。

數組雖然查很便利,但若是要在數組中插入或刪除某個元素就會比鏈表遜色不少,好比咱們要在Bule和Yellow中間插入Purple,以下圖:

首先數組中會新建追加數據的空間,以後依次將數據日後移動,直到將Blue後的空間騰出來,而後將Purple放進去,這就是一次數組的插入;同理,當咱們要刪除Purple時,又得將Purple以後的數據往前挪,直到填補上前面的空缺,因此對比起來數組在中間插入與刪除上確實比鏈表要麻煩的多。

前面咱們說了數組查詢可依賴索引,查詢時間與數組元素個數無關,因此查詢耗時爲O(1),而修改數組,好比新增刪除,按照時間複雜度最壞的來計算,假設是在第一位前新增元素,或者刪除第一位元素,要作的操做就會受到數組元素個數n的影響,因此操做的時間複雜度爲O(n)。

肆 ❀ 總

那麼到這裏,咱們介紹數據類型中的鏈表與數組兩種數據,固然數據類型遠遠不止這兩種,由於時間問題(明天還要上班),後面的幾種類型我會在第二篇中介紹。

回顧上文,咱們來將兩種數據結構作個對比:

讀取 新增 刪除
鏈表 慢 O(n) 快 O(1) 快 O(1)
數組 快 O(1) 慢 O(n) 慢 O(n)

你看,不一樣數據結構在不一樣操做上表現會徹底不一樣,以數組和鏈表爲例,若是咱們但願數據知識單獨訪問,很明顯數組更爲方便,而若是數組要頻繁操做,鏈表就更具優點了,這就是數據結構的魅力。

因爲本文記錄過程當中畫圖確實有點費時,後續的數據結構我會在第二篇中介紹,加油加油,那麼本文到這裏正式結束。

相關文章
相關標籤/搜索