一、list要注意事项


1.迭代器失效


list没有增容销毁空间这一说,因此insert等插入不会导致失效
erase也是返回下一个位置的迭代器

1
2
3
4
5
if (*it % 2 == 0)
it = l.erase(it); //erase 会导致迭代器失效
//空间被erase后不能再进行操作,即++,*;
else
++it;

2.splic(连接两个链表)


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
list<int> l;
l.push_back(1);
l.push_back(2);
l.push_back(3);
l.push_back(4);

list<int> lt;
lt.push_back(10);
lt.push_back(20);
lt.push_back(30);
lt.push_back(40);
list<int>::iterator pos = l.begin();
++pos;

l.splice(pos, lt); //在 l 链表中的pos位置插入lt链表
Print_list(l); //1 10 20 30 40 2 3 4
Print_list(lt); //lt插入过去就没了,成了l的一部分

二、模拟实现list


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
namespace 9TSe
{
template<class T> //一个节点的类
struct __list_node
{
T _data;
__list_node* _next;
__list_node* _prev;

__list_node(const T& x = T())
:_data(x)
,_next(nullptr)
,_prev(nullptr)
{}
};


template<class T, class Ref, class Ptr> //迭代器的类
struct __list_iterator
{
typedef __list_node<T> Node;
typedef __list_iterator<T, Ref, Ptr> Self;

Node* _node; //创建一个新节点

__list_iterator(Node* node) //构造节点
:_node(node)
{}

Ref operator*() //应该还有一个const类型的此函数,但要再写一个就要再创建一个const_iterator类其他都赋值,这两个加个const
{ //会导致代码冗余 T&
return _node->_data;
}

Ptr operator->() //同上,套用模板可以简写 T*
{
return &(_node->_data); //&取其地址以->,所以实际上使用应为 dit->->_year,只不过被编译器特殊处理优化
}


Self& operator++() //前置++,做到能像vector一样++就访问下一个数据
{
_node = _node->_next;
return *this;
}

Self& operator++(int) //后置++
{
//__list_iterator tmp(*this);
Self tmp = *this;

//_node = _node->_next;
++(*this);
return tmp;
}

Self& operator--() //前置--
{
_node = _node->_prev;
return *this;
}

Self& operator--(int) //后置--
{
Self tmp(*this);
//_node = _node->_prev;
--(*this);
return *this;
}

bool operator!=(const Self& it) //迭代器循环时需要!= 记得加上const
{
return _node != it._node; //迭代器(两个指针)不相同
}

bool operator==(const Self& it)
{
return _node == it._node;
}

};


template<class T> //链表的类
class list
{
public:
typedef __list_node<T> Node;
typedef __list_iterator<T,T&,T*> iterator;
typedef __list_iterator<T,const T&, const T*> const_iterator;

iterator begin()
{
return iterator(_head->_next); //哨兵的下一位才是数据的第一位
}

iterator end()
{
return iterator(_head); //哨兵就是最后一位
}

const_iterator begin()const
{
return const_iterator(_head->_next);
}

const_iterator end()const
{
return const_iterator(_head);
}

list()
{
_head = new Node;
_head->_next = _head;
_head->_prev = _head;
}

list(const list<T>& lt)
{
_head = new Node;
_head->_next = _head;
_head->_prev = _head;

/*const_iterator it = lt.begin();
while (it != end())
{
push_back(*it);
++it;
}*/

for (auto e : lt)
{
push_back(e);
}
}

/*list<T>& operator=(const list<T>& lt)
{
if (*this != &lt)
{
clear();
for (auto& e : lt)
{
push_back(e);
}
}
return *this;
}*/

list<T>& operator=(list<T> lt)
{
swap(_head, lt._head); //交换指针指向的方向,即哨兵
return *this;
}


~list()
{
clear(); //清楚除哨兵外的数据
delete _head;
_head = nullptr;
}

void clear()
{
iterator it = begin();
while (it != end())
{
erase(it++); //迭代器失效是因为,it被销毁后访问++或*,先调用重载++,后erase
}
}

void push_back(const T& x)
{
//Node* tail = _head->_prev;
//Node* newnode = new Node(x); //括号这里讲过
//
//tail->_next = newnode;
//newnode->_prev = tail;
//newnode->_next = _head;
//_head->_prev = newnode;
insert(end(), x); //插在哨兵前,哨兵前就是尾

}

void pop_back()
{
//erase(iterator(_head->_prev));
erase(--end()); //哨兵前就是最后一个数据
}

void push_front(const T& x)
{
insert(begin(), x);
}

void pop_front()
{
erase(begin());
}

void insert(iterator pos, const T& x) //pos位置前插入
{
Node* newnode = new Node(x); //这里一定要初始值x
Node* cur = pos._node;
Node* prev = cur->_prev;
cur->_prev = newnode;
newnode->_next = cur; //1 2 3 3 4
newnode->_prev = prev;
prev->_next = newnode;
}

void erase(iterator pos)
{
assert(pos != end()); //不能删哨兵 1 2 3 3 4
Node* cur = pos._node;
Node* next = cur->_next;
Node* prev = cur->_prev;
delete cur; //可以不置空,出作用域自动销毁

next->_prev = prev;
prev->_next = next;
}

private:
Node* _head;
};






void test_list1() //基本的遍历
{
list<int> lt;
lt.push_back(1);
lt.push_back(2);
lt.push_back(3);
lt.push_back(4);

list<int>::iterator lit = lt.begin();
while (lit != lt.end())
{
cout << *lit << " ";
++lit;
}
cout << endl;
}



struct Date
{
int _year = 0;
int _month = 1;
int _day = 1;
};
void test_list2() //cout类的数据
{
list<Date> dlt;
dlt.push_back(Date());
dlt.push_back(Date());

list<Date>::iterator dit = dlt.begin();
while (dit != dlt.end())
{
//cout << *dit << " "; //此时无法输出,一个类解引用怎么得不出想要的结果
cout << dit->_year << "-" << dit->_month << "-" << dit->_day << endl; //这里->需要重载
// dit-> 返回 Date*
//所以实际上应写为 dit->->_year 为了可读性,编译器将其优化了,这样写反而会出错


cout <<(*dit)._year << "-" << (*dit)._month << "-" << (*dit)._day << endl; //这样写也可以
//但是推荐->写法

dit++;
}
cout << endl;
}


void print_list(const list<int>& lt)
{
list<int>::const_iterator lit = lt.begin();
while (lit != lt.end())
{
//*lit = 1; //在修饰了lt为const,这一步却不报错且可以执行,不符合我们的要求
//此时加入const_iterator begin,end,重载*和&的修改
cout << *lit << " ";
++lit;
}
cout << endl;
}

void test_list3() //测试部分操作接口
{
list<int> lt;
lt.push_back(1);
lt.push_back(2);
lt.push_back(3);
lt.push_back(4);

print_list(lt);

lt.pop_back();
lt.pop_front();
print_list(lt);

lt.clear();
print_list(lt);
}

void test_list4() //测试默认函数
{
list<int> lt1;
lt1.push_back(1);
lt1.push_back(2);
lt1.push_back(3);
lt1.push_back(4);

list<int> lt2(lt1); //之所以在重载++地方报错是因为,clear时调用++,浅拷贝释放后无法++

list<int> lt3;
lt3 = lt2;

print_list(lt2);
print_list(lt3);
}

//Node* cur 和 iterator it 的区别
//他们都指向同一个节点,在物理内存中他们都是存的这个节点的地址
//但是他们类型不一样,他们的意义就不一样了
//*cur表示的是指针的解引用 ,取到的值是节点
//*it 表示去调用这个迭代器重载的*,返回的是节点中的值
}