學習過c++的朋友們應該對stl和泛型程式設計這兩個名詞不會陌生。兩者之間的關係不言而喻,泛型程式設計的思想促使了stl的誕生,而stl則很好地體現了泛型程式設計這種思想。這次想簡單說一下stl在acm中的一些應用。我們知道,在acm競賽中,經常需要用到陣列、字串、佇列、堆疊、鍊錶等資料結構和排序、搜尋等演算法,以提高程式的時間、空間執行效率。然而如果這些資料結構總是需要手工來編寫,那無疑會是一件很麻煩的工作,而stl的出現很好地解決了這個問題。
我們簡單來了解一下stl。stl提供了三種型別的元件:容器、迭代器和演算法。容器主要有兩類:順序容器和關聯容器。順序容器(vector、list、deque和string等)是一系列元素的有序集合。關聯容器(set、multiset、map和multimap)包括查詢元素的鍵值。迭代器的作用是遍歷容器。stl演算法庫包含四類演算法:排序演算法、不可變序演算法、變序性演算法和數值演算法。下面就簡單介紹一下stl裡常用的容器。
1. vector向量容器
vector向量容器不但像陣列一樣對元素進行隨機訪問,還能在尾部插入元素,是一種簡單、高效的容器,完全可以替代陣列。由於vector具有記憶體自動管理的功能,對於元素的插入和刪除,可動態調整所佔的記憶體空間,因此使用時不需要考慮釋放空間的問題。使用vector向量容器時,需要包含標頭檔案「vector」。(即#include )對於vector容器的容量定義,可以事先定義乙個固定大小,事後可以隨時調整其大小;(例如vectorv(10); //定義乙個用來儲存10個int型別元素的向量容器)也可以事先不用定義其大小,使用push_back()方法從尾部擴張元素,也可以使用insert()在某個元素位置前插入新元素。
vector容器有兩個重要的方法,begin()和end()。begin()返回的是首元素位置的迭代器;end()返回的是最後乙個元素的下乙個元素位置的迭代器。通常在遍歷vector所有元素時會用到這兩個方法。例如:
vector<
int
> v(3);
vector<
int
>::iterator it;
for
(it=v.begin(); it!=v.end(); it++)
至於vector元素的刪除,呼叫erase()方法可以刪除vector中迭代器所指的乙個元素或一段區間中的所有元素,clear()方法則可以刪除vector中所有元素。
通過使用size()方法可以返回向量的大小,即元素個數,呼叫empty()方法返回向量是否為空。
再簡單看一下在vector中常用到的演算法。使用reverse()反向排列演算法,需要定義標頭檔案「#include 」,reverse()演算法可將向量中某段迭代器區間元素反向排列;使用sort演算法可以對向量排序,預設情況下對元素進行公升序排列,也可以自己設計排序比較函式,具體使用細節就不贅述了。
2. string基本字元系列容器
c語言中對於字串只能使用字元陣列來處理,顯得十分不方便。c++ stl提供了string基本字串行容器來處理字串,可以把string理解為字串類,它提供了新增、刪除、替換、查詢和比較等豐富方法。使用string容器需要包含標頭檔案宣告「#include 」。
3. set集合容器
set集合容器實現了紅黑樹的平衡二叉檢索樹的資料結構,在插入元素時,它會自動調整二叉樹的排列,把該元素放到適當的位置,以確保每個子樹根節點的鍵值大於左子樹所有節點的鍵值,而小於右子樹所有節點的鍵值;另外,還得確保根節點左子樹的高度與右子樹的高度相等,因為二叉樹高度最小,檢索速度最快。這裡要注意的是,set容器不會插入相同鍵值的元素。
平衡二叉檢索樹的檢索使用中序遍歷演算法,檢索效率高於vector、deque和list等容器。另外,採用中序遍歷演算法可將鍵值由小到大遍歷出來,所以,可以理解為平衡二叉檢索樹在插入元素時,就會自動將元素按鍵值由小到大的順序排列。由於構造set集合的主要目的就是為了快速檢索,對於set容器中的鍵值,不可直接去修改。multiset、map和multimap的內部結構也是平衡二叉檢索樹。
4. multiset多重集合容器
multiset與set一樣,也是使用紅黑樹來組織元素資料的,唯一不同的是,multiset允許重複的元素鍵值插入,而set則不允許。multiset也需要宣告標頭檔案包含「#include 」,由於它包含重複元素,所以在插入元素、刪除元素、查詢元素上較set有差別。
5. map映照容器
map映照容器的元素資料是由乙個鍵值和乙個映照資料組成的,鍵值與映照資料之間具有一一映照的關係。map映照容器的資料結構也是採用紅黑樹來實現的,插入元素的鍵值不允許重複,比較函式只對元素的鍵值進行比較,元素的各項資料可通過鍵值檢索出來。由於map與set採用的都是紅黑樹的資料結構,所以它們的用法基本類似。使用map容器需要標頭檔案包含語句「#include 」。
6. multiset多重映照容器
multiset與map基本相同,唯獨不同的是,mulitiset允許插入重複鍵值的元素。由於允許重複鍵值存在,所以multiset的元素插入、刪除、查詢都與map不相同。
7. deque雙端佇列容器
deque雙端佇列容器與vector一樣,採用線性表順序儲存結構。但與vector唯一不同的是,deque採用分塊的線性儲存結構來儲存資料,每塊的大小一般為512位元組,稱為乙個deque塊,所有的deque塊使用乙個map塊進行管理,每個map資料項紀錄每個deque塊的首位址。這樣,deque塊在頭部和尾部都可插入和刪除元素,而不需移動其他元素。一般來說,當考慮到容器元素的記憶體分配策略和操作的效能時,deque相對於vector會更有優勢。使用deque需要宣告標頭檔案包含「#include 」。
8. list雙向鍊錶容器
list容器實現了雙向鍊錶的資料結構,資料元素是通過鍊錶指標串連成邏輯意義上的線性表,這樣,對鍊錶的任一位置的元素進行插入、刪除和查詢都是極快速的。由於list物件的節點並不要求在一段連續的記憶體中,所以對於迭代器,只能通過「++」或「--」的操作將迭代器移動到後繼/前驅節點元素處。而不能對迭代器進行+n或-n的操作,這點是與vector等不同的地方。使用list需要宣告標頭檔案包含「#include 」。
9. stack堆疊容器
stack堆疊是乙個後進先出的線性表,插入和刪除元素都只能在表的一端進行。插入元素的一端稱為棧頂,另一端稱為棧底。插入元素叫入棧,元素的刪除稱為出棧。要使用stack必須宣告標頭檔案包含語句「#include 」。
10. queue佇列容器
queue佇列容器是乙個先進先出的線性儲存表,元素的插入只能在隊尾,元素的刪除只能在隊首。使用queue需要宣告標頭檔案包含語句「#include 」 。
C STL泛型程式設計 在ACM中的運用
學習過c 的朋友們應該對stl和泛型程式設計這兩個名詞不會陌生。兩者之間的關係不言而喻,泛型程式設計的思想促使了stl的誕生,而stl則很好地體現了泛型程式設計這種思想。這次想簡單說一下stl在acm中的一些應用。我們知道,在acm競賽中,經常需要用到陣列 字串 佇列 堆疊 鍊錶等資料結構和排序 搜...
C STL泛型程式設計 在ACM中的運用
學習過c 的朋友們應該對stl和泛型程式設計這兩個名詞不會陌生。兩者之間的關係不言而喻,泛型程式設計的思想促使了stl的誕生,而stl則很好地體現了泛型程式設計這種思想。這次想簡單說一下stl在acm中的一些應用。我們知道,在acm競賽中,經常需要用到陣列 字串 佇列 堆疊 鍊錶等資料結構和排序 搜...
C STL泛型程式設計 在ACM中的運用
學習過c 的朋友們應該對stl和泛型程式設計這兩個名詞不會陌生。兩者之間的關係不言而喻,泛型程式設計的思想促使了stl的誕生,而stl則很好地體現了泛型程式設計這種思想。這次想簡單說一下stl在acm中的一些應用。我們知道,在acm競賽中,經常需要用到陣列 字串 佇列 堆疊 鍊錶等資料結構和排序 搜...