C++ 標準樣板庫(Standard Template Library, STL)
9
0
0
全文
(2) 建國中學 2009 資訊科校隊選手培訓講義. A-2. list<T, alloc> 而 list 則是可以視為一個 doubly linked list,意即 list 這種循序式容器同時支 援 Forward 和 Backward 兩種方向的遍歷,並可以動態的改變容器大小。對於插 入或刪除元素 list 無論是在尾端或非尾端的元素都可以在(均攤)O(1)的時間內完 成操作,但由於 list 使用的是 bidirectional iterator,所以無法一次移動很多步(就 如同你平常寫的 linked list),當然由於不是 Random Access,你亦無法像 vector 一樣直接使用 [ ] 運算子來取值。list 容器被定義於標頭檔 list.h 中。 [ 一個 double 型態 list 的宣告: list<double> DoubleList; ] A-3. deque<T, alloc> 最後,deque 則是所謂的雙端佇列,它非常像 vector,與 vector 同樣為 Random Access 的循序式容器,因此可以用 [ ] 運算子取值但它可以在 O(1)的時間內在 尾端或前端插入或刪除一個元素,而對於其他中間的元素則仍要花費 O(n)的時 間。不過,deque 將會無法使用一些 vector 可以使用的成員函式,例如 reverse() 等。deque 容器被定義於標頭檔 deque.h。 [ 一個 char 型態 deque 的宣告: deque<char> CharDeque; ] A-4. 大小比較 兩個循序式容器我們也可以對他們作比較大小的動作,STL 定義我們說一個 容器 A 小於另一個容器 B 若且為若 A 的元素的字典順序(Lexicographical Order) 小於 B 的元素的字典順序。 A-5. 成員函式 至於以上三種循序式容器的成員函式請參照 sgi 的 STL 使用導引: vector: http://www.sgi.com/tech/stl/Vector.html list: http://www.sgi.com/tech/stl/List.html deque: http://www.sgi.com/tech/stl/Deque.html B. 關連式容器(Associative Containers) 常見的 STL 關連式容器有 set、map、multiset 和 multimap 這四種,以下我 們針對 set 和 map 作討論,multi 的版本其實和基本版本大同小異,有興趣的同 學可以自己查詢相關資料。 set 和 map 都是屬於 Sorted Associative Container,也就是它們會自動將 容器內的元素排序,也就是對於任意的時間點,set 和 map 永遠是有序的 (Sorted)。 B-1. set<Key, Compare, Alloc> set 是一種儲存 Key 型態的物件的有序關連式容器,在 set 中的元素是遞增 的,此外 set 是一種 Unique Associative Container,意思就是在 set 之中沒有 兩個元素會一樣。set 還有一個很重要的特性,那就是指向 set 中一個元素的 2.
(3) 建國中學 2009 資訊科校隊選手培訓講義. iterator 在其他元素被刪除時並不會失效。set 可以在 O(lgn)的時間內插入或刪 除一個元素。set 容器被定義於標頭檔 set.h 中。 [ 一個 int 型態 set 的宣告: set<int> IntSet; ] B-2. map<Key, Data, Compare, Alloc> map 也是一種有序的關聯式容器,但他儲存的是一對值,第一個是 Key,第 二個是 Data,兩種值不一定屬於要同一個型態。map 是屬於 Pair Associative Container,這代表它儲存的元素是一對一對的 pair<const key, Data>,map 也是 屬於 Unique Associative Container,意思就是在 map 之中沒有兩個 Key 會一 樣。 和 set 一樣,指向 map 中一個元素的 iterator 在其他元素被刪除時並不會失 效。map 可以在 O(lgn)的時間內插入或刪除一個元素(pair),也可以在 O(lgn) 的時間內修改任一個 Key 的 Data 值。map 容器被定義於標頭檔 map.h 中。 [ 一個 pair<int, double>型態 set 的宣告: map<int,double> MyMap; ] B-3. 自定 Compare 剛剛以上提到的 set 或者是 map 都屬於 Sorted Associative Container,如 果沒特別指定的話,理論上會照著容器中元素 Key 值的大小以遞增的方式排序, 但是,有的時候我們會希望能依照我們自己的想法排序,此時我們就可以自己寫 一個 Compare 的物件(符合希望排在前面的方式要 return true),大致上如下: struct MyCmp{ bool operator()( const int a, const int b ) const { if ( (a>=0)^(b>=0) ) return a<b; else { if ( a>=0 ) return a<b; else return a>b; } } }. 依照上面的自訂 Compare 物件,我們可以宣告一個使用上述 Compare 方式 的 set,像這樣:[. set<int, MyCmp> MySet; ],此時如果在 set 中的 Key 值. 集合為{-5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5},那麼剛剛宣告的自訂 Compare 方式的 set 就會將它們排序成 -1, -2, -3, -4, -5, 0, 1, 2, 3, 4, 5 。 然而要小心,在比較時不可以有矛盾的情況發生,否則會造成不能預期的結 果,例如,你把自訂排序依據為 a<=b,但是,此時如果有兩個元素 s1=s2,那 麼 s1<=s2 成立(return true),s2<=s1 亦成立,那麼究竟應該把哪一個元素放在 前面呢?懂吧,對於這一點一定要小心。 自訂排序依據往往是重要的,畢竟你不會真的每一次遇到的情況都是要從小 排到大吧? 3.
(4) 建國中學 2009 資訊科校隊選手培訓講義. B-4. 成員函式 以上兩種我們介紹的循序式容器之成員函式請參照 sgi 的 STL 使用導引: set: http://www.sgi.com/tech/stl/set.html map: http://www.sgi.com/tech/stl/Map.html C. 轉接器 (Adapters) STL 容器中有一種特殊的類別叫做轉接器(Adapters),就是使用上述的容器加 工而成的,呈現出一些常常比較容易用到的表現形態,STL 提供的 Container Adapter 主要有 stack、queue 和 priority_queue 三種,有興趣的人可以自行查閱 相關資料。. II. STL 迭代器 回想看看我們在對陣列(Arrays)作操作的時候,我們可以藉由指標(Pointers) 來定址,然而,對於 STL 的容器(Containers)來說由於不是普通的陣列,我們當 然不能直接地對這些容器使用指標,那要怎麼辦呢?因此,就產生了一種名為迭 代器(Iterators)的東西。幾乎所有的迭代器都被包含在標頭檔 Iterator.h 中。 對於迭代器,其實你可以很簡單的把它視為是對容器的指標來使用,雖然這 樣的觀念不盡正確,因為迭代器的功能其實不僅於定址,但是這種當作指標的想 法事實上對於第一次知道這種東西的人來說是有幫助的。 STL 的迭代器大致上可以分為五種:Output Iterator、Input Iterator、 Forward Iterator、Bidirectional Iterator 和 Random Access Iterator,其中它 們之間的功能關係為:Input Iterator ⊂ Forward Iterator ⊂ Bidirectional Iterator ⊂ Random Access Iterator。弄懂這幾種 Iterator 在哪裡 使用、有什麼特性絕對是重要的,尤其是之後會講到的 STL 所提供的演算法樣 板,搞錯對象的 Iterator 可是會讓你使用起來不斷地吃 Compile Error 的。 對於 Input Iterator 或 Output Iterator 理論上我們在競賽中會比較少用到, 理由是因為 C++的 standard I/O 的速度比 C 的 I/O 慢了不少(有興趣的同學可以 查詢 STL 相關書籍),但對於剩下的三種 Iterator,我們就有必要好好的了解一下 了。 首先對於 Forward Iterator,顧名思義,就是無法回頭的 Iterator(?),意思 就是只能++不能--,挺莫名的吧?接著就是 Bidirectional Iterator,一樣是顧名思 義,Bidirectional 就是雙向的意思,對於一個 Bidirectional Iterator,我們可以對 他++和--,然而,以上兩種 Iterator 都只能作平移一格的動作(++或--),而不像 Pointer 能夠一次+=k 或-=k 的大幅度平移,Random Access Iterator 就彌補了這 個缺失,它支援一次平移多格的功能。 4.
(5) 建國中學 2009 資訊科校隊選手培訓講義. 而對於取值的部分就和我們熟悉的指標(Pointer)一樣了!可以使用 * 或 -> 運算子作取值的動作。 然而,在使用迭代器時卻有一點一定要特別注意,那就是──當你修改了你 的容器內容後,所有在該容器上運作的迭代器都會失效!(除了 list, set 等特殊的 Container 以外)這一點一定要非常小心,畢竟這跟傳統的指標(Pointer)不同,指 標記的是記憶體位置,不管你整體是否有改變,在沒有修改到它的值之前指標會 一直指向同一個位置,而之所以 Iterator 會失效,原因大致上是因為容器的動態 (Dynamic)性,而詳細理由就不在這裡多提了。. III. STL 演算法 STL 除了提供了許多方便的容器以及在其上頭運用的 Iterator 之外,也提供 了許多有用的演算法模板,在有時間限制的短期比賽中,適當地使用 STL 所提 供的演算法模板不失為一種優勢,但若決定要使用它就必頇好好了解它,否則半 調子的胡亂使用可能會招致滅亡的結果。 STL 所提供的演算法模板五花八門,以下我們僅介紹其中幾種。要使用 STL 提供的演算法模板必頇先引入(Include)標頭檔 algorithm。 A. Sort 這個 STL 提供的演算法樣板可能很多人已經知道了,甚至賴以維生,STL 提供了高速的排序演算法 Introsort Algorithm,最差時間複雜度為 O(nlgn),較 一般的 Quicksort 快。sort()有 overload 兩種型態,一種是使用預設比較的型態, 另一種是加上自訂 Compare 物件的型態,兩種型態如下: >普通的型態:. template <class RandomAccessIterator> void sort(RandomAccessIterator first, RandomAccessIterator last); >自訂 Compare 物件時使用的型態: template <class RandomAccessIterator, class StrictWeakOrdering> void sort(RandomAccessIterator first, RandomAccessIterator last, StrictWeakOrdering comp);. Sort( )主要是使用 Random Access Iterator 來運作,因此唯有能夠使用 Random Access Iterator 的容器(當然,一般的陣列也是 Random Access 的) 才能 使用 Sort( )。此外,值得注意的一點是,Sort( )的排序區間為 [first, last) (其他 的 STL 相關物件的參數往往也是如此),並非一般人所想樣的兩端皆是閉的區間。 以下是一個使用的例子: int A[5]={3, 2, 5, 1, 4}; sort( A, A+5 ); //Result: 1, 2, 3, 4, 5 5.
(6) 建國中學 2009 資訊科校隊選手培訓講義. B. stable_sort 剛剛所提到的 sort()是屬於一種不穩定(non-stable 的排序),如果要穩定排 序的話可以使用 stable_sort(),使用的方法和 sort()一模一樣,這邊就不多提了。 C. nth_element 對於要在 O(n)的時間內求出第 k 大的元素,相信大家在學習以前教過的 Divide-and-Conquer 時應該都有練習過相關的習題吧?而 nth_element()可以產 生出同樣的結果,時間複雜度一樣是 O(n),較直接排序的 O(nlgn)更好。 >普通的型態:. template <class RandomAccessIterator> void nth_element(RandomAccessIterator first, RandomAccessIterator nth, RandomAccessIterator last); >自訂 Compare 物件時使用的型態: template <class RandomAccessIterator, class StrictWeakOrdering> void nth_element(RandomAccessIterator first, RandomAccessIterator nth, RandomAccessIterator last, StrictWeakOrdering comp);. nth_element( )主要是使用 Random Access Iterator 來運作,因此唯有能夠 使用 Random Access Iterator 的容器(當然,一般的陣列也是 Random Access 的) 才能使用 nth_element(),nth_element()保證結果的序列內[nth, last)區間中的每 個元素都不會小於[first, nth)區間中的每個元素。 int A[5]={3, 2, 5, 1, 4}; nth_element( A, A+3, A+5 ); //Result of A[3] is: 4 D. binary_search 對於一個有序(Sorted)的序列,binary_search()可以在 O(lgn)的時間內找出 一個元素 value 是否存在於序列當中。若存在回傳 true,不存在回傳 false。 >普通的型態:. template <class ForwardIterator, class LessThanComparable> bool binary_search(ForwardIterator first, ForwardIterator last, const LessThanComparable& value); >自訂 Compare 物件時使用的型態: template <class ForwardIterator, class T, class StrictWeakOrdering> bool binary_search(ForwardIterator first, ForwardIterator last, const T& value, StrictWeakOrdering comp);. int A[5] = { 1, 1, 2, 3, 5 }; for ( int i=1; i<5; i++ ) { printf(“Searching for %d: %s\n”, i, (binary_search(A, A+5, i) ? "present" : "not present") ); } 6.
(7) 建國中學 2009 資訊科校隊選手培訓講義 /*The output is: Searching for 1: present Searching for 2: present Searching for 3: present Searching for 4: not present Searching for 5: present Searching for 6: not present Searching for 7: not present Searching for 8: present Searching for 9: not present Searching for 10: not present */. E. upper_bound / lower_bound upper_bound()和 lower_bound()是二分搜尋的兩種特殊版本,它會找到在給 定的有序(Sorted)序列中最後一個 <= / < 給定 value 的元素。upper_bound()和 lower_bound()使用的 Iterator 種類是 Forward Iterator,由於 Forward Iterator 包含於 Random Access Iterator,所以也可以使用 Random Access Iterator(或其 他包含 Forward Iterator 的 Iterator 類型)。 >普通的型態:. template <class ForwardIterator, class LessThanComparable> ForwardIterator upper_bound(ForwardIterator first, ForwardIterator last, const LessThanComparable& value); >自訂 Compare 物件時使用的型態: template <class ForwardIterator, class T, class StrictWeakOrdering> ForwardIterator upper_bound(ForwardIterator first, ForwardIterator last, const T& value, StrictWeakOrdering comp);. 以下是一個例子: int A[5] = { 1, 1, 2, 3, 5 }; printf(“%d ”,*upper_bound( A, A+5, 2 ) ); printf(“%d\n”,*lower_bound( A, A+5, 2 ) ); //The output is: 2 3. F. next_permutation next_permutation()可以把一個序列轉變為它在全排列中的下一個排列。 相對應的,也有 prev_permutation(),其功能則是將序列轉變為它在全排列中的 前一個排列,若無後/前一個排列,則會 return false。next_permutation()和 prev_permutation()皆是使用 Bidirectional Iterator,所有包含於 Bidirectional Iterator 的 Iterator 類型皆可以使用,但不可使用像 Forward Iterator 這類層級 比 Bidirectional Iterator 小的 Iterator。 7.
(8) 建國中學 2009 資訊科校隊選手培訓講義. >普通的型態:. template <class BidirectionalIterator> bool next_permutation(BidirectionalIterator first, BidirectionalIterator last); >自訂 Compare 物件時使用的型態:. template <class BidirectionalIterator, class StrictWeakOrdering> bool next_permutation(BidirectionalIterator first, BidirectionalIterator last, StrictWeakOrdering comp);. 以下是一個例子: int A[5] = { 1, 1, 2, 3, 5 }; next_permutation( A, A+5 ); //Result of A[ ]: 1, 1, 2, 5, 3. G. min / max min()和 max()是很簡單的樣板,主旨就是回傳兩個參數中較小/大的那一個, 它們也可以有第三個參數,也就是自訂的 Compare 物件。 >普通的型態:. template <class T> const T& min(const T& a, const T& b); >自訂 Compare 物件時使用的型態:. template <class T, class BinaryPredicate> const T& min(const T& a, const T& b, BinaryPredicate comp);. 以下是一個例子: int a = 5, b = 10; printf(“%d %d\n”,min(5,10), max(5,10) ); //The output is: 5 10. H. min_element / max_element min_element()和 max_element()是 min()和 max()的進化版,它們可以求出 一段區間內的最小/大值,傳入的要是 Forward Iterator 或者是包含 Forward Iterator 的 Iterator 種類。 >普通的型態:. template <class ForwardIterator> ForwardIterator min_element(ForwardIterator first, ForwardIterator last); >自訂 Compare 物件時使用的型態: template <class ForwardIterator, class BinaryPredicate> ForwardIterator min_element(ForwardIterator first, ForwardIterator last, BinaryPredicate comp);. 以下是一個例子: 8.
(9) 建國中學 2009 資訊科校隊選手培訓講義. int A[5]={5, 2, 4, 3, 8} printf(“%d %d\n”,min_element(A,A+5), max_element(A+1,A+4) ); //The output is: 2 4. I. swap swap()可以將兩個給定元素的值作交換,以 call by reference 的方式呈現。 template <class Assignable> void swap(Assignable& a, Assignable& b);. J. make_heap / push_heap / pop_heap STL 也提供了資料結構堆積(Heap)的相關樣板,主要有 make_heap()、 push_heap()和 pop_heap()三種,之前的講義都有提到過,這邊就不多談了。. The last comment: 其實現在 sgi 所提供的 STL 和以前相較起來已經又擴充了許多新的元素,但 受限於比賽時官方所提供的編譯器 Library 不一定會支援最新版的 STL 使用,故 本講義中並未提到新擴充的內容(意即理論上比賽時上述的 STL 素材都是可以使 用的),如果你真的很有興趣,也可以到 sgi 的官方網站下在最新版的 STL。. CK6207 楊鈞百. - References 1. Standard Template Library Programmer's Guide http://www.sgi.com/tech/stl/ 2. Wikipedia en http://en.wikipedia.org/. 9.
(10)
相關文件
不過 Proposition 4.2.3 告訴 我們對於 linear transformation, 可以直接由它的 range 的 dimension 來判斷是否為 onto?. 至於如何知道一個 linear transformation
安全就是針對所有可能對資安有影響的威脅(threat)進行防衛,而可能被
味,Alex更是國家認證的品鑑師。
◎以下引文摘自古蘭經譯文 引文一:你們的主宰(指阿拉)是獨一的應受拜者,應受拜者唯有祂。祂是至仁的,至慈的。
接下來我們來看看要如何才能視覺化出這樣的結果,首先,我們知道整個矩 陣在程式執行過程中會有三種不同的數字,也就是
【自傳範本】 家庭背景:
這裡(機率)變異數與(數學)變異數是一樣的。但往後請同學在做題目時自行
得勝者課程以遊戲的方式,慢慢深入主題,義工老師都很有耐心的教