1. 為什么用紅黑樹實現?
map, set底層都提供了排序功能,紅黑樹形式存儲的鍵值是有序的。同時紅黑樹可以在O(log n)時間內做插入,查找和刪除。
2. 紅黑樹的性質
紅黑樹是每個節點都帶有顏色屬性的二叉搜索樹,顏色要么是紅色,要么是黑色。
性質1:紅黑樹的每個節點要么是紅色,要么是黑色。
性質2:紅黑樹的根節點一定是黑色的。
性質3:紅黑樹的所有外部節點都是黑色的。(外部節點是擴充二叉樹中對所有空指針填充的節點)
性質4:紅黑樹的所有紅色節點的兩個子節點一定是黑色節點。(這就保證了紅黑樹從根到外部節點的任一條路徑上都不會有兩個連續的紅色節點)
性質5:紅黑樹從根到任意一個外部節點的路徑上的黑色節點的數目都是相同的。
3. HashMap和TreeMap底層實現的不同
C++中unordered_map的底層是用哈希表來實現的,通過key的哈希路由到每一個桶(即數組)用來存放內容。通過key來獲取value的時間復雜度就是O(1)。因為key的哈希容易碰撞,所以需要對碰撞做處理。unordered_map里的每一個數組(桶)里面存的其實是一個鏈表,key的哈希沖突以后會加到鏈表的尾部,這是再通過key獲取value的時間復雜度就變成O(n),當碰撞很多的時候查詢就會變慢。為了優化這個時間復雜度,map的底層就把這個鏈表轉換成了紅黑樹,這樣雖然插入增加了復雜度,但提高了頻繁哈希碰撞時的查詢效率,使查詢效率變成O(log n)。
4. 為什么使用紅黑樹而不是二叉搜索樹?
二叉搜索樹並不一定是一顆平衡樹,二叉搜索樹(BST)只是左子樹的值一定小於根節點,而右子樹的值一定大於根節點。如果插入的值是有序的,那么構造出來的二叉樹將是一個鏈表,它的時間復雜度將達到O(n)。而使用紅黑樹,可以通過對每個節點標色的方式,每次更新數據后進行平衡,保證查找效率。
5. 左旋,右旋操作
紅黑樹在插入數據時要保持它的平衡需要進行着色處理,配合左旋,右旋來保持它的平衡。可以認為紅色和黑色是為了更好地輔助平衡。平衡的操作如下:首先,新插入的節點必須是紅色。因為黑色破壞性質的可能性更大。實現平衡的公式如下:
假定X是新插入的節點,P是父節點,Y是叔父節點,G是祖父節點,P是G的左孩子
當Y為紅色->P,Y變黑,G變紅,X變G
當Y為黑色,X是右孩子->左旋P,X變P
當Y為黑色,X為左孩子->G變紅,P變黑,右旋G
當P為G的右孩子,直接做鏡像操作就可以。
一個紅黑樹插入節點的實例可以參考:https://blog.csdn.net/mxway/article/details/29216199?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-2&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-2