在網上學習了一些材料。html
這一篇:https://www.zhihu.com/question/30527705node
AVL樹:最先的平衡二叉樹之一。應用相對其餘數據結構比較少。windows對進程地址空間的管理用到了AVL樹 紅黑樹:平衡二叉樹,普遍用在C++的STL中。map和set都是用紅黑樹實現的。咱們熟悉的STL的map容器底層是RBtree,固然指的不是unordered_map,後者是hash。 B/B+樹用在磁盤文件組織 數據索引和數據庫索引 Trie樹 字典樹,用在統計和排序大量字符串 ------ AVL是一種高度平衡的二叉樹,因此一般的結果是,維護這種高度平衡所付出的代價比從中得到的效率收益還大,故而實際的應用很少,
更多的地方是用追求局部而不是很是嚴格總體平衡的紅黑樹。固然,若是場景中對插入刪除不頻繁,只是對查找特別有要求,AVL仍是優於紅黑的。 紅黑樹的應用就不少了,除了上面同窗提到的STL,還有 epoll在內核中的實現,用紅黑樹管理事件塊 nginx中,用紅黑樹管理timer等 Java的TreeMap實現 著名的linux進程調度Completely Fair Scheduler,用紅黑樹管理進程控制塊 B和B+主要用在文件系統以及數據庫中作索引等,好比Mysql:B-Tree Index in MySql trie 樹的一個典型應用是前綴匹配,好比下面這個很常見的場景,在咱們輸入時,搜索引擎會給予提示 還有好比IP選路,也是前綴匹配,必定程度會用到trie ------ 跳錶:Redis中就使用跳錶,而不是紅黑樹來存儲管理其中的元素(應該說的是一級元素-直接的Key,裏面的value應該是有不一樣的數據結構)。 首先,跳錶是skiplist?不是ziplist。ziplist在redis中是一個很是省內存的鏈表(代價是性能略低),因此在hash元素的個數不多(好比只有幾十個),
那麼用這個結構來存儲則能夠在性能損失很小的狀況下節約不少內存(redis是內存數據庫啊,能省仍是要省的)。好這個問題清楚了。 在server端,對併發和性能有要求的狀況下,如何選擇合適的數據結構(這裏是跳躍表和紅黑樹)。 若是單純比較性能,跳躍表和紅黑樹能夠說相差不大,可是加上併發的環境就不同了,
若是要更新數據,跳躍表須要更新的部分就比較少,鎖的東西也就比較少,因此不一樣線程爭鎖的代價就相對少了,
而紅黑樹有個平衡的過程,牽涉到大量的節點,爭鎖的代價也就相對較高了。性能也就不如前者了。 在併發環境下skiplist有另一個優點,紅黑樹在插入和刪除的時候可能須要作一些rebalance的操做,這樣的操做可能會涉及到整個樹的其餘部分,
而skiplist的操做顯然更加局部性一些,鎖須要盯住的節點更少,所以在這樣的狀況下性能好一些。
另外Redis做者描述的使用跳錶的緣由:linux
請看開發者說的,他爲何選用skiplist The Skip list There are a few reasons: 1) They are not very memory intensive. It's up to you basically.
Changing parameters about the probability of a node to have a given number of levels will make then less memory intensive
than btrees.
注:跳錶的一個缺點是耗內存(由於要重複分層存節點),可是做者也說了,能夠調參數來下降內存消耗,和那些平衡樹結構達到差很少。
2) A sorted set is often target of many ZRANGE or ZREVRANGE operations, that is, traversing the skip list as a linked list.
With this operation the cache locality of skip lists is at least as good as with other kind of balanced trees.
注:redis經查有範圍操做,這樣利用跳錶裏面的雙向鏈表,能夠方便地操做。另外還有緩存區域化(cache locality)不會比平衡樹差。
3) They are simpler to implement, debug, and so forth. For instance thanks to the skip list simplicity I received a patch
(already in Redis master) with augmented skip lists implementing ZRANK in O(log(N)). It required little changes to the code.
注:實現簡單。zrank操做可以到O(log(N)).
About the Append Only durability & speed, I don't think it is a good idea to optimize Redis at cost of more code
and more complexity for a use case that IMHO should be rare for the Redis target (fsync() at every command).
Almost no one is using this feature even with ACID SQL databases, as the performance hint is big anyway.
About threads: our experience shows that Redis is mostly I/O bound. I'm using threads to serve things from Virtual Memory.
The long term solution to exploit all the cores, assuming your link is so fast that you can saturate a single core,
is running multiple instances of Redis (no locks, almost fully scalable linearly with number of cores),
and using the "Redis Cluster" solution that I plan to develop in the future.
上面文章中有一些英文縮寫,整理以下:nginx
imho, imo(in my humble opinion, in my opinion):在我看來,常見於論壇。
idk(I don’t know):我不知道。
rofl(rolling on the floor laughing):笑到摔到地上。
roflmao(rolling on the floor laughing my ass of):前兩個的結合版,也就是超級搞笑的意思。
sth(something):某事某物。
nth(nothing):什麼也沒有。
plz(please):請。please 字尾是z 音,因此按照讀音縮寫爲plz。
thx(thanks):謝謝。按照發音來看,thanks字尾的ks能夠用字母X代替。
紅黑樹與B(+)樹工程實現的比較:redis
已有的幾個答案都是從算法角度分析的,我嘗試分析下從工程角度區分成黑樹與b+樹的應用場景,紅黑樹一個node只存一對kv,所以可使用相似嵌入式鏈表的方式實現,
數據結構自己無論理內存,比較輕量級,使用更靈活也更省內存,好比一個node能夠同時存在若干個樹或鏈表中,內核中比較常見。
而b+樹因爲每一個node要存多對kv,node結構的內存通常就要由數據結構本身來管,是真正意義上的container,相對嵌入式方法實現的紅黑樹,
好處是用法簡單,本身管理內存更容易作lockfree,一個node存多對kv的方式cpu cache命中率更高,因此用戶態實現的高併發索引通常仍是選b+樹。
再說b樹與b+樹,btree的中間節點比b+樹多存了value,一樣出度的狀況下,node更大,相對來講cpu cache命中率是不如b+樹的。
另外再提一句,b+樹的掃描特性(鏈表串起來的葉子節點)在無鎖狀況下是很難作的(我還沒見到過解法),所以我目前見到的無鎖b+樹葉子節點都是不串起來的。
從各自特色特徵角度,分析各類數據結構的應用場景:算法
紅黑樹,AVL樹簡單來講都是用來搜索的唄。
AVL樹:平衡二叉樹,通常是用平衡因子差值決定並經過旋轉來實現,左右子樹樹高差不超過1,那麼和紅黑樹比較它是嚴格的平衡二叉樹,平衡條件很是嚴格(樹高差只有1),
只要插入或刪除不知足上面的條件就要經過旋轉來保持平衡。因爲旋轉是很是耗費時間的。咱們能夠推出AVL樹適合用於插入刪除次數比較少,但查找多的狀況。 紅黑樹:平衡二叉樹,經過對任何一條從根到葉子的簡單路徑上各個節點的顏色進行約束,確保沒有一條路徑會比其餘路徑長2倍,於是是近似平衡的。
因此相對於嚴格要求平衡的AVL樹來講,它的旋轉保持平衡次數較少。用於搜索時,插入刪除次數多的狀況下咱們就用紅黑樹來取代AVL。 (如今部分場景使用跳錶來替換紅黑樹,可搜索「爲啥 redis 使用跳錶(skiplist)而不是使用 red-black?」) B樹,B+樹:它們特色是同樣的,是多路查找樹,通常用於數據庫系統中,爲何,由於它們分支多層數少唄,
都知道磁盤IO是很是耗時的,而像大量數據存儲在磁盤中因此咱們要有效的減小磁盤IO次數避免磁盤頻繁的查找。 B+樹是B樹的變種樹,有n棵子樹的節點中含有n個關鍵字,每一個關鍵字不保存數據,只用來索引,數據都保存在葉子節點。是爲文件系統而生的。 Trie樹: 又名單詞查找樹,一種樹形結構,經常使用來操做字符串。它是不一樣字符串的相同前綴只保存一份。 相對直接保存字符串確定是節省空間的,可是它保存大量字符串時會很耗費內存(是內存)。
相似的有 前綴樹(prefix tree),後綴樹(suffix tree),radix tree(patricia tree, compact prefix tree),crit-bit tree(解決耗費內存問題),
以及前面說的double array trie。 簡單的補充下我瞭解應用 前綴樹:字符串快速檢索,字符串排序,最長公共前綴,自動匹配前綴顯示後綴。 後綴樹:查找字符串s1在s2中,字符串s1在s2中出現的次數,字符串s1,s2最長公共部分,最長迴文串。 radix tree:linux內核,nginx。
紅黑樹的介紹能夠看這兩篇文章:史上最清晰的紅黑樹講解(上)+(下)sql
http://mt.sohu.com/20161014/n470317653.shtml數據庫
http://mt.sohu.com/20161018/n470610910.shtmlwindows
當查找樹的結構發生改變時,紅黑樹的條件可能被破壞,須要經過調整使得查找樹從新知足紅黑樹的條件。
調整能夠分爲兩類: 一類是顏色調整,即改變某個節點的顏色; 另外一類是結構調整,集改變檢索樹的結構關係。結構調整過程包含兩個基本操做:左旋(Rotate Left),右旋(RotateRight)
記住,不管有多少狀況,具體的調整操做只有兩種:1.改變某些節點的顏色,2.對某些節點進行旋轉。
另開一文分析字符串相關的各類算法,以及用到的各類數據結構,包括前綴樹後綴樹等各類樹。緩存