❶ 一文帶你認識30個重要的數據結構和演算法
數組是最簡單也是最常見的數據結構。它們的特點是可以通過索引(位置)輕松訪問元素。
它們是做什麼用的?
想像一下有一排劇院椅。每把椅子都分配了一個位置(從左到右),因此每個觀眾都會從他將要坐的椅子上分配一個號碼。這是一個數組。將問題擴展到整個劇院(椅子的行和列),您將擁有一個二維數組(矩陣)。
特性
鏈表是線性數據結構,就像數組一樣。鏈表和數組的主要區別在於鏈表的元素不存儲在連續的內存位置。它由節點組成——實體存儲當前元素的值和下一個元素的地址引用。這樣,元素通過指針鏈接。
它們是做什麼用的?
鏈表的一個相關應用是瀏覽器的上一頁和下一頁的實現。雙鏈表是存儲用戶搜索顯示的頁面的完美數據結構。
特性
堆棧是一種抽象數據類型,它形式化了受限訪問集合的概念。該限制遵循 LIFO(後進先出)規則。因此,添加到堆棧中的最後一個元素是您從中刪除的第一個元素。
堆棧可以使用數組或鏈表來實現。
它們是做什麼用的?
現實生活中最常見的例子是在食堂中將盤子疊放在一起。位於頂部的板首先被移除。放置在最底部的盤子是在堆棧中保留時間最長的盤子。
堆棧最有用的一種情況是您需要獲取給定元素的相反順序。只需將它們全部推入堆棧,然後彈出它們。
另一個有趣的應用是有效括弧問題。給定一串括弧,您可以使用堆棧檢查它們是否匹配。
特性
隊列是受限訪問集合中的另一種數據類型,就像前面討論的堆棧一樣。主要區別在於隊列是按照FIFO(先進先出)模型組織的:隊列中第一個插入的元素是第一個被移除的元素。隊列可以使用固定長度的數組、循環數組或鏈表來實現。
它們是做什麼用的?
這種抽象數據類型 (ADT) 的最佳用途當然是模擬現實生活中的隊列。例如,在呼叫中心應用程序中,隊列用於保存等待從顧問那裡獲得幫助的客戶——這些客戶應該按照他們呼叫的順序獲得幫助。
一種特殊且非常重要的隊列類型是優先順序隊列。元素根據與它們關聯的「優先順序」被引入隊列:具有最高優先順序的元素首先被引入隊列。這個 ADT 在許多圖演算法(Dijkstra 演算法、BFS、Prim 演算法、霍夫曼編碼 )中是必不可少的。它是使用堆實現的。
另一種特殊類型的隊列是deque 隊列(雙關語它的發音是「deck」)。可以從隊列的兩端插入/刪除元素。
特性
Maps (dictionaries)是包含鍵集合和值集合的抽象數據類型。每個鍵都有一個與之關聯的值。
哈希表是一種特殊類型的映射。它使用散列函數生成一個散列碼,放入一個桶或槽數組:鍵被散列,結果散列指示值的存儲位置。
最常見的散列函數(在眾多散列函數中)是模常數函數。例如,如果常量是 6,則鍵 x 的值是x%6。
理想情況下,散列函數會將每個鍵分配給一個唯一的桶,但他們的大多數設計都採用了不完善的函數,這可能會導致具有相同生成值的鍵之間發生沖突。這種碰撞總是以某種方式適應的。
它們是做什麼用的?
Maps 最著名的應用是語言詞典。語言中的每個詞都為其指定了定義。它是使用有序映射實現的(其鍵按字母順序排列)。
通訊錄也是一張Map。每個名字都有一個分配給它的電話號碼。
另一個有用的應用是值的標准化。假設我們要為一天中的每一分鍾(24 小時 = 1440 分鍾)分配一個從 0 到 1439 的索引。哈希函數將為h(x) = x.小時*60+x.分鍾。
特性
術語:
因為maps 是使用自平衡紅黑樹實現的(文章後面會解釋),所以所有操作都在 O(log n) 內完成;所有哈希表操作都是常量。
圖是表示一對兩個集合的非線性數據結構:G={V, E},其中 V 是頂點(節點)的集合,而 E 是邊(箭頭)的集合。節點是由邊互連的值 - 描述兩個節點之間的依賴關系(有時與成本/距離相關聯)的線。
圖有兩種主要類型:有向圖和無向圖。在無向圖中,邊(x, y)在兩個方向上都可用:(x, y)和(y, x)。在有向圖中,邊(x, y)稱為箭頭,方向由其名稱中頂點的順序給出:箭頭(x, y)與箭頭(y, x) 不同。
它們是做什麼用的?
特性
圖論是一個廣闊的領域,但我們將重點介紹一些最知名的概念:
一棵樹是一個無向圖,在連通性方面最小(如果我們消除一條邊,圖將不再連接)和在無環方面最大(如果我們添加一條邊,圖將不再是無環的)。所以任何無環連通無向圖都是一棵樹,但為了簡單起見,我們將有根樹稱為樹。
根是一個固定節點,它確定樹中邊的方向,所以這就是一切「開始」的地方。葉子是樹的終端節點——這就是一切「結束」的地方。
一個頂點的孩子是它下面的事件頂點。一個頂點可以有多個子節點。一個頂點的父節點是它上面的事件頂點——它是唯一的。
它們是做什麼用的?
我們在任何需要描繪層次結構的時候都使用樹。我們自己的家譜樹就是一個完美的例子。你最古老的祖先是樹的根。最年輕的一代代表葉子的集合。
樹也可以代表你工作的公司中的上下級關系。這樣您就可以找出誰是您的上級以及您應該管理誰。
特性
二叉樹是一種特殊類型的樹:每個頂點最多可以有兩個子節點。在嚴格二叉樹中,除了葉子之外,每個節點都有兩個孩子。具有 n 層的完整二叉樹具有所有2ⁿ-1 個可能的節點。
二叉搜索樹是一棵二叉樹,其中節點的值屬於一個完全有序的集合——任何任意選擇的節點的值都大於左子樹中的所有值,而小於右子樹中的所有值。
它們是做什麼用的?
BT 的一項重要應用是邏輯表達式的表示和評估。每個表達式都可以分解為變數/常量和運算符。這種表達式書寫方法稱為逆波蘭表示法 (RPN)。這樣,它們就可以形成一個二叉樹,其中內部節點是運算符,葉子是變數/常量——它被稱為抽象語法樹(AST)。
BST 經常使用,因為它們可以快速搜索鍵屬性。AVL 樹、紅黑樹、有序集和映射是使用 BST 實現的。
特性
BST 有三種類型的 DFS 遍歷:
所有這些類型的樹都是自平衡二叉搜索樹。不同之處在於它們以對數時間平衡高度的方式。
AVL 樹在每次插入/刪除後都是自平衡的,因為節點的左子樹和右子樹的高度之間的模塊差異最大為 1。 AVL 以其發明者的名字命名:Adelson-Velsky 和 Landis。
在紅黑樹中,每個節點存儲一個額外的代表顏色的位,用於確保每次插入/刪除操作後的平衡。
在 Splay 樹中,最近訪問的節點可以快速再次訪問,因此任何操作的攤銷時間復雜度仍然是 O(log n)。
它們是做什麼用的?
AVL 似乎是資料庫理論中最好的數據結構。
RBT(紅黑樹) 用於組織可比較的數據片段,例如文本片段或數字。在 Java 8 版本中,HashMap 是使用 RBT 實現的。計算幾何和函數式編程中的數據結構也是用 RBT 構建的。
在 Windows NT 中(在虛擬內存、網路和文件系統代碼中),Splay 樹用於緩存、內存分配器、垃圾收集器、數據壓縮、繩索(替換用於長文本字元串的字元串)。
特性
最小堆是一棵二叉樹,其中每個節點的值都大於或等於其父節點的值:val[par[x]]
❷ 計算機二級數據結構與演算法知識點
一、數據結構
(1)數據結構的基本概念
1、數據:數據是客觀事物的符號表示,是能輸入到計算機中並被計算程序識別和處理的符號的總稱,如文檔,聲音,視頻等。
2、數據元素:數據元素是數據的基本單位。
3、數據對象:數據對象是性質相同的數據元素的集合。
4、數據結構:是指由某一數據對象中所有數據成員之間的關系組成的集合。
(2)邏輯結構和存儲結構
1、數據結構可分為數據的邏輯結構和存儲結構。
1)數據的邏輯結構是對數據元素之間的邏輯關系的描述,與數據的存儲無關,是面向問題的,是獨立於計算機的。它包括數據對象和數據對象之間的關系。
2)數據的存儲結構也稱為數據的物理結構,是數據在計算機中的存放的方式,是面向計算機的,它包括數據元素的存儲方式和關系的存儲方式。
2、存儲結構和邏輯結構的關系:一種數據的邏輯結構可以表示成多種存儲結構即數據的邏輯結構和存儲結構不一定一一對應。
3、常見的存儲結構有:順序,鏈接,索引等。採用不同的存儲結構其數據處理的效率是不同的。
❸ 數據結構與演算法知識
對於大多數的程序員來說,在學習數據分析等技術的時候需要先了解關於數據結構以及演算法等知識點,下面我們就給大家簡單介紹一下什麼是數據結構?什麼是演算法?
大部分數據結構和演算法教材,在開篇都會給這兩個概嫌唯亂念下一個明確的定義。但是,這些定義都很抽象,對理解這兩個概念並沒有實質山旁性的幫助,反倒會讓你陷入死摳定義的誤區。畢竟,我們現在學習,並不是為了考試,所以,概念背得再牢,不會用也就沒什麼用。
雖然我們說沒必要深挖嚴格的定義,但是這並不等於不需要理解概念。下面我就從廣義和狹義兩個層面,來幫你理解數據結構與演算法這兩個概念。
從廣義上講,數據結構就是指一組數據的芹檔存儲結構。演算法就是操作數據的一組方法。
圖書館儲藏書籍你肯定見過吧?為了方便查找,圖書管理員一般會將書籍分門別類進行「存儲」。按照一定規律編號,就是書籍這種「數據」的存儲結構。
那我們如何來查找一本書呢?有很多種辦法,你當然可以一本一本地找,也可以先根據書籍類別的編號,是人文,還是科學、計算機,來定位書架,然後再依次查找。籠統地說,這些查找方法都是演算法。
從狹義上講,也就是我們專欄要講的,是指某些著名的數據結構和演算法,比如隊列、棧、堆、二分查找、動態規劃等。這些都是前人智慧的結晶,我們可以直接拿來用。我們要講的這些數據結構和演算法,都是前人從很多實際操作場景中抽象出來的,經過非常多的求證和檢驗,可以高效地幫助我們解決很多實際的開發問題。
那數據結構和演算法有什麼關系呢?為什麼大部分書都把這兩個東西放到一塊兒來講呢?
這是因為,數據結構和演算法是相輔相成的。數據結構是為演算法服務的,演算法要作用在特定的數據結構之上。因此,我們無法孤立數據結構來講演算法,也無法孤立演算法來講數據結構。
比如,因為數組具有隨機訪問的特點,常用的二分查找演算法需要用數組來存儲數據。但如果IT培訓選擇鏈表這種數據結構,二分查找演算法就無法工作了,因為鏈表並不支持隨機訪問。
數據結構是靜態的,它只是組織數據的一種方式。如果不在它的基礎上操作、構建演算法,孤立存在的數據結構就是沒用的。
❹ 數據結構與演算法基礎知識
1.數據結構的邏輯結構
(1)集合結構
(2)線性結構(存在唯一的第一個元素與唯一的最後一個元素)(eg: 線性表、隊列、棧、字元串、數組、鏈表)
(3)樹形結構(一對多)
(4)圖形結構(多對多)
2.數據結構的物理(存儲)結構
(1).順序存儲結構(插入與刪除低效因為要挪動其他元素的位置。但是遍歷簡單)
(2).鏈式存儲結構(插入與刪除高效,但是遍歷低效)
3.大O表示法(注意大O表示法表達的是最壞的情況)
規則:
(1)用常數1取代其他所有的常數(注意常數0也當1算)(3 -> 1, O(1))
(2) 只保留最高階項(n^3+2n^2+5 ->n^3, O(n^3))
(3) 若存在最高階,省略與其想成的常數(2n^3 -> n^3, O(n^3))
4. 時間復雜度類型
(1)常數階
(2)線性階
(3)平方階
(4)對數階
(5)立方階
(6)nlog階
(7)指數階(O(2^n)或O(n!), 往往會造成噩夢般的時間消耗)
5. 空間復雜度(用大O表示法求解改演算法的輔助空間即可,例如用於交換變數用的臨時變數的數量)
六. 順序存儲的線性表
線性表結構特點:
(1) 存在唯一一個的被稱作」第一個」的數據元素;
(2) 存在唯一一個的被稱作」第二個」的數據元素;
(3) 除了第一個元素以外,結構中的每個數據元素均有一個前驅;
(4) 除了最後一個元素以外,結構中的每個數據元素均有一個後繼。
七. 鏈式存儲的線性表(單鏈表)
首元結點是鏈表中第一個值域不為空的結點。
頭結點是一個值域為空且處於首位的結點。
首指針可指向首元結點也可指向頭結點,但是如果指向頭結點可以更加方便的處理單鏈表的插入和刪除問題,不用再對首位做額外判斷,並且指向頭節點的指針永遠不用變化。
*注意一下單鏈表的前插法和尾插法。尾插法更符合邏輯
❺ 數據結構——圖
轉自: http://www.cnblogs.com/mcgrady/archive/2013/09/23/3335847.html
閱讀目錄
一,圖的定義
二,圖相關的概念和術語
三,圖的創建和遍歷
四,最小生成樹和最短路徑
五,演算法實現
這一篇我們要總結的是圖(Graph),圖可能比我們之前學習的線性結構和樹形結構都要復雜,不過沒有關系,我們一點一點地來總結,那麼關於圖我想從以下幾點進行總結:
1,圖的定義?
2,圖相關的概念和術語?
3,圖的創建和遍歷?
4,最小生成樹和最短路徑?
5,演算法實現?
一,圖的定義
什麼是圖呢?
圖是一種復雜的非線性結構。
在線性結構中,數據元素之間滿足唯一的線性關系,每個數據元素(除第一個和最後一個外)只有一個直接前趨和一個直接後繼;
在樹形結構中,數據元素之間有著明顯的層次關系,並且每個數據元素只與上一層中的一個元素(雙親節點)及下一層的多個元素(孩子節點)相關;
而在圖形結構中,節點之間的關系是任意的,圖中任意兩個數據元素之間都有可能相關。
圖G由兩個集合V(頂點Vertex)和E(邊Edge)組成,定義為G=(V,E)
二,圖相關的概念和術語
1,無向圖和有向圖
對於一個圖,若每條邊都是沒有方向的,則稱該圖為無向圖。圖示如下:
因此,(Vi,Vj)和(Vj,Vi)表示的是同一條邊。注意,無向圖是用小括弧,而下面介紹的有向圖是用尖括弧。
無向圖的頂點集和邊集分別表示為:
V(G)={V1,V2,V3,V4,V5}
E(G)={(V1,V2),(V1,V4),(V2,V3),(V2,V5),(V3,V4),(V3,V5),(V4,V5)}
對於一個圖G,若每條邊都是有方向的,則稱該圖為有向圖。圖示如下。
因此,和是兩條不同的有向邊。注意,有向邊又稱為弧。
有向圖的頂點集和邊集分別表示為:
V(G)={V1,V2,V3}
E(G)={,,,}
2,無向完全圖和有向完全圖
我們將具有n(n-1)/2條邊的無向圖稱為無向完全圖。同理,將具有n(n-1)條邊的有向圖稱為有向完全圖。
3,頂點的度
對於無向圖,頂點的度表示以該頂點作為一個端點的邊的數目。比如,圖(a)無向圖中頂點V3的度D(V3)=3
對於有向圖,頂點的度分為入度和出度。入度表示以該頂點為終點的入邊數目,出度是以該頂點為起點的出邊數目,該頂點的度等於其入度和出度之和。比如,頂點V1的入度ID(V1)=1,出度OD(V1)=2,所以D(V1)=ID(V1)+OD(V1)=1+2=3
記住,不管是無向圖還是有向圖,頂點數n,邊數e和頂點的度數有如下關系:
因此,就拿有向圖(b)來舉例,由公式可以得到圖G的邊數e=(D(V1)+D(V2)+D(V3))/2=(3+2+3)/2=4
4,子圖
故名思義,這個就不解釋了。
5,路徑,路徑長度和迴路
路徑,比如在無向圖G中,存在一個頂點序列Vp,Vi1,Vi2,Vi3…,Vim,Vq,使得(Vp,Vi1),(Vi1,Vi2),…,(Vim,Vq)均屬於邊集E(G),則稱頂點Vp到Vq存在一條路徑。
路徑長度,是指一條路徑上經過的邊的數量。
迴路,指一條路徑的起點和終點為同一個頂點。
6,連通圖(無向圖)
連通圖是指圖G中任意兩個頂點Vi和Vj都連通,則稱為連通圖。比如圖(b)就是連通圖。下面是一個非連通圖的例子。
上圖中,因為V5和V6是單獨的,所以是非連通圖。
7,強連通圖(有向圖)
強連通圖是對於有向圖而言的,與無向圖的連通圖類似。
8,網
帶」權值」的連通圖稱為網。如圖所示。
三,圖的創建和遍歷
1,圖的兩種存儲結構
1) 鄰接矩陣,原理就是用兩個數組,一個數組保存頂點集,一個數組保存邊集。下面的演算法實現里邊我們也是採用這種存儲結構。如下圖所示:
2) 鄰接表,鄰接表是圖的一種鏈式存儲結構。這種存儲結構類似於樹的孩子鏈表。對於圖G中每個頂點Vi,把所有鄰接於Vi的頂點Vj鏈成一個單鏈表,這個單鏈表稱為頂點Vi的鄰接表。
2,圖的兩種遍歷方法
1) 深度優先搜索遍歷
深度優先搜索DFS遍歷類似於樹的前序遍歷。其基本思路是:
a) 假設初始狀態是圖中所有頂點都未曾訪問過,則可從圖G中任意一頂點v為初始出發點,首先訪問出發點v,並將其標記為已訪問過。
b) 然後依次從v出發搜索v的每個鄰接點w,若w未曾訪問過,則以w作為新的出發點出發,繼續進行深度優先遍歷,直到圖中所有和v有路徑相通的頂點都被訪問到。
c) 若此時圖中仍有頂點未被訪問,則另選一個未曾訪問的頂點作為起點,重復上述步驟,直到圖中所有頂點都被訪問到為止。
圖示如下:
註:紅色數字代表遍歷的先後順序,所以圖(e)無向圖的深度優先遍歷的頂點訪問序列為:V0,V1,V2,V5,V4,V6,V3,V7,V8
如果採用鄰接矩陣存儲,則時間復雜度為O(n2);當採用鄰接表時時間復雜度為O(n+e)。
2) 廣度優先搜索遍歷
廣度優先搜索遍歷BFS類似於樹的按層次遍歷。其基本思路是:
a) 首先訪問出發點Vi
b) 接著依次訪問Vi的所有未被訪問過的鄰接點Vi1,Vi2,Vi3,…,Vit並均標記為已訪問過。
c) 然後再按照Vi1,Vi2,… ,Vit的次序,訪問每一個頂點的所有未曾訪問過的頂點並均標記為已訪問過,依此類推,直到圖中所有和初始出發點Vi有路徑相通的頂點都被訪問過為止。
圖示如下:
因此,圖(f)採用廣義優先搜索遍歷以V0為出發點的頂點序列為:V0,V1,V3,V4,V2,V6,V8,V5,V7
如果採用鄰接矩陣存儲,則時間復雜度為O(n2),若採用鄰接表,則時間復雜度為O(n+e)。
四,最小生成樹和最短路徑
1,最小生成樹
什麼是最小生成樹呢?在弄清什麼是最小生成樹之前,我們需要弄清什麼是生成樹?
用一句語簡單概括生成樹就是:生成樹是將圖中所有頂點以最少的邊連通的子圖。
比如圖(g)可以同時得到兩個生成樹圖(h)和圖(i)
知道了什麼是生成樹之後,我們就很容易理解什麼是最小生成樹了。所謂最小生成樹,用一句話總結就是:權值和最小的生成樹就是最小生成樹。
比如上圖中的兩個生成樹,生成樹1和生成樹2,生成樹1的權值和為:12,生成樹2的權值為:14,我們可以證明圖(h)生成樹1就是圖(g)的最小生成樹。
那麼如何構造最小生成樹呢?可以使用普里姆演算法。
2,最短路徑
求最短路徑也就是求最短路徑長度。下面是一個帶權值的有向圖,表格中分別列出了頂點V1其它各頂點的最短路徑長度。
表:頂點V1到其它各頂點的最短路徑表
從圖中可以看出,頂點V1到V4的路徑有3條(V1,V2,V4),(V1,V4),(V1,V3,V2,V4),其路徑長度分別為15,20和10,因此,V1到V4的最短路徑為(V1,V3,V2,V4)。
那麼如何求帶權有向圖的最短路徑長度呢?可以使用迪傑斯特拉(Dijkstra)演算法。