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)
空 间 利 用 率 底层为连续空间,不容易造成内存碎片,空间利用率 底层节点动态开辟,小节点容易
高,缓存利用率高 造成内存碎片,空间利用率低,缓存利用率低
迭 代 器 原生态指针 对原生态指针(节点指针)进行封装
迭 代 器 失 效 在插入元素时,要给所有的迭代器重新赋值,因为插入 插入元素不会导致迭代器失效,
元素有可能会导致重新扩容,致使原来迭代器失效,删 删除元素时,只会导致当前迭代
除时,当前迭代器需要重新赋值否则会失效 器失效,其他迭代器不受影响
使 用 场 景 需要高效存储,支持随机访问,不关心插入删除效率 大量插入和删除操作,不关心随机访问