1. 程式人生 > >C++ STL list

C++ STL list

##`std::list` `` ###列表性質   1、雙向連結串列   2、只支援雙向順序訪問,不支援下標訪問(隨機訪問迭代器)(元素隨機訪問)   3、因為不支援隨機訪問迭代器,所以不能使用`std::sort`進行排序,需要呼叫成員函式`list::sort`   4、在`list`中任何位置進行`插入/刪除`操作速度都很快 ###容器操作 ####1、類型別名 | 型別 | 解釋 | | ------------ | ------ | | `iterator` | 此容器型別的迭代器型別 | | `const_iterator` | 可以讀取元素,但不能修改元素的迭代器型別 | | `size_type` | 無符號整數型別,足夠儲存此種容器型別最大可能容器的大小 | | `difference_type` | 帶符號整數型別,足夠儲存兩個迭代器之間的距離 | | `value_type` | 元素型別 | | `reference` | 元素的左值型別;與`value_type&`含義相同 | | `const_reference` | 元素的左值型別,(即`const value_type&`) | ####2、構造列表 ##### 1)、預設構造 > 構造一個沒有任何元素的空容器 ```   list mylist; ``` ##### 2)、填充構造 構造一個含有 n 個元素的容器, 每一個元素被賦值為 val(如果存在 val) > `list mylist( size_type n, const value_type &val );` ```   list mylist (5); // 含有 5 個元素,每個元素都被執行了預設初始化 (0) list mylist ( 5, 1314 ); // 含有 5 個元素,每個元素的值都是 1314 ``` ##### 3)、範圍構造 構造一個容器,具有和範圍 **[** first, last **)** 一樣多數量的元素,並且容器內元素順序與範圍內元素順序對應 >`list mylist( Iterator first, Iterator last );` ``` int myints[5] = { 75, 23, 65, 42, 13 }; list mylist ( myints, myints + 5 ); // 構造一個 list 容器,元素為 myints 內的元素的副本 ``` ##### 4)、拷貝構造 構造一個與`mylist`中的元素與元素順序相同的容器 >`list yourlist( const list &mylist );` ```   list mylist (5, 1314); list yourlist ( mylist ); // 將 mylist 的元素拷貝給 yourlist ``` ##### 5)、列表構造(列表元素初始化) 構造一個與`il`中的元素與元素順序相同的容器,`initializer_list`即`{ }` >`list mylist( initializer_list il );` ``` /* 三種寫法相同 */ list mylist ( {1, 3, 5} ); //mylist 內的元素為1, 3, 5 list mylist {1, 3, 5}; list mylist = {1, 3, 5}; // 下文 `賦值`中會說明‘=’的作用 ``` ####3、賦值 (`=`) ##### 1)拷貝 將 列表`x` 拷貝給 列表`mylist` >`mylist = const list &x;` ``` list mylist ( {1, 3, 5} ); // 不需要提前給 x 分配大小 因為 ‘=’ 會把 mylist 中的元素資訊全部拷貝過去 list x; x = mylist; ``` ##### 2)列表拷貝 通過列表拷貝 `initializer_list`即`{ }` >`mylist = initializer_list il;` ``` list mylist(3); // 注意要為 mylist 分配大小 mylist = {1, 2, 3}; ``` #### 4、迭代器 ##### 1)`begin` >返回指向容器第一個元素的迭代器 ##### 2)`end` >返回一個尾後迭代器,指向尾元素的下一個位置 用法舉例: ``` #include #include using namespace std; int main ( void ) { list lk; for ( int i = 1; i <= 5; i++ ) // 1, 2, 3, 4, 5 lk.push_back(i); for ( auto i = lk.begin(); i != lk.end(); i++ ) cout << *i << " "; cout << endl; return 0; } ``` ![](https://img2020.cnblogs.com/blog/2283267/202101/2283267-20210122123720327-1086126948.png) ##### 4)`cbegin ` >
返回的迭代器型別為`const_iterator` 所以不可以對迭代器解引用修改 ##### 5)`cend ` >返回的迭代器型別為`const_iterator` 所以不可以對迭代器解引用修改 ##### 5)`rbegin` >返回指向容器的尾元素之前位置的迭代器 ##### 6)`rend` >返回指向容器首元素之前位置的迭代器 ##### 7)`crbegin ` >返回`const_iterator` ##### 8)`crend ` >返回`const_iterator` #### 5、空間 ##### 1)`empty` >
返回當前容器是否為空 ##### 2)`size` >容器中元素的數目 ##### 3)`max_size` >容器可儲存的最大元素數目 #### 6、訪問元素 ##### 1)`front` > 返回對`list`容器的第一個元素的引用 ##### 2)`back` > 返回對`list`容器的最後一個元素的引用 #### 7、修改 ##### 1)`assign` `assign`也是一種賦值方式,和`初始化`與`賦值`不同的是:`assign`允許我們從一個不同但相容型別賦值,或者從容器的一個子序列賦值。 `assign`操作用引數所指定的元素(的拷貝)替換左邊容器中的所有元素。 例如,我們可以用`assign`實現將一個`vector`中的一段`char*`值賦予一個`list`中的`string`: ``` #include #include #include using namespace std; int main ( void ) { list myString; vector myChar; myChar.push_back ( "1 2 3 4 5 6" ); myChar.push_back ( "7 8 9 10" ); myChar.push_back ( "11 12 13 14" ); myString.assign ( myChar.begin(), myChar.end() ); //可以將 char* 轉換為 string for ( auto i = myString.begin(); i != myString.end(); i++ ) { cout << *i << ' '; } cout << endl; return 0; } ``` 這段程式碼中對`assign`的呼叫將`names`中的元素替換為迭代器指定的範圍中的元素的拷貝。 `assign`的引數決定了容器中將有多少個元素以及它們的值都是什麼。 輸出 ![](https://img2020.cnblogs.com/blog/2283267/202101/2283267-20210123075756890-1014079877.png) | 型別 | 解釋 | | ---- | ---- | | `val` | 待插入元素的值 | | `n` | 新的容器尺寸 | | `first, last` | 指定元素範圍的迭代器,將 [first,last)範圍內的所有元素拷貝到list容器中 | | `il` | 一個列表元素,相當於列表初始化 | ###### (1)範圍賦予 >
`void assign ( InputIterator first, InputIterator last );` ###### (2)填充賦予 接受一個整數值和一個元素值。它用指定數目且具有相同給定值的元素替換容器中原有的元素 > `void assign ( size_type n, const value_type &val );` ###### (3)列表元素賦予 接受一段元素列表,將`list`容器中的元素和大小按序替換為該元素列表內的值和個數 > `void assign ( initializer_list il );` ##### 2)`emplace ` ##### 3)`emplace_front ` > `void emplace_front ( Args&&... args );` ##### 4)`emplace_back ` > `void emplace_back ( Args&&... args );` 來救救蒟蒻吧,`emplace`沒學懂,歡迎留言補充交流 ##### 5)`push_front` 在`list`容器的頭部建立一個值為`val`的元素,相應地使`size`增大了`1` > `void push_front ( const value_type &val );` ##### 6)`pop_front` 刪除`list`容器的的首元素 > `void pop_front ( void );` ##### 7)`push_back` 在`list`容器的尾部建立一個值為`val`的元素,相應地使`size`增大了`1` > `void push_back ( const value_type &val );` ##### 8)`pop_back` 刪除`list`容器的的尾元素 > `void pop_back ( void );` ##### 9)`insert` | 型別 | 解釋 | | ---- | ---- | | `position` | 在容器中插入新元素的位置,新元素將插入在`position`的前面 | | `val` | 待插入元素的值 | | `n` | 要插入的元素個數,每個數的值都是`val` | | `first, last` | 指定元素範圍的迭代器,將 [first,last)範圍內的所有元素副本插入到`position`的前面 | | `il` | 將列表`{ }`內的值插入到`position`的前面 | ######(1)插入單個元素 在迭代器`position`指向的元素之前建立一個值為`val`的元素,返回指向新新增的元素的迭代器 >`iterator insert ( const_iterator position, const value_type& val );` ######(2)插入 n 個相同元素 在迭代器`position`指向的元素之前插入`n`個值為`val`的元素,返回指向新新增的一個元素的迭代器;若`n`為`0`,則返回`p` >`iterator insert ( const_iterator position, size_type n, const value_type& val );` ######(3)插入元素值列表 `{ a, b, c, ... }` `il`是一個花括號包圍的元素值列表。將這些給定值插入到迭代器`position`指向的元素之前。返回指向新新增的第一個元素的迭代器;若列表為空,則返回`p` >iterator insert (const_iterator position, initializer_list il); ##### 10)`erase` ###### a.刪除單個元素 刪除由一個迭代器指定的單個元素 返回指向刪除的元素之後位置的迭代器 > `iterator erase ( const_iterator position );` ###### b.刪除多個元素 接受一對迭代器,允許我們刪除一個範圍內的元素 迭代器`first`指向要刪除的第一個元素,`last`指向我們要刪除的最後一個元素之後的位置 > `iterator erase ( const_iterator first, const_iterator last );` ##### 11)`swap` 用於交換容器內容,`swap`交換兩個`list`容器內部的資料結構(元素本身並未交換),所以非常快,可以保證在常數時間內完成。 > `void swap ( list &x );` ##### 12)`resize` 將容器的大小變為`n` 1、如果`n`小於當前容器的大小,則將元素個數減少到前n個元素,並刪除超出範圍的元素。 2、如果`n`大於當前容器的大小,則通過在末尾插入任意數量的元素以達到n個元素。 如果指定了`val`,則將新元素初始化為`val`的副本,否則,將對它們進行值的預設初始化。 > `void resize ( size_type n, value_type val = value_type() );` ##### 13)`clear` 刪除list容器中所有元素 `void clear ( void )` #### 8、操作 ##### 1)`splice` 例如有`list`a,`list`b 則`splice`的作用是將`b`中的某些元素`移動`到`a`當中的某個位置去
###### a.移動所有元素 將`x`容器中的所有元素移動到指定容器的迭代器`position`所指向的位置。 插入的第一個元素置於迭代器`position`所指向的位置 原先位置的元素置於被插入的最後一個元素的後面。(兩容器的大小均已改變) 注意和`insert`的區別,`splice`相當是把元素插入在了`position`的前面 > `void splice ( iterator position, list &x );` ###### c.單一元素移動 將`x`容器中,迭代器`i`所指向的元素移動到`list`容器中,迭代器`position`所指向的位置之前. > `void splice (iterator position, list& x, iterator i);` ###### c.範圍元素移動 將範圍`[first,last)`內的元素從`x`移動到`list`容器中`position`所指向的位置之前。 > `void splice (iterator position, list& x, iterator first, iterator last);` 關於`splice`的具體操作請見程式碼: ``` // splicing lists #include #include int main () { std::list mylist1, mylist2; std::list::iterator it; // set some initial values: for (int i=1; i<=4; ++i) mylist1.push_back(i); // mylist1: 1 2 3 4 for (int i=1; i<=3; ++i) mylist2.push_back(i*10); // mylist2: 10 20 30 it = mylist1.begin(); ++it; // points to 2 mylist1.splice (it, mylist2); // mylist1: 1 10 20 30 2 3 4 // mylist2 (empty) // "it" still points to 2 (the 5th element) mylist2.splice (mylist2.begin(),mylist1, it); // mylist1: 1 10 20 30 3 4 // mylist2: 2 // "it" is now invalid. it = mylist1.begin(); std::advance(it,3); // "it" points now to 30 mylist1.splice ( mylist1.begin(), mylist1, it, mylist1.end()); // mylist1: 30 3 4 1 10 20 std::cout << "mylist1 contains:"; for (it=mylist1.begin(); it!=mylist1.end(); ++it) std::cout << ' ' << *it; std::cout << '\n'; std::cout << "mylist2 contains:"; for (it=mylist2.begin(); it!=mylist2.end(); ++it) std::cout << ' ' << *it; std::cout << '\n'; return 0; } ``` OutPut: ``` mylist1 contains: 30 3 4 1 10 20 mylist2 contains: 2 ``` > 以上程式碼源於http://www.cplusplus.com/reference/list/list/splice/ ##### 2)`remove` 刪除具有`val`的元素 > `void remove ( const value_type &val );` ##### 3)`remove_if` 刪除滿足條件的元素 > `void remove_if ( Predicate pred );` 程式碼說明一切 ``` // list::remove_if #include #include // a predicate implemented as a function: bool single_digit (const int& value) { return (value<10); } // a predicate implemented as a class: struct is_odd { bool operator() (const int& value) { return (value%2)==1; } }; int main () { int myints[]= {15,36,7,17,20,39,4,1}; std::list mylist (myints,myints+8); // 15 36 7 17 20 39 4 1 mylist.remove_if (single_digit); // 15 36 17 20 39 mylist.remove_if (is_odd()); // 36 20 std::cout << "mylist contains:"; for (std::list::iterator it=mylist.begin(); it!=mylist.end(); ++it) std::cout << ' ' << *it; std::cout << '\n'; return 0; } ``` OutPut: ``` mylist contains: 36 20 ``` > 以上程式碼源於http://www.cplusplus.com/reference/list/list/remove_if/ ##### 4)`unique` 刪除相鄰重重元素,是真的銷燬掉. > `void unique ( void );` ##### 5)`merge` 拼接`list`容器 ###### a.拼接 > `void merge ( list &x );` ###### b.帶有比較模板的拼接 > `void merge ( list& x, Compare comp );` ##### 6)`sort` 對`list`容器進行排序 ###### a.升序排序 // 0, 1, 2, 3, 4 > `void sort ( void );` ###### b.`cmp`模板排序 > `void sort ( Compare comp );` ##### 7)`reverse` 反轉`list`容器中元素的順序 > `void reverse (