1.stl中的set底層用的什麼數據結構?
2.紅黑樹的數據結構怎麼定義的?
3.紅黑樹有哪些性質?
4.紅黑樹的各種操作的時間複雜度是多少?
5.紅黑樹相比於BST和AVL樹有什麼優點?
6.紅黑樹相對於哈希表,在選擇使用的時候有什麼依據?
7.如何擴展紅黑樹來獲得比某個結點小的元素有多少個?
8.擴展數據結構有什麼步驟?
9 爲什麼一般hashtable的桶數會取一個素數
詳細解答
1.stl中的set底層用的什麼數據結構?
紅黑樹
2.紅黑樹的數據結構怎麼定義?
- enum Color
- {
- RED = 0,
- BLACK = 1
- };
- struct RBTreeNode
- {
- struct RBTreeNode*left, *right, *parent;
- int key;
- int data;
- Color color;
- };
3.紅黑樹有哪些性質?
一般的,紅黑樹,滿足以下性質,即只有滿足以下全部性質的樹,我們才稱之爲紅黑樹:
1)每個結點要麼是紅的,要麼是黑的。
2)根結點是黑的。
3)每個葉結點(葉結點即指樹尾端NIL指針或NULL結點)是黑的。
4)如果一個結點是紅的,那麼它的倆個兒子都是黑的。
5)對於任一結點而言,其到葉結點樹尾端NIL指針的每一條路徑都包含相同數目的黑結點。
4.紅黑樹的各種操作的時間複雜度是多少?
能保證在最壞情況下,基本的動態幾何操作的時間均爲O(lgn)
5.紅黑樹相比於BST和AVL樹有什麼優點?
紅黑樹是犧牲了嚴格的高度平衡的優越條件爲代價,它只要求部分地達到平衡要求,降低了對旋轉的要求,從而提高了性能。紅黑樹能夠以O(log2 n)的時間複雜度進行搜索、插入、刪除操作。此外,由於它的設計,任何不平衡都會在三次旋轉之內解決。當然,還有一些更好的,但實現起來更復雜的數據結構能夠做到一步旋轉之內達到平衡,但紅黑樹能夠給我們一個比較“便宜”的解決方案。
相比於BST,因爲紅黑樹可以能確保樹的最長路徑不大於兩倍的最短路徑的長度,所以可以看出它的查找效果是有最低保證的。在最壞的情況下也可以保證O(logN)的,這是要好於二叉查找樹的。因爲二叉查找樹最壞情況可以讓查找達到O(N)。
紅黑樹的算法時間複雜度和AVL相同,但統計性能比AVL樹更高,所以在插入和刪除中所做的後期維護操作肯定會比紅黑樹要耗時好多,但是他們的查找效率都是O(logN),所以紅黑樹應用還是高於AVL樹的. 實際上插入 AVL 樹和紅黑樹的速度取決於你所插入的數據.如果你的數據分佈較好,則比較宜於採用 AVL樹(例如隨機產生系列數),但是如果你想處理比較雜亂的情況,則紅黑樹是比較快的
6.紅黑樹相對於哈希表,在選擇使用的時候有什麼依據?
權衡三個因素: 查找速度, 數據量, 內存使用,可擴展性。
總體來說,hash查找速度會比map快,而且查找速度基本和數據量大小無關,屬於常數級別;而map的查找速度是log(n)級別。並不一定常數就比log(n) 小,hash還有hash函數的耗時,明白了吧,如果你考慮效率,特別是在元素達到一定數量級時,考慮考慮hash。但若你對內存使用特別嚴格, 希望程序儘可能少消耗內存,那麼一定要小心,hash可能會讓你陷入尷尬,特別是當你的hash對象特別多時,你就更無法控制了,而且 hash的構造速度較慢。
紅黑樹並不適應所有應用樹的領域。如果數據基本上是靜態的,那麼讓他們待在他們能夠插入,並且不影響平衡的地方會具有更好的性能。如果數據完全是靜態的,例如,做一個哈希表,性能可能會更好一些。
在實際的系統中,例如,需要使用動態規則的防火牆系統,使用紅黑樹而不是散列表被實踐證明具有更好的伸縮性。Linux內核在管理vm_area_struct時就是採用了紅黑樹來維護內存塊的。
紅黑樹通過擴展節點域可以在不改變時間複雜度的情況下得到結點的秩。
7.如何擴展紅黑樹來獲得比某個結點小的元素有多少個?
這其實就是求節點元素的順序統計量,當然任意的順序統計量都可以需要在O(lgn)時間內確定。
在每個節點添加一個size域,表示以結點 x 爲根的子樹的結點樹的大小,則有
size[x] = size[[left[x]] + size [right[x]] + 1;
這時候紅黑樹就變成了一棵順序統計樹。
利用size域可以做兩件事:
1). 找到樹中第i小的結點;
- OS-SELECT(x;,i)
- r = size[left[x]] + 1;
- if i == r
- return x
- elseif i < r
- return OS-SELECT(left[x], i)
- else return OS-SELECT(right[x], i)
思路:size[left[x]]表示在對x爲根的子樹進行中序遍歷時排在x之前的個數,遞歸調用的深度不會超過O(lgn);
2).確定某個結點之前有多少個結點,也就是我們要解決的問題;
- OS-RANK(T,x)
- r = x.left.size + 1;
- y = x;
- while y != T.root
- if y == y.p.right
- r = r + y.p.left.size +1
- y = y.p
- return r
紅黑樹屬於平衡二叉樹。它不嚴格是因爲它不是嚴格控制左、右子樹高度或節點數之差小於等於1,但紅黑樹高度依然是平均log(n),且最壞情況高度不會超過2log(n)。
紅黑樹(red-black tree) 是一棵滿足下述性質的二叉查找樹:
每一個結點要麼是紅色,要麼是黑色。
根結點是黑色的。
所有葉子結點都是黑色的(實際上都是Null指針,下圖用NIL表示)。葉子結點不包含任何關鍵字信息,所有查詢關鍵字都在非終結點上。
每個紅色結點的兩個子節點必須是黑色的。換句話說:從每個葉子到根的所有路徑上不能有兩個連續的紅色結點
從任一結點到其每個葉子的所有路徑都包含相同數目的黑色結點
紅黑樹相關定理
從根到葉子的最長的可能路徑不多於最短的可能路徑的兩倍長。
根據上面的性質5我們知道上圖的紅黑樹每條路徑上都是3個黑結點。因此最短路徑長度爲2(沒有紅結點的路徑)。再根據性質4(兩個紅結點不能相連)和性質1,2(葉子和根必須是黑結點)。那麼我們可以得出:一條具有3個黑結點的路徑上最多只能有2個紅結點(紅黑間隔存在)。也就是說黑深度爲2(根結點也是黑色)的紅黑樹最長路徑爲4,最短路徑爲2。從這一點我們可以看出紅黑樹是 大致平衡的。 (當然比平衡二叉樹要差一些,AVL的平衡因子最多爲1)
紅黑樹的樹高(h)不大於兩倍的紅黑樹的黑深度(bd),即h<=2bd
根據定理1,我們不難說明這一點。bd是紅黑樹的最短路徑長度。而可能的最長路徑長度(樹高的最大值)就是紅黑相間的路徑,等於2bd。因此h<=2bd。
一棵擁有n個內部結點(不包括葉子結點)的紅黑樹的樹高h<=2log(n+1)
下面我們首先證明一顆有n個內部結點的紅黑樹滿足n>=2^bd-1。這可以用數學歸納法證明,施歸納於樹高h。當h=0時,這相當於是一個葉結點,黑高度bd爲0,而內部結點數量n爲0,此時0>=2^0-1成立。假設樹高h<=t時,n>=2^bd-1成立,我們記一顆樹高 爲t+1的紅黑樹的根結點的左子樹的內部結點數量爲nl,右子樹的內部結點數量爲nr,記這兩顆子樹的黑高度爲bd’(注意這兩顆子樹的黑高度必然一 樣),顯然這兩顆子樹的樹高<=t,於是有nl>=2^bd’-1以及nr>=2^bd’-1,將這兩個不等式相加有nl+nr>=2^(bd’+1)-2,將該不等式左右加1,得到n>=2^(bd’+1)-1,很顯然bd’+1>=bd,於是前面的不等式可以 變爲n>=2^bd-1,這樣就證明了一顆有n個內部結點的紅黑樹滿足n>=2^bd-1。
在根據定理2,h<=2bd。即n>=2^(h/2)-1,那麼h<=2log(n+1) 從這裏我們能夠看出,紅黑樹的查找長度最多不超過2log(n+1),因此其查找時間複雜度也是O(log N)級別的。
紅黑樹的操作
因爲每一個紅黑樹也是一個特化的二叉查找樹,因此紅黑樹上的查找操作與普通二叉查找樹上的查找操作相同。然而,在紅黑樹上進行插入操作和刪除操作會導致不 再符合紅黑樹的性質。恢復紅黑樹的屬性需要少量(O(log n))的顏色變更(實際是非常快速的)和不超過三次樹旋轉(對於插入操作是兩次)。 雖然插入和刪除很複雜,但操作時間仍可以保持爲 O(log n) 次 。
紅黑樹的優勢
紅黑樹能夠以O(log2(N))的時間複雜度進行搜索、插入、刪除操作。此外,任何不平衡都會在3次旋轉之內解決。這一點是AVL所不具備的。
而且實際應用中,很多語言都實現了紅黑樹的數據結構。比如 TreeMap, TreeSet(Java )、 STL(C++)等。
轉自:http://blog.csdn.net/silangquan/article/details/18655795
轉自:https://www.cnblogs.com/gofighting/p/5437998.html