1. 程式人生 > >陣列、連結串列、棧、佇列和STL【轉】

陣列、連結串列、棧、佇列和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實現優先佇列