日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

前言

HashMap是怎么實現地?為什么JDK8之后要換成紅黑樹?MySQL的索引為什么要用B+樹?

這些問題在面試中是經常被問到的。今天抽空把這些數據結構進行總結。其實每種數據結構都是為了滿足某種場景的需求,都是有著某種內在的聯系的,今天我們將嘗試進行梳理和總結。此外,在我們對這些數據結構進行研究的時候,主要關注于其評價指標,包括查找,刪除,插入的時間復雜度。

這里解釋下,我只是對其進行了梳理和總結,里面的配圖是在網上找的,會在后面注明來源。

數組和鏈表

數組和鏈表是我們最先接觸到的數據結構,我們先來分析下

數組 鏈表 查找 O(1) O(n) 插入 O(n) O(1) 刪除 O(n) O(1)

注:我們一般設置一個哨兵節點,這樣在處理頭結點的刪除和插入的時候不至于進行特殊處理。

上面的鏈表說的是單鏈表,除此之外,我們還需要了解雙向鏈表和循環鏈表

棧和隊列

這里需要注意,棧和隊列本質上是用數組/鏈表來實現的,不過二者是操作受限的線性表,其在特定的場景下可以發揮特有的作用。

跳表

跳表是什么?我們為什么需要跳表呢?

我們知道,二分查找的時間復雜度為lgn,性能是很好的,但是其只能局限在數組中,鏈表是不能使用二分查找的。那么有沒有辦法在鏈表中實現二分查找的特性呢?

如果數據是有序的,還是需要O(n)的時間復雜度。

數據結構不迷茫

 

那怎么提高查找效率呢?每兩個結點提取一個結點到上一級。

數據結構不迷茫

 

類推:

數據結構不迷茫

 

所以,當鏈表的長度 n 比較大時,在構建索引之后,查找效率的提升就會非常明顯。直觀上,我們可以看到查找的效率提高了提高,下面讓我們來具體分析提高的效率。

假設鏈表的長度為n,那么第一級索引的節點個數為n/2,第二級為n/4,那么第k級索引的節點個數為n/(2^k)。我們知道,最高的索引有2個節點,則k=lgn-1。在我們查詢數據的時候,如果每一層需要查找m個節點,則在跳表中查詢一個數據的時間復雜度就是 O(m*logn)。

且m=3,則時間復雜度為O(lgn)。

原因如下:假設我們要查找的數據是 x,在第 k 級索引中,我們遍歷到 y 結點之后,發現 x 大于 y,小 于后面的結點 z,所以我們通過 y 的 down 指針,從第 k 級索引下降到第 k-1 級索引。在 第 k-1 級索引中,y 和 z 之間只有 3 個結點(包含 y 和 z),所以,我們在 K-1 級索引中 最多只需要遍歷 3 個結點,依次類推,每一級索引都最多只需要遍歷 3 個結點。

數據結構不迷茫

 

我們可以看到,通過建立索引,我們實現了快速查找,代價了浪費了空間,空間復雜度為O(n)。其實在實際的軟件開發中,鏈表中存儲的是比較大的對象,但是索引中存儲的是id,所以相比較之下是可以忽略的。

下面我們來分析插入和刪除的時間復雜度,先給結論,也是O(lgn)。

數據結構不迷茫

 

我們還需要注意的是要及時更新索引,紅黑樹是通過左右旋來保持穩定的,而跳表是通過隨機函數來保存平衡性的。

數據結構不迷茫

 

hashmap

我們知道,數組可以在O(1)的時間復雜度內完成查詢,但是需要O(n)的時間復雜度完成插入和刪除,而鏈表正好相反,那么我們是否可以綜合利用數組和鏈表的優勢,這就是hashmap。

數據結構不迷茫

 

二叉查找樹

前面我們看到,hashmap是十分高效的,但是其問題也是比較明顯的。

  1. Hashmap中的數據是無序存儲的,若要輸出有序數據,則需要先進行排序,而二叉查找樹直接中序遍歷即可;
  2. Hashmap擴容耗時多;
  3. Hashmap在hash沖突的時候耗時多;
  4. Hashmap的構造復雜,需要考慮散列函數的設計、沖突解決辦法、擴容、縮容等問題,而二叉查找樹只需要考慮平衡性問題;

所以綜合以上的考量,在某些場景下,我們需要二叉查找樹,其查找的時間復雜度為O(logn)。

平衡二叉樹和紅黑樹

前面我們學到二叉查找樹在某些情況下可能會失衡,即退化為鏈表,時間復雜度降低為O(n),所以我們需要對二叉查找樹進行平衡。

最先被使用的是AVL平衡二叉查找樹,其首先符合二叉查找樹的概念,然后左右子樹的高度差不超過1。這樣就可以很好的保證查找的時間復雜度了。但是其缺點也是很明顯的,需要不斷的對整棵樹進行調整。

數據結構不迷茫

 

這個時候我們就引入了紅黑樹:左右子樹的高度差不超過1倍。紅黑樹的高度,是2logn。其查找,插入,刪除的時間復雜度都是O(logn)。

數據結構不迷茫

 

我們再來看另外一種特殊的二叉樹:堆。

我們知道堆是一種完全二叉樹,往往采用數據里存儲。堆在很多地方都有應用,比如

  • 優先級隊列:用在赫夫曼編碼、圖的最短路徑、最小生成樹算法
  • TOPK問題
  • 求動態數據中的中位數

此外,堆在排序算法中的表現也是很好的,時間復雜度是O(logn),空間復雜度為O(1),從這個角度來講,是要比快排和歸并排序都要優秀的,但是工程中更常見的排序算法依然是快排的,那這是為什么呢?主要從2個角度來考慮:

  1. 堆排序數據訪問的方式沒有快速排序友好。CPU的空間局部性原理。快排中,數據是順序訪問的,而堆中是跳著訪問的。
  2. 同樣的數據,堆排序的交換次數多余快排。

B樹和B+樹

這里要從mysql講起,使用mysql來查詢數據,我們比較關注的兩個點是等值查詢和范圍查詢,如:

select * from user where id=1234;
select * from user where id > 1234 and id < 2345

我們前面學到的數據結構中:

  • 散列表:等值查詢時間復雜度為O(1),但可能存在hash沖突的問題,且范圍查詢不支持;
  • 二分查找樹:可能失衡
  • 平衡二叉樹(AVL,紅黑樹):范圍查詢仍然不方便,且樹的高度為logn;
  • 跳表:插入、查找、刪除數據的時間復雜度都為logn,同時支持區間查詢,但是logn的時間復雜度仍然過高。且B+樹提出于1972年,跳表提出于1989年,所以B+樹才是爸爸。

綜上,我們必須要降低樹的高度,所以肯定是多叉樹。

  • B樹:
數據結構不迷茫

 

  • B+樹
數據結構不迷茫

 

我們來對比下B樹和B+樹:

B B+ 存儲結構 每個節點存數據 葉子節點存數據,非葉子節點存儲索引。所以可以存放更多的數據 查找性能 不穩定 穩定,必須查找到葉子節點 范圍查詢 不支持 支持

所以,mysql的索引選擇了B+樹。那么B+樹是怎么演化來的呢?

如果我們對二分查找樹進行改造,樹中的節點并不存儲數據本身,而是只是作為索引。除此之外,我們把每個葉子節點串在一條鏈表上,鏈表中的數據是從小到大有序的。

數據結構不迷茫

 

如果我們要為上億的數據建立索引,比如,我們給一億個數據構建二叉查找樹索引,那索引中會包含大約 1 億個節點,每個節 點假設占用 16 個字節,那就需要大約 1GB 的內存空間。給一張表建立索引,我們需要 1GB 的內存空間。如果我們要給 10 張表建立索引,那對內存的需求是無法滿足的。如何解決這個索引占用太多內存的問題呢?

答案是把索引存放到硬盤中,但是如此一來,需要從硬盤中讀取數據,速度是無法忍受的,因為樹高是需要IO的次數,所以要降低樹高。答案是多叉樹。

數據結構不迷茫

 

那多叉樹的m到底是多少比較好呢?不管是內存中的數據,還是磁盤中的數據,操作系統都是按頁(一頁大小通常是 4KB,這 個值可以通過 getconfig PAGE_SIZE 命令查看)來讀取的,一次會讀一頁的數據。如果要 讀取的數據量超過一頁的大小,就會觸發多次 IO 操作。所以,我們在選擇 m 大小的時 后,要盡量讓每個節點的大小等于一個頁的大小。讀取一個節點,只需要一次磁盤 IO 操作。

數據結構不迷茫

 

總結

我們可以看到,任何一種技術都是為了解決在某些場景下,其他的方案存在的某些問題,我們要理清這種內部的關系,這樣我們才可以了然于胸。

這篇文章的字數不多,但是希望可以幫助你梳理下常見的數據結構,在學習的時候不至于迷茫。

參考

數據結構與算法之美:https://time.geekbang.org/column/intro/126

分享到:
標簽:數據結構
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定