陣列、連結串列、棧、佇列和STL【轉】
陣列
陣列是一種最基本的資料結構,它是記憶體上的一塊連續儲存空間。正因如此陣列的隨機訪問很方便。但陣列也有其固有的限制,大小分配後不能改變。
STL中的陣列
STL中的Array是靜態陣列模板,就是我們所說的陣列。使用方法如下。
std::array<int, 3> a1 = { 1, 2, 3 };
std::array<std::string, 2>a3 = {"a","b"};
STL中的Vector是動態陣列模板,根據需要動態的分配記憶體。Vector的採用加倍的擴容策略。Push_back()最壞情況,最好和平均情況是。陣列和動態陣列常用來組成更復雜的資料結構。
連結串列
連結串列是一種線性表(有n個元素組成的有限序列),連結串列是一種基礎的資料結構,通常有一連串的節點組成。節點中存放資料和指向下一節點的指標。因為連結串列不是按線性的順序儲存結構,其查詢某節點的時間是,插入操作。連結串列分為單鏈表,雙鏈表和迴圈連結串列。
單鏈表
雙鏈表
迴圈單鏈表
迴圈雙鏈表
連結串列的效能比較
單鏈表和雙鏈表的查詢時間最好情況,最壞和平均情況。
單鏈表涉及到向前訪問的操作Before(),InsertBefore(),Remove()最壞和平均情況,最好情況。其他查詢更新操作。
雙鏈表的所有操作都是。
STL中的連結串列
List是用普通雙鏈表實現的,如果在實際應用中需要使用連結串列,那麼首先應該選擇List。或者將List作為其成員。
連結串列和陣列的對比
陣列 |
動態陣列 |
連結串列 |
快速的隨機訪問 |
快速的隨機訪問 |
快速的插入和刪除 |
大小受限 |
動態分配 |
容量不受限 |
插入刪除費時 |
插入刪除費時 |
隨機訪問慢 |
Forward_list是C++11新增的,實現為一種簡單的單鏈表,沒有size()成員,只有前向迭代器沒有反向迭代器。
棧
棧是一種後進先出的資料結構,可以用陣列也可用連結串列實現。連結串列的實現形式更接近於棧的抽象概念,因為連結串列的節點數與棧中元素數目相同,而在陣列實現形式中,陣列的容量常常超過其尺寸。棧的直接應用包括函式呼叫,網頁瀏覽記錄,編輯器中的重做。。。棧也是其它資料結構和演算法的基本元件。
順序棧(用陣列實現的棧)
鏈式棧(用連結串列實現的棧)
棧的效能比較
STL中的棧
STL中的stack是一種容器介面卡,就是用其他容器最為底層實現,將其他容器轉化為棧。Stack封裝了入棧,出棧,取棧頂元素,檢視大小和是否為空操作。預設情況下,stack用deque做底層容器。也可以將其修改為vector,list。
std::stack<int> deque_stack;
std::stack<int, std::vector<int>> vec_stack;
std::stack<int, std::list<int>> list_stack;
佇列
佇列是一種先進先出的資料結構,可以用陣列也可以用連結串列實現佇列。佇列可用訪問共享資源,排隊購物。還用來構成其他更復雜的資料結構。
基於陣列的佇列
基於連結串列的佇列
佇列的效能分析
雙端佇列
雙端佇列的效能分析
優先佇列
許多情況下佇列的先入先出機制不能滿足要求,此時需通過優先規則來完善入隊出隊的機制。優先佇列應用而生。實現方式有兩種:1.基於有序連結串列的實現,插入操作,刪除操作;2.基於無序連結串列的實現,插入操作,刪除操作。
堆(堆放在這裡說是因為最大堆可用來實現優先佇列)
堆是一種資料結構,完全二叉樹,但在實現方式上沒有選擇一般的二叉樹資料結構(即一個結點包含兩個指向孩子的指標)而使用了陣列。要明白堆的含義,必須知道什麼是完全二叉樹,完全二叉樹是有滿二叉樹引起的,瞭解滿二叉樹也是必要的。
一般的樹中,某結點的高度和深度的定義。
滿二叉樹: 如果一個二叉樹的任意結點或者有0或者有2個孩子。
完全二叉樹:如果一個二叉樹除倒數第一層外都被填滿,並且倒數第一層從左至右填充。
完美樹:如果一個二叉樹的所有層被填滿。
堆的定義:1.是一個完全二叉樹;2.上層的節點鍵值大於下層節點鍵值(最小堆),或者相反(最大堆)。
基於陣列實現的堆
某節點位於陣列i處,做左子節點位於2i,右子節點位於2i+1,陣列第一個位置未使用。
STL中的佇列
1.queue
STL中的queue是一種容器介面卡,預設的底層實現容器是deque。這一點和stack很像,通過關閉或者限制deque的一些藉口可以很輕鬆的實現stack和queue。Deque是stack和queue的幕後功臣。那麼deque是怎麼實現的?
2.deque
Deque是雙端佇列,它的空間構造是幾塊分段線性的儲存區。其實現細節非常複雜。
Deque是如何擴充套件空間的?
如果緩衝區中還有備用的空間,那麼直接使用備用的空間;否則,另外配置一個緩衝區,將其資訊記錄到緩衝區地址表裡;更有甚者,如果緩衝區地址表都不夠的時候,緩衝區地址表也要嚴格依從"重新配置,複製,釋放"規則,但相比對"重新配置,複製,釋放"規則宗教式追狂熱的vector而言,效率高很多。侯傑老師推薦,將deque所有的元素倒騰到一個vector中,再用STL<algorithm>的sort()函式,再從vector中倒騰進deque中。這種折騰是必須的,直接在的deque內部進行排序,效率更低。(引http://daoluan.net/blog/stl-deque/)
3.priority_queue
Priority_queue優先順序佇列是一個擁有權值概念的單向佇列queue,在STL的具體實現中也是以別的容器為底層資料結構,在利用堆的規則調整元素之間的位置。預設的底層實現是vector。這與queue的預設底層實現deque差別很大。
4.heap
STL中關於堆的操作,建堆make_heap(),加資料push_heap(),刪資料pop_heap(),堆排序sort_heap()。標頭檔案<algorithm>。
總結
陣列 |
靜態陣列=array |
動態陣列=vector |
|
連結串列 |
單鏈表= forward_list |
雙鏈表=list |
|
佇列 |
單向佇列=queue(預設deque) |
單向陣列佇列=queue<型別,vector<型別>> |
|
單向鏈式佇列=queue<型別,list<型別>> |
|
雙向佇列=deque |
|
優先佇列=priority_queue(預設vector) |
|
堆疊 |
meak_heap,push_heap,pop_heap,sort_heap |
練習
1.手寫堆
2.利用STL實現優先佇列