4.1 序列式容器:其中的元素都可許,但未必有序,有array,vector,list,deque;配接器:stack,queue,priority_queue。
4.2 vector:其實就是動態數組,配置較大的空間,用於添加元素,避免多次申請空間,不斷的重複“配置新空間、資料移動、釋放舊空間”的過程。
vector預設使用了alloc空間配置器,定義了其5個型別pointer等,其中iterator為T*(vector泛型參數類型的指標),主要包括了start、finish(當前已使用元素的下一個位置)、end_of_storage(表示目前可用空間的尾)和一些函數。
STL源碼剖析上有這些函數的定義式,vector使用push_back在尾部插入元素,如果finish!=end_of_storage,則使用全域函數construct在finish處加入x的值,finish後移一位;否則,需要申請當前大小2倍的空間,複製舊元素,添加x,釋放就空間,而這裡面都是使用的2.3的記憶體基本處理工具的全域函數,包含在<memory>標頭檔中。
erase的重載函數實現了元素的刪除功能,先將最後一個要刪除元素的下一個值到尾部的值,利用全域函數copy複製到第一個要刪除元素的位置,然後利用destroy函數釋放掉從finish處往前的刪除元素個數值。
insert(iterator position,size_type n, const T& x):在position開始,插入n個x
經觀察,只考察n>0的情況,當end_of_storage-finish>=n即備用空間大於插入元素個數時,不需要新申請空間,此時考慮兩種情形,1.插入點之後的元素大於n,先將finish前的n個元素插入到finish後n個位置,再將position到finish-n之間的元素插入到finish之前,最後在po
sition處填充n個x,(有點亂,大概是這個意思,但是沒有準確的畫出來,只是大概標示了步驟2的位置在finish前);2.插入後的現有元素個數(elems_after)>=n,現在finish後添加n-elems_after個x,然後將position到finish之間的元素複製到x之後,把position到finish之間的元素設定為x。如果備用空間不足時,申請舊長度的兩倍或者舊長度和新增元素個數,然後,將原來position前的元素複製到新空間起始處,添加n個x,再把position後的元素複製到x之後。
4.3 list:雙向迴圈鏈表,有一個沒有值的頭結點,用於標示空鏈表,此時prev和next都指向結點本身。
list的操作,其實都是對雙向迴圈鏈表的操作,而且不用特殊的處理頭結點,思路相對簡單,只要注意結點類型和迭代器的類型即可。
list的遷移操作transfer實現了將迭代器範圍內的元素插入到指定位置,其它的splice、merge等操作都使用了該函數。其中sort函數我感覺比較好,書上說採用了quick sort方法,建議大家看一下(PS:我不太懂!!!)
4.4 deque:雙向開口的連續空間,他是動態以分段連續空間組合而成,隨時增加一段新的空間並串連起來。
deque使用所謂的map控制這些分段的空間,建議看一下書上的幾個圖片,就知道deque實現的原理了,但是,實現起來估計很麻煩。
4.5 stack:採用deque實現,使用deque的方法就可以實現stack的FILO功能。
4.6queue:預設採用deque實現,同stack。其中stack和queue都沒有迭代器。
4.7 heap:基於vector的完全二叉樹,預設是大頂堆。
push_heap:將新插入的元素放到最下一層的最右邊作為葉子結點,不斷與父節點比較,若大於父節點的值,就交換,直至小於父節點,該位置就是新插入元素的位置。
pop_heap:去掉各節點(len/2),從上到下,將左右孩子中較大的結點放入到根節點處,迴圈進行直到到達葉子結點,然後將最後一個結點放入到剛剛的葉子結點中,再利用push_heap的方法調整heap。但是,最大值並沒有刪除,只是放到了最後的位置。(PS:為什麼不之間把最後一個結點和根調換,然後從上到下開始調整呢?這個最多隻要一個logN啊????)
其他的函數都是建立在這兩個函數的基礎上的,不斷的插入和讀取。
4.8 priority_queue:優先權隊列,基於heap實現的。push就是push_heap,pop即pop_heap,然後在刪除元素。