STL 中的算法 sort 可以用來對 vector 和 deque 排序,它需要隨機訪問迭代器的支持。因爲 list 不支持隨機訪問迭代器,所以不能用算法 sort 對 list 容器排序。因此,list 容器引入了 sort 成員函數以完成排序。
list排序插入函數的使用
#include <iostream>
#include <stdlib.h>
#include <list>
#include <algorithm>
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 &a2);
};
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[] = { 1, 2, 3, 4, 53, 2 };
A b[] = { 10, 23, 4, 65,23,10,10,10,4,4,7,7,7,87 };
list<A>lst1(a, a + sizeof(a) / sizeof(a[0]))
, lst2(b, b + sizeof(b) / sizeof(b[0]));
lst1.sort();
cout << "1):"; Print(lst1.begin(),lst1.end()); //從小到大排序後輸出
lst2.sort();
cout << "2):"; Print(lst2.begin(), lst2.end()); //從小到大排序後輸出
lst2.remove(4); //刪除和4相同的元素
cout << "3):"; Print(lst2.begin(), lst2.end());
lst2.pop_front(); //刪除lst2的第一個元素
cout << "4):"; Print(lst2.begin(), lst2.end());
lst2.unique(); //刪除所有和前一個元素相等的元素
cout << "5):"; Print(lst2.begin(),lst2.end());
lst1.merge(lst2); //合併lst2到lst1並清空lst2
cout << "6.1):"; Print(lst1.begin(), lst1.end());
cout << "6.2):"; Print(lst2.begin(), lst2.end());
lst1.reverse(); //將lst1前後倒置
cout << "7):"; Print(lst1.begin(), lst1.end());
lst2.insert(lst2.begin(), a + 1, a + 4); //在 lst2 中插入 三個元素
cout << "8)"; Print(lst2.begin(), lst2.end());
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 << "9)"; Print(lst1.begin(), lst1.end());
cout << "10)"; Print(lst2.begin(), lst2.end());
system("pause");
return 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) //將猴子的編號放入list
monkeys.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;
}
vector與list 的區別
vector list
底 層 結 構 動態順序表,一段連續空間 帶頭結點的雙向循環鏈表
隨 機 訪 問 支持隨機訪問,訪問某個元素效率O(1) 不支持隨機訪問,訪問某個元素 效率O(N)
插 入 和 刪 除 任意位置插入和刪除效率低,需要搬移元素,
時間複雜 度爲O(N),插入時有可能需要增容, 任意位置插入和刪除效率高,不需要搬移元素
增容:開闢新空 間,拷貝元素,釋放舊空間,導致效率更低 時間複雜度O(1)
空 間 利 用 率 底層爲連續空間,不容易造成內存碎片,空間利用率 底層節點動態開闢,小節點容易
高,緩存利用率高 造成內存碎片,空間利用率低,緩存利用率低
迭 代 器 原生態指針 對原生態指針(節點指針)進行封裝
迭 代 器 失 效 在插入元素時,要給所有的迭代器重新賦值,因爲插入 插入元素不會導致迭代器失效,
元素有可能會導致重新擴容,致使原來迭代器失效,刪 刪除元素時,只會導致當前迭代
除時,當前迭代器需要重新賦值否則會失效 器失效,其他迭代器不受影響
使 用 場 景 需要高效存儲,支持隨機訪問,不關心插入刪除效率 大量插入和刪除操作,不關心隨機訪問