有人相愛,有人年少財務自由,有人數據結構都背不出來

你們好,我是小羽。前端

這段時間在圈子裏也認識了不少大佬們,從他們身上看到的是事業有成,感情幸福,還都很年輕。不由感嘆,年輕人都這麼有規劃,成爲了別人眼中的人生贏家模樣。我以爲不要太在乎與別人的橫向比較,更多的應該是與本身的縱向比較。由於普通人更多,咱們都是在爲工做、生活努力的那羣人。這句話更多的是想送給一部分關注我號,目前比較焦慮的小夥伴,你要堅信只要努力,沒有辦不成的事。程序員

今天給你們介紹的是常見的幾種數據結構,主要針對一些剛入門數據結構以及須要系統複習數據結構的小夥伴們!身爲程序員的咱們,天天都在和不一樣的數據打交道。那麼你真的對數據結構一清二楚了麼?算法

小羽從各數據結構的定義、特色、使用和方法實現來給你們進行介紹。每種都配有圖文進行詳解,幫助你們來更好地掌握對應知識。若是你對這個問題有困惑,快來看看~後端

棧 stack

棧(stack)是限制插入和刪除只能在一個位置上進行的表,該位置是表的末端,叫作棧頂(top)。它是後進先出(LIFO)的。對棧的基本操做只有 push(進棧)和 pop(出棧)兩種,前者至關於插入,後者至關於刪除最後的元素。數組

存儲結構markdown

隊列 queue

隊列是一種特殊的線性表,特殊之處在於它只容許在表的前端(front)進行刪除操做,而在表的後端(rear)進行插入操做,和棧同樣,隊列是一種操做受限制的線性表。進行插入操做的端稱爲隊尾,進行刪除操做的端稱爲隊頭。數據結構

存儲結構dom

鏈表 Link

鏈表是一種數據結構,和數組同級。好比,Java 中咱們使用的 ArrayList,其實現原理是數組。而LinkedList 的實現原理就是鏈表了。鏈表在進行循環遍歷時效率不高,但插入和刪除時優點明顯。函數

存儲結構spa

散列表 Hash Table

散列表(Hash table,也叫哈希表)是一種查找算法,與鏈表、樹等算法不一樣的是,散列表算法在查找時不須要進行一系列和關鍵字(關鍵字是數據元素中某個數據項的值,用以標識一個數據元素)的比較操做。

散列表算法但願能儘可能作到不通過任何比較,經過一次存取就能獲得所查找的數據元素,於是必需要在數據元素的存儲位置和它的關鍵字(可用 key 表示)之間創建一個**肯定的對應關係,**使每一個關鍵字和散列表中一個惟一的存儲位置相對應。所以在查找時,只要根據這個對應關係找到給定關鍵字在散列表中的位置便可。這種對應關係被稱爲散列函數(可用 h(key)表示)。

用的構造散列函數的方法有:

直接定址法:取關鍵字或關鍵字的某個線性函數值爲散列地址。即:h(key) = key 或 h(key) = a * key + b,其中 a 和 b 爲常數。

數字分析法:數字分析法又稱數字選擇法,其方法是收集全部可能出現的鍵值,排列在一塊兒,對鍵值的每一位進行分析,選擇分佈較均勻若干位組成散列地址。

平方取值法:取關鍵字平方後的中間幾位爲散列地址。

摺疊法:將關鍵字分割成位數相同的幾部分,而後取這幾部分的疊加和做爲散列地址。

除留餘數法:取關鍵字被某個不大於散列表表長 m 的數 p 除後所得的餘數爲散列地址,即:h(key) = key MOD p p ≤ m

隨機數法:選擇一個隨機函數,取關鍵字的隨機函數值爲它的散列地址,即:h(key) = random(key)

用散列函數h將關鍵字映射到散列表中

排序二叉樹

首先若是普通二叉樹每一個節點知足:左子樹全部節點值小於它的根節點值,且右子樹全部節點值大於它的根節點值,則這樣的二叉樹就是排序二叉樹。

插入操做

首先要從根節點開始往下找到本身要插入的位置(即新節點的父節點);具體流程是:新節點與當前節點比較,若是相同則表示已經存在且不能再重複插入;若是小於當前節點,則到左子樹中尋找,若是左子樹爲空則當前節點爲要找的父節點,新節點插入到當前節點的左子樹便可;若是大於當前節點,則到右子樹中尋找,若是右子樹爲空則當前節點爲要找的父節點,新節點插入到當前節點的右子樹便可。

從左到右,從下到上(7次插入操做)

刪除操做

刪除操做主要分爲三種狀況,即要刪除的節點無子節點,要刪除的節點只有一個子節點,要刪除的節點有兩個子節點。

1.對於要刪除的節點無子節點能夠直接刪除,即讓其父節點將該子節點置空便可。

2.對於要刪除的節點只有一個子節點,則替換要刪除的節點爲其子節點。

3.對於要刪除的節點有兩個子節點,則首先找該節點的替換節點(即右子樹中最小的節點),接着替換要刪除的節點爲替換節點,而後刪除替換節點。

三種狀況

查詢操做

查找操做的主要流程爲:先和根節點比較,若是相同就返回,若是小於根節點則到左子樹中遞歸查找,若是大於根節點則到右子樹中遞歸查找。所以在排序二叉樹中能夠很容易獲取最大(最右最深子節點)和最小(最左最深子節點)值。

紅黑樹

R-B Tree,全稱是 Red-Black Tree,又稱爲「紅黑樹」,它一種特殊的二叉查找樹。紅黑樹的每一個節點上都有存儲位表示節點的顏色,能夠是紅(Red)或黑(Black)。

紅黑樹的特性

1.每一個節點或者是黑色,或者是紅色。

2.根節點是黑色。

3.每一個葉子節點(NIL)是黑色。[注意:這裏葉子節點,是指爲空(NIL 或NULL)的葉子節點!] (4)若是一個節點是紅色的,則它的子節點必須是黑色的。

4.從一個節點到該節點的子孫節點的全部路徑上包含相同數目的黑節點。

左旋

對 x 進行左旋,意味着,將「x 的右孩子」設爲「x 的父親節點」;即,將 x 變成了一個左節點(x成了爲 z 的左孩子)!。所以,左旋中的「左」,意味着「被旋轉的節點將變成一個左節點」。

左旋

LEFT-ROTATE(T, x) 
y ← right[x] // 前提:這裏假設 x 的右孩子爲 y。下面開始正式操做
right[x] ← left[y] // 將 「y 的左孩子」 設爲 「x 的右孩子」,即 將β設爲 x 的右孩子
p[left[y]] ← x // 將 「x」 設爲 「y 的左孩子的父親」,即 將β的父親設爲 x
p[y] ← p[x] // 將 「x 的父親」 設爲 「y 的父親」
if p[x] = nil[T] 
then root[T] ← y // 狀況 1:若是 「x 的父親」 是空節點,則將 y 設爲根節點
else if x = left[p[x]] 
 then left[p[x]] ← y // 狀況 2:若是 x 是它父節點的左孩子,則將 y 設爲「x 的父節點
的左孩子」
 else right[p[x]] ← y // 狀況 3:(x 是它父節點的右孩子) 將 y 設爲「x 的父節點的右孩
子」
left[y] ← x // 將 「x」 設爲 「y 的左孩子」
p[x] ← y // 將 「x 的父節點」 設爲 「y
複製代碼

節點左旋演示

右旋

對 x 進行右旋,意味着,將「x 的左孩子」設爲「x 的父親節點」;即,將 x 變成了一個右節點(x成了爲 y 的右孩子)!所以,右旋中的「右」,意味着「被旋轉的節點將變成一個右節點」。

右旋

RIGHT-ROTATE(T, y) 
x ← left[y] // 前提:這裏假設 y 的左孩子爲 x。下面開始正式操做
left[y] ← right[x] // 將 「x 的右孩子」 設爲 「y 的左孩子」,即 將β設爲 y 的左孩子
p[right[x]] ← y // 將 「y」 設爲 「x 的右孩子的父親」,即 將β的父親設爲 y
p[x] ← p[y] // 將 「y 的父親」 設爲 「x 的父親」
if p[y] = nil[T] 
then root[T] ← x // 狀況 1:若是 「y 的父親」 是空節點,則將 x 設爲根節點
else if y = right[p[y]] 
 then right[p[y]] ← x // 狀況 2:若是 y 是它父節點的右孩子,則將 x 設爲「y 的父節
點的左孩子」
 else left[p[y]] ← x // 狀況 3:(y 是它父節點的左孩子) 將 x 設爲「y 的父節點的左孩
子」
right[x] ← y // 將 「y」 設爲 「x 的右孩子」
p[y] ← x // 將 「y 的父節點」 設爲 「x」
複製代碼

添加

第一步: 將紅黑樹看成一顆二叉查找樹,將節點插入。

第二步:將插入的節點着色爲"紅色"。根據被插入節點的父節點的狀況,能夠將"當節點 z 被着色爲紅色節點,並插入二叉樹"劃分爲三種狀況來處理。

當被插入的節點是根節點時間,直接把此節點塗爲黑色。

當被插入的節點的父節點是黑色,什麼也不須要作。節點被插入後,仍然是紅黑樹。

當被插入的節點的父節點是紅色。這種狀況下,被插入節點是必定存在非空祖父節點的;進一步的講,被插入節點也必定存在叔叔節點(即便叔叔節點爲空,咱們也視之爲存在,空節點自己就是黑色節點)。理解這點以後,咱們依據"叔叔節點的狀況",將這種狀況進一步劃分爲 3 種狀況(Case)。

3種狀況(case)

第三步: 經過一系列的**旋轉或着色等操做,**使之從新成爲一顆紅黑樹。

刪除

第一步:將紅黑樹看成一顆二叉查找樹,將節點刪除。

這和"刪除常規二叉查找樹中刪除節點的方法是同樣的"。分 3 種狀況:

1.被刪除節點沒有兒子,即爲葉節點。那麼,直接將該節點刪除就 OK 了。

2.被刪除節點只有一個兒子。那麼,直接刪除該節點,並用該節點的惟一子節點頂替它的位置。

3.被刪除節點有兩個兒子。那麼,先找出它的後繼節點;而後把「它的後繼節點的內容」複製給「該節點的內容」;以後,刪除「它的後繼節點」。

第二步:經過"旋轉和從新着色"等一系列來修正該樹,使之從新成爲一棵紅黑樹。

由於"第一步"中刪除節點以後,可能會違背紅黑樹的特性。因此須要經過"旋轉和從新着色"來修正該樹,使之從新成爲一棵紅黑樹。選擇重着色 3 種狀況。

當 x 是「紅+黑」節點,直接把 x 設爲黑色,結束。此時紅黑樹性質所有恢復。

當 x 是「黑+黑」節點,且 x 是根,什麼都不作,結束。此時紅黑樹性質所有恢復。

當 x 是「黑+黑」節點,且 x 不是根,這種狀況又能夠劃分爲 4 種子狀況。這 4 種子狀況以下表所示:

4種狀況(case)

B-TREE

B-tree 又叫平衡多路查找樹。一棵 m 階的 B-tree (m 叉樹)的特性以下(其中 ceil(x)是一個取上限的函數):

1.樹中每一個結點至多有 m 個孩子;

2.除根結點和葉子結點外,其它每一個結點至少有有 ceil(m / 2)個孩子;

3.若根結點不是葉子結點,則至少有 2 個孩子(特殊狀況:沒有孩子的根結點,即根結點爲葉子結點,整棵樹只有一個根節點);

4.全部葉子結點都出如今同一層,葉子結點不包含任何關鍵字信息(能夠看作是外部結點或查詢失敗的結點,實際上這些結點不存在,指向這些結點的指針都爲 null);

5.每一個非終端結點中包含有 n 個關鍵字信息:(n,P0,K1,P1,K2,P2,……,Kn,Pn)。其中:

Ki (i=1…n)爲關鍵字,且關鍵字按順序排序 K(i-1)< Ki。

Pi 爲指向子樹根的接點,且指針 P(i-1)指向子樹種全部結點的關鍵字均小於 Ki,但都大於 K(i-1)。

關鍵字的個數 n 必須知足:ceil(m / 2)-1 <= n <= m-1

b-tree

一棵 m 階的 B+tree 和 m 階的 B-tree 的差別在於:

1.有 n 棵子樹的結點中含有 n 個關鍵字;(B-tree 是 n 棵子樹有 n-1 個關鍵字)

2.全部的葉子結點中包含了所有關鍵字的信息,及指向含有這些關鍵字記錄的指針,且葉子結點自己依關鍵字的大小自小而大的順序連接。(B-tree 的葉子節點並無包括所有須要查找的信息)

3.全部的非終端結點能夠當作是索引部分,結點中僅含有其子樹根結點中最大(或最小)關鍵字。(B-tree 的非終節點也包含須要查找的有效信息)

差別

位圖

位圖的原理就是用一個 bit 來標識一個數字是否存在,採用一個 bit 來存儲一個數據,因此這樣能夠**大大的節省空間。**bitmap 是很經常使用的數據結構,好比用於 Bloom Filter 中;用於無重複整數的排序等等。bitmap 一般基於數組來實現,數組中每一個元素能夠當作是一系列二進制數,全部元素組成更大的二進制集合。

例如:unsigned int bit[N],在這個數組裏面,能夠存儲 N * sizeof(int) * 8個數據,可是最大的數只能是N * sizeof(int) * 8 - 1。假如,咱們要存儲的數據範圍爲0-15,則咱們只須要使得N=1,這樣就能夠把數據存進去。以下圖:

數據爲【5,1,7,15,0,4,6,10】,則存入這個結構中的狀況爲

相關文章
相關標籤/搜索