[STL] Implement "map", "set"

練習熱身

Ref: STL中map的數據結構html

C++ STL中標準關聯容器set, multiset, map, multimap內部採用的就是一種很是高效的平衡檢索二叉樹:紅黑樹,也成爲RB樹(Red-Black Tree)。RB樹的統計性能要好於通常的平衡二叉樹(有些書籍根據做者姓名,Adelson-Velskii和Landis,將其稱爲AVL-樹),因此被STL選擇做爲了關聯容器的內部結構。本文並不會介紹詳細AVL樹和RB樹的實現以及他們的優劣,關於RB樹的詳細實現參看紅黑樹: 理論與實現(理論篇)。本文針對開始提出的幾個問題的回答,來向你們簡單介紹map和set的底層數據結構。c++

 

(1) 爲什麼map和set的插入刪除效率比用其餘序列容器高?

相似list高效;所以插入的時候只須要稍作變換,把節點的指針指向新的節點就能夠了。刪除的時候相似,稍作變換後把指向刪除節點的指針指向其餘節點就OK了數據結構

 

(2) 爲什麼每次insert以後,之前保存的iterator不會失效?

內存沒有變,指向內存的指針怎麼會失效呢。app

 

(3) 爲什麼map和set不能像vector同樣有個reserve函數來預分配數據?

使用reserv() 函數預分配函數

假定你想創建一個容納1-1000值的vector。沒有使用reserve,你能夠像這樣來作:post

vector<int> v; 
for (int i = 1; i <= 1000; ++i) v.push_back(i);


在大多數STL實現中,這段代碼在循環過程當中將會致使2到10次從新分配。性能

使用reserve:ui

vector<int> v; 
v.reserve(1000);
for (int i = 1; i <= 1000; ++i)   v.push_back(i);

Thus, 這在循環中不會發生從新分配。
 this

(4) 當數據元素增多時(10000和20000個比較),map和set的插入和搜索速度變化如何?

這涉及到二叉樹的性質,便容易理解了。url

 

 

 

Boost Library

STL爲啥沒提供tree的接口

前幾天以爲STL中沒有樹和圖真是一種莫大的遺憾啊,可是在網上搜了搜,發現其實能夠用容器很簡單的構造樹。

There are two reasons you could want to use a tree:

You want to mirror the problem using a tree-like structure:
For this, we have boost graph library

Or you want a container that has tree like access characteristics For this we have

Basically, the characteristics of these two containers are such that they practically have to be implemented using trees (though this is not actually a requirement).

See also this question: C tree Implementation

 

The Boost Graph Library (BGL)

Ref: boost graph library

Algorithms

The BGL algorithms consist of a core set of algorithm patterns (implemented as generic algorithms) and a larger set of graph algorithms. The core algorithm patterns are

    • Breadth First Search
    • Depth First Search
    • Uniform Cost Search

 

By themselves, the algorithm patterns do not compute any meaningful quantities over graphs; they are merely building blocks for constructing graph algorithms. The graph algorithms in the BGL currently include

    • Dijkstra's Shortest Paths
    • Bellman-Ford Shortest Paths
    • Johnson's All-Pairs Shortest Paths
    • Kruskal's Minimum Spanning Tree
    • Prim's Minimum Spanning Tree
    • Connected Components
    • Strongly Connected Components
    • Dynamic Connected Components (using Disjoint Sets)
    • Topological Sort
    • Transpose
    • Reverse Cuthill Mckee Ordering
    • Smallest Last Vertex Ordering
    • Sequential Vertex Coloring

 

 

Boost 做爲「準標準庫」,其中包括了二十個分類,上述的graph屬於其中的一個。

 

 

褲衩樹

二叉樹基本概念

Ref: 二叉樹總結(一)概念和性質

二叉樹的性質

    • 在二叉樹中的第i層上至多有2^(i-1)個結點(i>=1)。
    • 深度爲k的二叉樹至多有2^k - 1個節點(k>=1)。
    • 對任何一棵二叉樹T,若是其葉結點數目爲n0,度爲2的節點數目爲n2,則n0=n2+1

滿二叉樹深度爲k且具備2^k-1個結點的二叉樹。即滿二叉樹中的每一層上的結點數都是最大的結點數。

徹底二叉樹深度爲k具備n個結點的二叉樹,當且僅當每個結點與深度爲k的滿二叉樹中的編號從1至n的結點一一對應。

    • 具備n個節點的徹底二叉樹的深度爲log2n + 1

 

  • 性質1:二叉樹第i層上的結點數目最多爲 2{i-1} (i≥1)

證實:下面用"數學概括法"進行證實。
        (01) 當i=1時,第i層的節點數目爲2{i-1}=2{0}=1。由於第1層上只有一個根結點,因此命題成立。
        (02) 假設當i>1,第i層的節點數目爲2{i-1}。這個是根據(01)推斷出來的!
               下面根據這個假設,推斷出"第(i+1)層的節點數目爲2{i}"便可。
                因爲二叉樹的每一個結點至多有兩個孩子,故"第(i+1)層上的結點數目" 最可能是 "第i層的結點數目的2倍"。即,第(i+1)層上的結點數目最大值=2×2{i-1}=2{i}
                故假設成立,原命題得證!

  • 性質2:深度爲k的二叉樹至多有2{k}-1個結點(k≥1)

證實:在具備相同深度的二叉樹中,當每一層都含有最大結點數時,其樹中結點數最多。利用"性質1"可知,深度爲k的二叉樹的結點數至多爲:
           20+21+…+2k-1=2k-1
           故原命題得證!

  • 性質3:包含n個結點的二叉樹的高度至少爲log2 (n+1)

證實:根據"性質2"可知,高度爲h的二叉樹最多有2{h}–1個結點。反之,對於包含n個節點的二叉樹的高度至少爲log2(n+1)。

  • 性質4:在任意一棵二叉樹中,若終端結點的個數爲n0,度爲2的結點數爲n2,則n0=n2+1

證實:由於二叉樹中全部結點的度數均不大於2,因此結點總數(記爲n)="0度結點數(n0)" + "1度結點數(n1)" + "2度結點數(n2)"。由此,獲得等式一。
         (等式一) n=n0+n1+n2
      另外一方面,0度結點沒有孩子,1度結點有一個孩子,2度結點有兩個孩子,故二叉樹中孩子結點總數是:n1+2n2。此外,只有根不是任何結點的孩子。故二叉樹中的結點總數又可表示爲等式二。
         (等式二) n=n1+2n2+1
        由(等式一)和(等式二)計算獲得:n0=n2+1。原命題得證!

  

二叉樹的初始化

Ref: 二叉樹總結(二)樹的遍歷

經過層次遍歷構造二叉樹。

 

二叉樹的進化

二叉樹總結(二)樹的遍歷

二叉樹總結(三)二叉搜索樹

二叉樹總結(四)平衡二叉樹

二叉樹總結(五)伸展樹、B-樹和B+樹

30張圖帶你完全理解紅黑樹

  

 

map and set

詳見:[c++] Associative Containers

 

End. 

相關文章
相關標籤/搜索