AVL 紅黑樹 B(+)樹 跳錶 字典樹 應用場景及分析
1 AVL樹:平衡二叉樹,一般是用平衡因子差值決定並通過旋轉來實現,左右子樹樹高差不超過1,那麼和紅黑樹比較它是嚴格的平衡二叉樹,平衡條件非常嚴格(樹高差只有1),只要插入或刪除不滿足上面的條件就要通過旋轉來保持平衡。由於旋轉是非常耗費時間的。我們可以推出AVL樹適合用於插入刪除次數比較少,但查詢多的情況。
2 紅黑樹:平衡二叉樹,通過任何一條從根到葉子的簡單路徑上各個節點的顏色進行約束,確保沒有一條路徑會比其他路徑長2倍,因而是近似平衡的。所以相對於嚴格要求平衡的AVL樹來說,它的旋轉保持平衡次數較少。用於搜尋時,插入刪除次數多的情況下我們使用紅黑樹來取代AVL。(現在部分場景使用跳錶來替換紅黑樹)
紅黑樹應用:c++ STL
epoll 在核心中的實現,用紅黑樹來管理事件塊
nginx中,用紅黑樹來管理timer等
Java中的TreeMap實現
著名的linux程序排程Completely Fair Scheduler,用紅黑樹管理程序控制塊
3 B樹 B+樹:他們的特點是一樣的,是多路查詢樹,一般用於資料庫系統,為什麼?因為他們分支多層數少,都知道磁碟IO是非常耗時的,而像大量資料儲存在磁碟中所以我們要有效的減少磁碟IO次數避免磁碟頻繁的查詢。B+樹是B樹的變種,資料都儲存在葉子節點。是為檔案系統而生的。
4 Tire樹:又名單詞查詢樹,一種樹型結構,常用來操作字串。它是不同字串的相同字首只儲存一份。相對直接儲存字串肯定是節省空間的,但是它儲存大量字串時會很耗費記憶體(是記憶體)。類似的有字首樹,字尾樹,radix tree(patricia tree, compact prefix tree)) ,crit-bit tree(解決耗費記憶體問題),以及前面說的double array trie。簡單的補充下我瞭解應用的字首樹:字串快速檢索,字串排序,最長公共字首,自動匹配字首顯示字尾。字尾樹:查詢字串s1 在s2 中,字串s1在s2中出現的次數,字串s1,s2最長公共部分,最長迴文串。radix tree:linux 核心,nginx。
PS:Redis 中使用跳錶,而不是紅黑樹來儲存管理其中的元素(應該說的是一級元素-直接的Key,裡面的value應該是有不同的資料結構)
首先,條表示SkipList 不是ZipList .ZipList 在redis中是有一個非常省記憶體的連結串列(代價是效能略低),所以在hash元素的個數很少(比如只有幾十個),那麼用這個結構來儲存則可以效能損失很少的情況下節約很多記憶體(Redis 是記憶體資料庫,能省還是要省)
在server端,對併發和效能有要求的情況下,如何選擇合適的資料結構(這裡是跳躍表和紅黑樹)。如果在單純比價效能,跳躍表和紅黑樹可以說相差不打,但是加上併發的環境就不一樣了,如果要更新資料,跳躍表需要更新的部分就比較少,鎖的東西也就比較少,所以不同執行緒爭鎖的代價就相對少了,而在紅黑樹有個平衡的過程,牽涉到大量的節點,爭鎖的代價就相對高了。效能也就不如前者。在併發環境下skiplist的操作顯然更加區域性性一些,鎖需要盯住的節點更少,因此這樣的情況下效能好一些。