
无参构造,n个value 构造,迭代区间构造,拷贝构造
迭代器都一样,不一样的是链表还支持下标加方括号吗 ,不支持,获取下标能想办法,【】要从头开始获取第三个第五个,代价太大O(N)。之前数组都是o(1).



也能用范围for 其他迭代器就不演示了。
删除第三个位置数据不能这么写
迭代器不是原生指针,找第几个很麻烦,之前说从功能上划分iterator reverse------iterator const------iterator const------reverse------iterator ,
决定迭代器性质的是由底层结构决定的。mebertype能看

sort只能用随机迭代器,不是就报错,底层是快排,三数取中要支持加减随机访问的,两个迭代器相加相减, 快排递归深度太深转换成别的堆排也要求随机访问,所以要随机迭代器,
reverse 要求传双向迭代器, forwardlist就不能用它逆置
因为这个算法用了--,vector string这些随机迭代器能不能用逆置啊,可以,双向是一种特殊单项,随机是特殊单项 双向,
find 这里的迭代器是input迭代器,这个迭代器,可以给任意类型迭代器,find只用了++,所以单项双向随机都可以,
看一个算法,看看容器到底支不支持,forward iterator 单项迭代器就行。
#include<algorithm>
给一个不匹配的迭代器实际编译会报错,实际底层用迭代器进行减,随机迭代器才进行+ -,
命名时候名字就暗示了要用哪些迭代器。
pushback支持的emplace也支持
如果插入的数据不是单个,emplace会有差别,
cpp
struct A
{
public:
A(int a1 = 1, int a2 = 1)
:_a1(a1)
,_a2(a2)
{
cout << "A(int a1 = 1, int a2 = 1)" << endl;
}
A(const A& aa)
:_a1(aa._a1)
,_a2(aa._a2)
{
cout << "A(const A& aa)" << endl;
}
int _a1;
int _a2;
};
void test_list2()
{
/*list<int> lt;
lt.push_back(1);
lt.emplace_back(2);
lt.emplace_back(3);
lt.emplace_back(4);
for (auto e : lt)
{
cout << e << " ";
}
cout << endl;*/
list<A> lt;
A aa1(1, 1);
lt.push_back(aa1);
lt.push_back(A(2,2));
//lt.push_back(3, 3);
lt.emplace_back(aa1);
lt.emplace_back(A(2,2));
cout << endl;
// 支持直接传构造A对象的参数emplace_back
lt.emplace_back(3, 3);
}
pushback支持的我也支持,我还可以3,3,因为pushcack只支持一个参数,,emplace是个模板的,可以自动推推导,底层比较复杂,上面的是把A构造好了,再去拷贝构造,
下面这个更高效一点,他把参数直接往下面传,到节点那一层直接构造就可以了,直接拿参数往下走,直接构造。
最后那个少一次拷贝构造,emplace效率高,
插入一个值,插入n个值,插入迭代器区间。如果想在第三个位置插入一下,不好搞。,迭代器限制,双向迭代器不能+3

erase支持删除一段迭代区间值,少,主要用删除某个位置的值


swap为了高效,不走深拷贝,交换指针就行。。。。这些都差不多
erase还是O(1),find是O(N)
双向链表插入,找到前一个就行,删除也是,O(1)
find是算法不是链表,甩锅嫌疑

这样可以逆置,但是

这也可以逆置,所以这些有些冗余,双向迭代器也支持
自己单独支持一个sort,因为双向链表的原因算法库不支持,算法库不支持,所以自己写了个

算法和这都是默认升序,这只管用。降序用到仿函数,这是个特殊的类
算法库有两个东西,<就是升序>就是降序
这就可以降序了。这时候传匿名对象就爽死了,有名对象还要写两行
算法库里sort也是默认升序,如果想降序,第三个传greater的匿名对象就行,

链表合并前提是要求链表有序
合并时候就是取小的尾插,这是second合并给给first,second就空了,用得不多
unique去重,要求数据必须有序
后面5没去掉。因为他以为所有相同值都挨在一起,逻辑就是假设有序。

算法有序了以后想去重是很简单的事,遇到这个位置,用一个双指针,如果后一个值跟这个值相同,让后一个迭代器++,直到不相等,中间有值要把这段区间删掉,迭代器++,到这个位置,然后erase掉这个区间,就是双指针 如果有多个相同的,那就找到这个区间,然后第一个保留剩下erase,费劲的是sort,不排序去重,效率极低
remove就是删除一个值
splice:剪切
第二个是转移那一个,第三个转移区间
x插入position之前,我的链表就没了
拿走插入2之前,mylist2就空了
假设要把顺序转移一下,6转移到头上去
第一种方式5删除,头插入;第二种方式:直接诶转移走。splice 可以自己转移给自己
给it和it后面的值,如果给it,就把这一个值转移到前面了
splice可以把一个链表给另一个链表也可以调整一个链表的数据
cpp
void test_list6()
{
// 一个链表节点转移给另一个链表
std::list<int> mylist1, mylist2;
std::list<int>::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
// 调整当前链表节点的顺序
list<int> lt;
lt.push_back(1);
lt.push_back(2);
lt.push_back(3);
lt.push_back(4);
lt.push_back(5);
lt.push_back(6);
for (auto e : lt)
{
cout << e << " ";
}
cout << endl;
int x = 0;
cin >> x;
it = find(lt.begin(), lt.end(), x);
if (it != lt.end())
{
//lt.splice(lt.begin(), lt, it);
lt.splice(lt.begin(), lt, it, lt.end());
}
for (auto e : lt)
{
cout << e << " ";
}
cout << endl;
}
swap也是,不是调用库里的,头结点交换,效率最高
数据量少可以用链表排序,数据量不能用,效率低
cpp
void test_op1()
{
srand(time(0));
const int N = 1000000;
list<int> lt1;
vector<int> v;
for (int i = 0; i < N; ++i)
{
auto e = rand() + i;
lt1.push_back(e);
v.push_back(e);
}
int begin1 = clock();
// 排序
sort(v.begin(), v.end());
int end1 = clock();
int begin2 = clock();
lt1.sort();
int end2 = clock();
printf("vector sort:%d\n", end1 - begin1);
printf("list sort:%d\n", end2 - begin2);
}
测性能时候开release;因为debug优化没开全。
vector底层用的快排,递归在debug下面表现不好,因为debug要打很多调试信息,建立战阵存很多信息,调用很多函数,打印很多调试信息所以递归在debug下很差。但是火力全开就很牛bi。
cpp
void test_op2()
{
srand(time(0));
const int N = 1000000;
list<int> lt1;
list<int> lt2;
for (int i = 0; i < N; ++i)
{
auto e = rand()+i;
lt1.push_back(e);
lt2.push_back(e);
}
int begin1 = clock();
// 拷贝vector
vector<int> v(lt2.begin(), lt2.end());
// 排序
sort(v.begin(), v.end());
// 拷贝回lt2
lt2.assign(v.begin(), v.end());
int end1 = clock();
int begin2 = clock();
lt1.sort();
int end2 = clock();
printf("list copy vector sort copy list sort:%d\n", end1 - begin1);
printf("list sort:%d\n", end2 - begin2);
}
两个链表排序,用相同数据,
这时候用不了赋值因为一个是vector 一个是list,这里用assign
有个迭代区间,别人迭代区间也行,链表拷贝给vector ,vector排完序,在assign给链表,这样还是快。