Primer STL筆記第二部分容器與演算法

2021-07-16 15:09:26 字數 4203 閱讀 1655

9.1順序容器的定義

要定義乙個容器型別的物件筆下那個先包含相關的容器標頭檔案。

所有容器型別都定義了預設建構函式,用於建立指定型別的空容器物件。預設建構函式不帶引數。為了使程式更清晰、簡短,容器型別最常用的建構函式是預設建構函式。在大多數的程式中,使用預設建構函式能達到最佳執行時效能,並且使容器更容易使用。

下面一些例子 將乙個容器複製給另乙個容器時,型別必須匹配:容器型別和元素型別都必須相同。

vectorivec;

vectorivec2(ivec); // ok: ivec is vector

listilist(ivec); // error: ivec is not list

vectordvec(ivec); // error: ivec holds int not double

初始化為一段元素的副本

儘管不能直接將一種容器內的元素複製給另一種容器,但系統允許通過傳遞一對迭代器(第 3.4 節)間接實現該實現該功能。使用迭代器時,不要求容器型別相同。容器內的元素型別也可以不相同,只要它們相互相容,能夠將要複製的元素轉換為所構建的新容器的元素型別,即可實現複製

// initialize slist with copy of each element of svec

listslist(svec.begin(), svec.end());

// find midpoint in the vector

vector::iterator mid = svec.begin() + svec.size()/2;

// initialize front with first half of svec: the elements up to but

not including *mid

dequefront(svec.begin(), mid);

// initialize back with second half of svec: the elements *mid

through end of svec

dequeback(mid, svec.end());

回顧一下指標,我們知道指標就是迭代器,因此允許通過使用內建陣列中的

一對指標初始化容器也就不奇怪了:

char *words = ;

// calculate how many elements in words

size_t words_size = sizeof(words)/sizeof(char *);

// use entire array to initialize words2

listwords2(words, words + words_size);//還是begin 到end

建立容器時,除了指定元素個數,還可選擇是否提供元素初始化式。我們也可以只指定容器大小

不提供元素初始化式時,標準庫將為該容器實現值初始化(3.3.1&nbps;節)。採用這種型別的初始化,元素型別必須是內建或復合型別,或者是提供了預設建構函式的類型別。如果元素型別沒有預設建構函式,則必須顯式指定其元素初始化式。接受容器大小做形參的建構函式只適用於順序容器,而關聯容器不支援這種初始化。

因為容器受容器元素型別的約束,所以可定義元素是容器型別的容器

vector< vector> lines; // vector of vectors

迭代器與迭代器範圍

每種容器型別都提供若干共同工作的迭代器型別。與容器型別一樣,所有迭代器具有相同的介面

常用迭代器運算:

*iter 返回迭代器 iter 所指向的元素的引用

iter->mem 對 iter 進行解引用,獲取指定元素中名為 mem 的成員。等效於(*iter).mem

++iter

iter++ 給 iter 加 1,使其指向容器裡的下乙個元素

--iter

iter-- 給 iter 減 1,使其指向容器裡的前乙個元素

iter1 == 比較兩個迭代器是否相等(或不等)。當兩個迭代器指向同乙個

iter2容器中的同乙個元素,或者當它們都指向同乙個容器的超出末端的下一位置時,兩個迭代器相等

iter1 !=

iter2

vector 和 deque 容器的迭代器提供額外的運算

iter + n iter-n 、iter1 +=iter2 、iter1 -=iter2 、iter1 -iter2(only)、關係操作符:>, >=,

迭代器 first 和 last 如果滿足以下條件,則可形成乙個迭代器範圍:

• 它們指向同乙個容器中的元素或超出末端的下一位置。

• 如果這兩個迭代器不相等,則對 first 反覆做自增運算必須能夠到達 last。換句話說,在容器中,last 絕對不能位於 first 之前。

使用左閉合區間的程式設計意義因為左閉合區間有兩個方便使用的性質,所以標準庫使用此煩區間。假設first 和 last 標記了乙個有效的迭代器範圍,於是:1. 當 first 與 last 相等時,迭代器範圍為空;2. 當 first 與不相等時,迭代器範圍內至少有乙個元素,而且 first 指向該區間中的第一元素。此外,通過若干次自增運算可以使 first 的值不斷增大,直到 first == last 為止。

例子:slist.insert(slist.end(), sarray, sarray+4);

list::iterator slist_iter = slist.begin();

// insert last two elements of sarray before slist_iter

slist.insert(slist_iter, sarray+2, sarray+4);

容器關係操作符

所有的容器型別都支援用關係操作符(第 5.2 節)來實現兩個容器的比較。顯比較的容器必須具有相同的容器型別,而且其元素型別也必須相同

capacity 和reserve

弄清楚容器的 capacity(容量)與 size(長度)的區別非常重要。size 指容器當前擁有的元素個數;而 capacity 則指容器在必須分配新儲存空間之前可以儲存的元素總數。空 vector 容器的 size 是 0,而標準庫顯然將其 capacity 也設定為 0。當程式設計師在 vector 中插入元素時,容器的 size 就是所新增的元素個數,而其 capacity 則必須至少等於 size,但通常比 size 值更大。

ivec.reserve(50); // sets capacity to at least 50; might be more

插入操作如何影響容器的選擇

list容器是不連續的記憶體區域,向前向後歷遍元素都可以,任何位置insert或erase都高效,除去容器尾部,其他位置上的插入刪除操作都要求移動被插入元素的右邊的所有元素。(就是右邊的移動)

• 與 vector 容器一樣,在 deque 容器的中間 insert 或 erase 元素效率比較低。

• 不同於 vector 容器,deque 容器提供高效地在其首部實現 insert 和erase 的操作,就像在容器尾部的一樣。

• 與 vector 容器一樣而不同於 list 容器的是, deque 容器支援對所有元素的隨機訪問。

• 在 deque 容器首部或尾部插入元素不會使任何迭代器失效,而首部或尾部刪除元素則只會使指向被刪除元素的迭代器失效。在 deque 容器的任何其他位置的插入和刪除操作將使指向該容器元素的所有迭代器都失效

1. 如果程式要求隨機訪問元素,則應使用 vector 或 deque 容器。

2. 如果程式必須在容器的中間位置插入或刪除元素,則應採用 list 容器。

3. 如果程式不是在容器的中間位置,而是在容器首部或尾部插入或刪除元

素,則應採用 deque 容器。

4. 如果只需在讀取輸入時在容器的中間位置插入元素,然後需要隨機訪問元

素,則可考慮在輸入時將元素讀入到乙個 list 容器,接著對此容器重新

排序,使其適合順序訪問,然後將排序後的 list 容器複製到乙個 vector

容器。

linux筆記第二部分

其實我只是想記錄下自己的學習軌跡,順便讓自己的部落格裡面稍微有點東西。之前筆記都是儲存在evernote上,因為是普通使用者,貌似不能共享。就拷過來了。總之這是第二部分 linux磁碟及檔案系統管理以及如何獲取幫助 linux 08磁碟基本概念 linux 09使用fdisk進行磁碟管理 1.fdi...

Web API 第二部分

web api 第二部分 元素偏移量 offset element.offsettop element.offsetleft element.offsetwidth 可以得到元素的大小 寬度和高度 是包含padding border width element.offsetheight elemen...

redux 第二部分

redux 的使用方法,為什麼使用 action.js 檔案,進行優化 將其分開,然後我們通過工廠函式的每次返回不同的物件,由於引數是固定的,每次返回的都是事件型別和事件資料,所以我們可以使用乙個函式,通過其返回值來返回乙個物件,讓後傳遞給 action 我們的 reducer 函式有兩個引數,引數...