数据结构
List使用的数据结构为双向循环链表,使用node指针指向一个置于尾端的空白节点,node便是last迭代器,而node->next便是begin迭代器,形成“前闭后开”的区间。
迭代器
由于STL List为双向链表,故list提供的是双向迭代器(Bidirection Iterators),具备前后移功能。
List重要性质:Inset和splice操作不会造成原有的list的迭代器失效,这在vector中不成立,即使是erase操作都只失去指向被删节点的迭代器。
1. template <class T>
2. struct __list_node
3. {
4. typedef void* void_pointer;
5. void_pointer next;
6. void_pointer prev;
7. T data;
8. };
9.
10. // 至于为什么不使用默认参数, 这个是因为有一些编译器不能提供推导能力,
11. // 而作者又不想维护两份代码, 故不使用默认参数
12. template<class T, class Ref, class Ptr>
13. struct __list_iterator
14. {
15. typedef __list_iterator<T, T&, T*> iterator; // STL标准强制要求
16. typedef __list_iterator<T, Ref, Ptr> self;
17.
18. typedef bidirectional_iterator_tag iterator_category;
19. typedef T value_type;
20. typedef Ptr pointer;
21. typedef Ref reference;
22. typedef __list_node<T>* link_type;
23. typedef size_t size_type;
24. typedef ptrdiff_t difference_type;
25.
26. link_type node; //迭代器内部当然要有一个普通指针,指向list的节点
27.
28. //迭代器的三种构造方式
29. __list_iterator(link_type x) : node(x) {} //用链表,指向链表的Node节点
30. __list_iterator() {}
31. __list_iterator(const iterator& x) : node(x.node) {} //复制构造函数
32.
33. //重载
34. // 在STL算法中需要迭代器提供支持
35. bool operator==(const self& x) const { return node == x.node; }
36. bool operator!=(const self& x) const { return node != x.node; }
37.
38. // 以下对迭代器取值(dereference),取的是节点的数据值
39. reference operator*() const { return (*node).data; }
40.
41. // 以下是迭代器的成员存取运算子的标准做法
42. pointer operator->() const { return &(operator*()); }
43.
44. // 前缀自加,对迭代器累加1,就是前进一个节点
45. self& operator++()
46. {
47. node = (link_type)((*node).next);
48. return *this;
49. }
50.
51. // 后缀自加, 需要先产生自身的一个副本, 然会再对自身操作, 最后返回副本
52. self operator++(int)
53. {
54. self tmp = *this;
55. ++*this;
56. return tmp;
57. }
58.
59. // 前缀自减
60. self& operator--()
61. {
62. node = (link_type)((*node).prev);
63. return *this;
64. }
65.
66. self operator--(int)
67. {
68. self tmp = *this;
69. --*this;
70. return tmp;
71. }
72. };
List的构造与内存管理
List缺省使用alloc作为空间配置器,并据此另外定义了一个list_node_allocator为了更方便的以节点大小为配置单位
1. // 默认allocator为alloc, 其具体使用版本请参照<stl_alloc.h>
2. template <class T, class Alloc = alloc>
3. class list
4. {
5. protected:
6. typedef void* void_pointer;
7. typedef __list_node<T> list_node;
8.
9. // 专属之空间配置器,每次配置一个节点大小
10. typedef simple_alloc<list_node, Alloc> list_node_allocator;
11.
12. public:
13. typedef T value_type;
14. typedef value_type* pointer;
15. typedef value_type& reference;
16. typedef list_node* link_type;
17. typedef size_t size_type;
18. typedef ptrdiff_t difference_type;
19.
20. typedef __list_iterator<T, T&, T*> iterator;
21.
22. protected:
23. link_type node ; // 只要一个指针,便可表示整个环状双向链表
24. // 分配一个新结点, 注意这里并不进行构造,
25. // 构造交给全局的construct, 见<stl_stl_uninitialized.h>
26. link_type get_node() { return list_node_allocator::allocate(); }
27.
28. // 释放指定结点, 不进行析构, 析构交给全局的destroy
29. void put_node(link_type p) { list_node_allocator::deallocate(p); }
30.
31. // 产生(配置并构造)一个节点, 首先分配内存, 然后进行构造
32. // 注: commit or rollback
33. link_type create_node(const T& x)
34. {
35. link_type p = get_node();
36. construct(&p->data, x);
37. return p;
38. }
39.
40. // 析构结点元素, 并释放内存
41. void destroy_node(link_type p)
42. {
43. destroy(&p->data);
44. put_node(p);
45. }
46.
47. protected:
48. // 用于空链表的建立
49. void empty_initialize()
50. {
51. node = get_node(); // 配置一个节点空间,令node指向它
52. node->next = node; // 令node头尾都指向自己,不设元素值
53. node->prev = node;
54. }
55.
56. // 创建值为value共n个结点的链表
57. // 注: commit or rollback
58. void fill_initialize(size_type n, const T& value)
59. {
60. empty_initialize();
61. __STL_TRY
62. {
63. // 此处插入操作时间复杂度O(1)
64. insert(begin(), n, value);
65. }
66. __STL_UNWIND(clear(); put_node(node));
67. }
68.
69.
70. // 在指定位置插入元素
71.
72. // insert(iterator position, const T& x)
73. // ↓
74. // create_node(x)
75. // p = get_node();-------->list_node_allocator::allocate();
76. // construct(&p->data, x);
77. // ↓
78. // tmp->next = position.node;
79. // tmp->prev = position.node->prev;
80. // (link_type(position.node->prev))->next = tmp;
81. // position.node->prev = tmp;
82.
83.
84. iterator insert(iterator position, const T& x)
85. {
86. link_type tmp = create_node(x); // 产生一个节点
87. // 调整双向指针,使tmp插入进去
88. tmp->next = position.node;
89. tmp->prev = position.node->prev;
90. (link_type(position.node->prev))->next = tmp;
91. position.node->prev = tmp;
92. return tmp;
93. }
List元素操作
常用操作:
在链头插入、删除;
push_front(const T& x) pop_front()
在链尾插入、删除;
push_back(const T& x) pop_back()
·删除指定结点;
erase(iterator first, iterator last)
置空整条链;
clear()
返回链长;
size()
结合;
// 将链表x移动到position所指位置之前
splice(iterator position, list& x)
// 将链表中i指向的内容移动到position之前
splice(iterator position, list&, iterator i)
// 将[first, last}元素移动到position之前
splice(iterator position, list&, iterator first, iterator last)
删除所有值为value的结点;
remove(const T& value);
删除连续且相同的元素,只剩一个;
unique()
将x合并到*this上,两链表需要递增排序;
merge(list& x);
颠倒整个链表;
reverse()
排序;
// 使用quick sort,主要操作使用merge
sort()
1. // 在链表前端插入结点
2. void push_front(const T& x) { insert(begin(), x); }
3. // 在链表最后插入结点
4. void push_back(const T& x) { insert(end(), x); }
5.
6. // 移除迭代器position所指节点
7. iterator erase(iterator position)
8. {
9. link_type next_node = link_type(position.node->next);
10. link_type prev_node = link_type(position.node->prev);
11. prev_node->next = next_node;
12. next_node->prev = prev_node;
13. destroy_node(position.node);
14. return iterator(next_node);
15. }
16.
17. // 擦除一个区间的结点, 详细解析见实现部分
18. iterator erase(iterator first, iterator last);
19.
20. void resize(size_type new_size, const T& x);
21. void resize(size_type new_size) { resize(new_size, T()); }
22. void clear();
23.
24. // 删除链表第一个结点
25. void pop_front() { erase(begin()); }
26. // 删除链表最后一个结点
27. void pop_back()
28. {
29. iterator tmp = end();
30. erase(--tmp);
31. }
32.
33. //构造函数
34. list(size_type n, const T& value) { fill_initialize(n, value); }
35. list(int n, const T& value) { fill_initialize(n, value); }
36. list(long n, const T& value) { fill_initialize(n, value); }
37.
38. ~list()
39. {
40. // 释放所有结点
41. // 使用全局函数distance()进行计算, 时间复杂度O(n)
42. size_type size() const
43. {
44. size_type result = 0;
45. distance(begin(), end(), result);
46. return result;
47. }
48. clear();
49. {
50. // 释放头结点
51. put_node(node);
52. }
53.
54. list<T, Alloc>& operator=(const list<T, Alloc>& x);
55.
56. protected:
57.
58.
59. // 将[first, last)内的所有元素移动到position之前
60. // 如果last == position, 则相当于链表不变化, 不进行操作
61.
62. // 初始状态
63. // first last
64. // ↓ ↓
65. // -------- -------- -------- -------- -------- --------
66. // | next |-->| next |-->| next | | next |-->| next |-->| next |
67. // ... -------- -------- -------- ... -------- -------- -------- ...
68. // | prev |<--| prev |<--| prev | | prev |<--| prev |<--| prev |
69. // -------- -------- -------- -------- -------- --------
70. //
71. // position
72. // ↓
73. // -------- -------- -------- -------- -------- --------
74. // | next |-->| next |-->| next |-->| next |-->| next |-->| next |
75. // ... -------- -------- -------- -------- -------- -------- ...
76. // | prev |<--| prev |<--| prev |<--| prev |<--| prev |<--| prev |
77. // -------- -------- -------- -------- -------- --------
78. //
79. // 操作完成后状态
80. // first
81. // |
82. // --------------|--------------------------------------
83. // | ------------|------------------------------------ | last
84. // | | ↓ | | ↓
85. // -------- | | -------- -------- -------- | | -------- --------
86. // | next |-- | ----->| next |-->| next | | next |----- | -->| next |-->| next |
87. // ... -------- | | -------- -------- ... -------- | | -------- -------- ...
88. // | prev |<--- | ---| prev |<--| prev | | prev |<-- | -----| prev |<--| prev |
89. // -------- | | -------- -------- -------- | | -------- --------
90. // | | | |
91. // | ------ | |
92. // ------- | ------------------------------ |
93. // | | | |
94. // | | | -----------------------------
95. // | | | |
96. // | | | | position
97. // | | | | ↓
98. // -------- -------- | | | | -------- -------- -------- --------
99. // | next |-->| next |-- | | -->| next |-->| next |-->| next |-->| next |
100. // ... -------- -------- | | -------- -------- -------- -------- ...
101. // | prev |<--| prev |<--- ------| prev |<--| prev |<--| prev |<--| prev |
102. // -------- -------- -------- -------- -------- --------
103.
104. void transfer(iterator position, iterator first, iterator last)
105. {
106. if (position != last) // 如果last == position, 则相当于链表不变化, 不进行操作
107. {
108. (*(link_type((*last.node).prev))).next = position.node;
109. (*(link_type((*first.node).prev))).next = last.node;
110. (*(link_type((*position.node).prev))).next = first.node;
111. link_type tmp = link_type((*position.node).prev);
112. (*position.node).prev = (*last.node).prev;
113. (*last.node).prev = (*first.node).prev;
114. (*first.node).prev = tmp;
115. }
116. }
117.
118. public:
119. // 将链表x移动到position所指位置之前
120. void splice(iterator position, list& x)
121. {
122. if (!x.empty())
123. transfer(position, x.begin(), x.end());
124. }
125.
126. // 将链表中i指向的内容移动到position之前
127. void splice(iterator position, list&, iterator i)
128. {
129. iterator j = i;
130. ++j;
131. if (position == i || position == j) return;
132. transfer(position, i, j);
133. }
134.
135. // 将[first, last}元素移动到position之前
136. void splice(iterator position, list&, iterator first, iterator last)
137. {
138. if (first != last)
139. transfer(position, first, last);
140. }
141.
142. void remove(const T& value);
143. void unique();
144. void merge(list& x);
145. void reverse();
146. void sort();
147.
148. };
149.
150. // 销毁所有结点, 将链表置空
151. template <class T, class Alloc>
152. void list<T, Alloc>::clear()
153. {
154. link_type cur = (link_type) node->next;
155. while (cur != node)
156. {
157. link_type tmp = cur;
158. cur = (link_type) cur->next;
159. destroy_node(tmp);
160. }
161. // 恢复node原始状态
162. node->next = node;
163. node->prev = node;
164. }
165.
166. // 链表赋值操作
167. // 如果当前容器元素少于x容器, 则析构多余元素,
168. // 否则将调用insert插入x中剩余的元素
169. template <class T, class Alloc>
170. list<T, Alloc>& list<T, Alloc>::operator=(const list<T, Alloc>& x)
171. {
172. if (this != &x)
173. {
174. iterator first1 = begin();
175. iterator last1 = end();
176. const_iterator first2 = x.begin();
177. const_iterator last2 = x.end();
178. while (first1 != last1 && first2 != last2) *first1++ = *first2++;
179. if (first2 == last2)
180. erase(first1, last1);
181. else
182. insert(last1, first2, last2);
183. }
184. return *this;
185. }
186.
187.
188. // 移除容器内所有的相邻的重复结点
189. // 时间复杂度O(n)
190. // 用户自定义数据类型需要提供operator ==()重载
191. template <class T, class Alloc>
192. void list<T, Alloc>::unique()
193. {
194. iterator first = begin();
195. iterator last = end();
196. if (first == last) return;
197. iterator next = first;
198. while (++next != last)
199. {
200. if (*first == *next)
201. erase(next);
202. else
203. first = next;
204. next = first;
205. }
206. }
207.
208. // 假设当前容器和x都已序, 保证两容器合并后仍然有序
209. template <class T, class Alloc>
210. void list<T, Alloc>::merge(list<T, Alloc>& x)
211. {
212. iterator first1 = begin();
213. iterator last1 = end();
214. iterator first2 = x.begin();
215. iterator last2 = x.end();
216.
217. // 注意:前提是,两个lists都已经递增排序
218. while (first1 != last1 && first2 != last2)
219. if (*first2 < *first1)
220. {
221. iterator next = first2;
222. transfer(first1, first2, ++next);
223. first2 = next;
224. }
225. else
226. ++first1;
227. if (first2 != last2)
228. transfer(last1, first2, last2);
229. }
230. template <class T, class Alloc>
231. void list<T, alloc>::reverse()
232. {
233. //一下判断,如果是空链表,或仅有一个元素,就不进行任何操作
234. //使用size() == 0 || size() == 1 来判断,虽然也可以,但是比较慢
235. if (noode->next == node || link_type(node->next)->next== node)
236. return;
237. iterator first = begin();
238. ++first;
239. while (first != begin())
240. {
241. iterator old = first;
242. ++first;
243. transfer(begin(),old, first);
244. }
245. }
246. //本函数使用 quick sort
247. template <class T, class Alloc>
248. void list<T, alloc>::sort()
249. {
250. //一下判断,如果是空链表,或仅有一个元素,就不进行任何操作
251. //使用size() == 0 || size() == 1 来判断,虽然也可以,但是比较慢
252. if (noode->next == node || link_type(node->next)->next== node)
253. return;
254.
255. //一些新的lists,作为中介数据存放区
256. list<T,alloc> carry;
257. list<T,alloc> counter[64];
258. intfill = 0;
259. while (!empty())
260. {
261. carry.splice(carry.begin(), *this, begin());
262. inti = ;
263. while (i < fill && !counter[i].empty())
264. {
265. counter[i].merger(carry);
266. carry.swap(counter[i++]);
267. }
268. carry.swap(counter[i]);
269. if (i == fill)
270. ++fill;
271. }
272. for (int i= 1; i < fill; ++i)
273. counter[i].merge(counter[i - 1]);
274. swap(counter[fill- 1]);
275. }
276.