C++ list,STL list
list 是順序容器的一種。list 是一個雙向鏈表。使用 list 需要包含頭文件 list。雙向鏈表的每個元素中都有一個指針指向后一個元素,也有一個指針指向前一個元素。
在 list 容器中,在已經定位到要增刪元素的位置的情況下,增刪元素能在常數時間內完成。如圖2所示,在 ai 和 ai+1 之間插入一個元素,只需要修改 ai 和 ai+1 中的指針即可。
圖1 :雙向鏈表
圖2:在雙向鏈表中插入元素
list 容器不支持根據下標隨機存取元素。
list 的構造函數和許多成員函數的用法都與 vector 類似。除了順序容器都有的成員函數外,list 容器還獨有如下表所示的成員函數(此表不包含全部成員函數,且有些函數的參數較為復雜,表中只列出函數名)。
list 的成員函數
| void push_front(const T & val) | 將 val 插入鏈表最前面 |
| void pop_front() | 刪除鏈表最前面的元素 |
| void sort() | 將鏈表從小到大排序 |
| void remove (const T & val) | 刪除和 val 相等的元素 |
| remove_if | 刪除符合某種條件的元素 |
| void unique() | 刪除所有和前一個元素相等的元素 |
| void merge(list & x) | 將鏈表 x 合并進來并清空 x。要求鏈表自身和 x 都是有序的 |
| void splice(iterator i, list & x, iterator first, iterator last) | 在位置 i 前面插入鏈表 x 中的區間 [first, last),并在鏈表 x 中刪除該區間。鏈表自身和鏈表 x 可以是同一個鏈表,只要 i 不在 [first, last) 中即可 |
表中列出的成員函數有些是重載的,如 unique、merge、splice 成員函數都不止一個。
STL 中的算法 sort 可以用來對 vector 和 deque 排序,它需要隨機訪問迭代器的支持。因為 list 不支持隨機訪問迭代器,所以不能用算法 sort 對 list 容器排序。因此,list 容器引入了 sort 成員函數以完成排序。
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(); //刪除第一個元素cout << "3)"; Print(lst2.begin(), lst2.end()); //輸出:3)30 20 30 30 40 40lst2.unique(); //刪除所有和前一個元素相等的元素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 三個元素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 解決約瑟夫問題。
約瑟夫問題是:有 n 只猴子,按順時針方向圍成一圈選大王(編號為 1~n),從第 1 號開始報數,一直數到 m,數到 m 的猴子退到圈外,剩下的猴子再接著從 1 開始報數。就這樣,直到圈內只剩下一只猴子時,這個猴子就是猴王。編程求輸入 n、m 后,輸出最后猴王的編號。
輸入數據:每行是用空格分開的兩個整數,第一個是 n,第二個是 m(0<m, n<=1 000 000)。最后一行是:
0 0
輸出要求:對于每行輸入數據(最后一行除外),輸出數據也是一行,即最后猴王的編號。
輸入樣例:
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(); //清空list容器for (int i = 1; i <= n; ++i) //將猴子的編號放入listmonkeys.push_back(i);list<int>::iterator it = monkeys.begin();while (monkeys.size() > 1) { //只要還有不止一只猴子,就要找一只猴子讓其出列for (int i = 1; i < m; ++i) { //報數++it;if (it == monkeys.end())it = monkeys.begin();}it = monkeys.erase(it); //刪除元素后,迭代器失效,//要重新讓迭代器指向被刪元素的后面if (it == monkeys.end())it = monkeys.begin();}cout << monkeys.front() << endl; //front返回第一個元素的引用}return 0; }erase 成員函數返回被刪除元素后面那個元素的迭代器。如果被刪除的是最后一個元素,則返回 end()。
這個程序也可以用 vector 實現,但是執行速度要慢很多。因為 vector 的 erase 操作牽涉元素的移動,不能在常數時間內完成,所花費的時間和容器中的元素個數有關;而 list 的 erase 操作只是修改幾個指針而已,可以在常數時間內完成。當 n 很大(數十萬)時,兩種寫法在速度上會有明顯區別。
總結
以上是生活随笔為你收集整理的C++ list,STL list的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C语言指针是什么
- 下一篇: C++ open 打开文件