C++ list,STL list
list 是順序容器的一種。list 是一個(gè)雙向鏈表。使用 list 需要包含頭文件 list。雙向鏈表的每個(gè)元素中都有一個(gè)指針指向后一個(gè)元素,也有一個(gè)指針指向前一個(gè)元素。
在 list 容器中,在已經(jīng)定位到要增刪元素的位置的情況下,增刪元素能在常數(shù)時(shí)間內(nèi)完成。如圖2所示,在 ai 和 ai+1 之間插入一個(gè)元素,只需要修改 ai 和 ai+1 中的指針即可。
圖1 :雙向鏈表
圖2:在雙向鏈表中插入元素
list 容器不支持根據(jù)下標(biāo)隨機(jī)存取元素。
list 的構(gòu)造函數(shù)和許多成員函數(shù)的用法都與 vector 類(lèi)似。除了順序容器都有的成員函數(shù)外,list 容器還獨(dú)有如下表所示的成員函數(shù)(此表不包含全部成員函數(shù),且有些函數(shù)的參數(shù)較為復(fù)雜,表中只列出函數(shù)名)。
list 的成員函數(shù)
| void push_front(const T & val) | 將 val 插入鏈表最前面 |
| void pop_front() | 刪除鏈表最前面的元素 |
| void sort() | 將鏈表從小到大排序 |
| void remove (const T & val) | 刪除和 val 相等的元素 |
| remove_if | 刪除符合某種條件的元素 |
| void unique() | 刪除所有和前一個(gè)元素相等的元素 |
| void merge(list & x) | 將鏈表 x 合并進(jìn)來(lái)并清空 x。要求鏈表自身和 x 都是有序的 |
| void splice(iterator i, list & x, iterator first, iterator last) | 在位置 i 前面插入鏈表 x 中的區(qū)間 [first, last),并在鏈表 x 中刪除該區(qū)間。鏈表自身和鏈表 x 可以是同一個(gè)鏈表,只要 i 不在 [first, last) 中即可 |
表中列出的成員函數(shù)有些是重載的,如 unique、merge、splice 成員函數(shù)都不止一個(gè)。
STL 中的算法 sort 可以用來(lái)對(duì) vector 和 deque 排序,它需要隨機(jī)訪問(wèn)迭代器的支持。因?yàn)?list 不支持隨機(jī)訪問(wèn)迭代器,所以不能用算法 sort 對(duì) list 容器排序。因此,list 容器引入了 sort 成員函數(shù)以完成排序。
list 的示例程序如下:
#include <list> //使用 list 需要包含此頭文件 #include <iostream> #include <algorithm> //使用STL中的算法需要包含此頭文件 using namespace std; class A { private: int n; public:A(int n_) { n = n_; }friend bool operator < (const A & a1, const A & a2);friend bool operator == (const A & a1, const A & a2);friend ostream & operator << (ostream & o, const A & a); }; bool operator < (const A & a1, const A & a2) {return a1.n < a2.n; } bool operator == (const A & a1, const A & a2) {return a1.n == a2.n; } ostream & operator << (ostream & o, const A & a) {o << a.n;return o; } template <class T> void Print(T first, T last) {for (; first != last; ++first)cout << *first << " ";cout << endl; } int main() {A a[5] = { 1, 3, 2, 4, 2 };A b[7] = { 10, 30, 20, 30, 30, 40, 40 };list<A> lst1(a, a + 5), lst2(b, b + 7);lst1.sort();cout << "1)"; Print(lst1.begin(), lst1.end()); //輸出:1)1 2 2 3 4lst1.remove(2); //刪除所有和A(2)相等的元素cout << "2)"; Print(lst1.begin(), lst1.end()); //輸出:2)1 3 4lst2.pop_front(); //刪除第一個(gè)元素cout << "3)"; Print(lst2.begin(), lst2.end()); //輸出:3)30 20 30 30 40 40lst2.unique(); //刪除所有和前一個(gè)元素相等的元素cout << "4)"; Print(lst2.begin(), lst2.end()); //輸出:4)30 20 30 40lst2.sort();lst1.merge(lst2); //合并 lst2 到 lst1 并清空 lst2cout << "5)"; Print(lst1.begin(), lst1.end()); //輸出:5)1 3 4 20 30 30 40cout << "6)"; Print(lst2.begin(), lst2.end()); //lst2是空的,輸出:6)lst1.reverse(); //將 lst1 前后顛倒cout << "7)"; Print(lst1.begin(), lst1.end()); //輸出 7)40 30 30 20 4 3 1lst2.insert(lst2.begin(), a + 1, a + 4); //在 lst2 中插入 3,2,4 三個(gè)元素list <A>::iterator p1, p2, p3;p1 = find(lst1.begin(), lst1.end(), 30);p2 = find(lst2.begin(), lst2.end(), 2);p3 = find(lst2.begin(), lst2.end(), 4);lst1.splice(p1, lst2, p2, p3); //將[p2, p3)插入p1之前,并從 lst2 中刪除[p2,p3)cout << "8)"; Print(lst1.begin(), lst1.end()); //輸出:8)40 2 30 30 20 4 3 1cout << "9)"; Print(lst2.begin(), lst2.end()); //輸出:9)3 4return 0; }用 list 解決約瑟夫問(wèn)題。
約瑟夫問(wèn)題是:有 n 只猴子,按順時(shí)針?lè)较驀梢蝗x大王(編號(hào)為 1~n),從第 1 號(hào)開(kāi)始報(bào)數(shù),一直數(shù)到 m,數(shù)到 m 的猴子退到圈外,剩下的猴子再接著從 1 開(kāi)始報(bào)數(shù)。就這樣,直到圈內(nèi)只剩下一只猴子時(shí),這個(gè)猴子就是猴王。編程求輸入 n、m 后,輸出最后猴王的編號(hào)。
輸入數(shù)據(jù):每行是用空格分開(kāi)的兩個(gè)整數(shù),第一個(gè)是 n,第二個(gè)是 m(0<m, n<=1 000 000)。最后一行是:
0 0
輸出要求:對(duì)于每行輸入數(shù)據(jù)(最后一行除外),輸出數(shù)據(jù)也是一行,即最后猴王的編號(hào)。
輸入樣例:
6 2 12 4 8 3 0 0輸出樣例:
5 1 7示例程序如下:
#include <list> #include <iostream> using namespace std; int main() {list<int> monkeys;int n, m;while (true) {cin >> n >> m;if (n == 0 && m == 0)break;monkeys.clear(); //清空l(shuí)ist容器for (int i = 1; i <= n; ++i) //將猴子的編號(hào)放入listmonkeys.push_back(i);list<int>::iterator it = monkeys.begin();while (monkeys.size() > 1) { //只要還有不止一只猴子,就要找一只猴子讓其出列for (int i = 1; i < m; ++i) { //報(bào)數(shù)++it;if (it == monkeys.end())it = monkeys.begin();}it = monkeys.erase(it); //刪除元素后,迭代器失效,//要重新讓迭代器指向被刪元素的后面if (it == monkeys.end())it = monkeys.begin();}cout << monkeys.front() << endl; //front返回第一個(gè)元素的引用}return 0; }erase 成員函數(shù)返回被刪除元素后面那個(gè)元素的迭代器。如果被刪除的是最后一個(gè)元素,則返回 end()。
這個(gè)程序也可以用 vector 實(shí)現(xiàn),但是執(zhí)行速度要慢很多。因?yàn)?vector 的 erase 操作牽涉元素的移動(dòng),不能在常數(shù)時(shí)間內(nèi)完成,所花費(fèi)的時(shí)間和容器中的元素個(gè)數(shù)有關(guān);而 list 的 erase 操作只是修改幾個(gè)指針而已,可以在常數(shù)時(shí)間內(nèi)完成。當(dāng) n 很大(數(shù)十萬(wàn))時(shí),兩種寫(xiě)法在速度上會(huì)有明顯區(qū)別。
總結(jié)
以上是生活随笔為你收集整理的C++ list,STL list的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: C语言指针是什么
- 下一篇: C++ open 打开文件