-
Notifications
You must be signed in to change notification settings - Fork 0
/
list.hpp
216 lines (200 loc) · 6.78 KB
/
list.hpp
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
#ifndef _ASP_LIST_HPP_
#define _ASP_LIST_HPP_
#include <ostream>
#include "list_node.hpp"
#include "basic_io.hpp"
namespace asp {
template <typename _Tp, typename _Alloc = std::allocator<_Tp>> class list;
template <typename _Tp, typename _Alloc = std::allocator<_Tp>> struct list_alloc;
template <typename _Tp, typename _Alloc> struct list_alloc : public _Alloc {
typedef list_node<_Tp> node_type;
typedef _Alloc elt_allocator_type;
typedef std::allocator_traits<elt_allocator_type> elt_alloc_traits;
typedef typename elt_alloc_traits::template rebind_alloc<node_type> node_allocator_type;
typedef std::allocator_traits<node_allocator_type> node_alloc_traits;
elt_allocator_type& _M_get_elt_allocator() { return *static_cast<elt_allocator_type*>(this); }
const elt_allocator_type& _M_get_elt_allocator() const { return *static_cast<const elt_allocator_type*>(this); }
node_allocator_type _M_get_node_allocator() const { return node_allocator_type(_M_get_elt_allocator()); }
node_type* _M_allocate_node(const node_type& _x) {
node_allocator_type _node_alloc = _M_get_node_allocator();
auto _ptr = node_alloc_traits::allocate(_node_alloc, 1);
node_type* _p = std::addressof(*_ptr);
node_alloc_traits::construct(_node_alloc, _p, _x.val());
return _p;
}
template <typename... _Args> node_type* _M_allocate_node(_Args&&... _args) {
node_allocator_type _node_alloc = _M_get_node_allocator();
auto _ptr = node_alloc_traits::allocate(_node_alloc, 1);
node_type* _p = std::addressof(*_ptr);
node_alloc_traits::construct(_node_alloc, _p, std::forward<_Args>(_args)...);
return _p;
}
void _M_deallocate_node(node_type* _p) {
node_allocator_type _node_alloc = _M_get_node_allocator();
node_alloc_traits::destroy(_node_alloc, _p);
node_alloc_traits::deallocate(_node_alloc, _p, 1);
}
};
template <typename _Tp, typename _Alloc> class list : public list_alloc<_Tp, _Alloc> {
typedef list<_Tp, _Alloc> self;
typedef list_alloc<_Tp, _Alloc> base;
public:
typedef typename base::node_type node_type;
typedef typename node_type::value_type value_type;
typedef typename node_type::pointer pointer;
typedef typename node_type::reference reference;
typedef list_iterator<value_type> iterator;
typedef list_const_iterator<value_type> const_iterator;
list() {
_M_init_mark();
}
list(const self& _l) : m_element_count(_l.m_element_count) {
_M_init_mark();
this->_M_assign(_l);
}
self& operator=(const self& _l) {
if (&_l == this) return *this;
clear();
_M_init_mark();
this->_M_assign(_l);
return *this;
}
virtual ~list() {
node_type* p = mark.next;
while (p != &mark) {
auto pnext = p->next;
// delete p;
this->_M_deallocate_node(p);
p = pnext;
}
};
const value_type& front() const { return mark.next->val(); }
value_type& front() { return mark.next->val(); }
const value_type& back() const { return mark.prev->val(); }
value_type& back() { return mark.prev->val(); }
size_type size() const { return m_element_count; }
bool empty() const { return size() == 0; }
/// iterator
iterator begin() { return iterator(mark.next); }
const_iterator cbegin() const { return const_iterator(mark.next); }
iterator end() { return iterator(&mark); }
const_iterator cend() const { return const_iterator(&mark); }
void push_front(const value_type& e) { // to head
node_type* p = this->_M_allocate_node(e);
if (p == nullptr) {
return;
}
p->hook(mark.next);
++m_element_count;
}
void pop_front() {
if (empty()) {
return;
}
node_type* p = mark.next;
p->unhook();
this->_M_deallocate_node(p);
--m_element_count;
}
void push_back(const value_type& e) { // to tail
node_type* p = this->_M_allocate_node(e);
if (p == nullptr) {
return;
}
p->hook(&mark);
++m_element_count;
}
void pop_back() {
if (empty()) {
return;
}
node_type* p = mark.prev;
p->unhook();
this->_M_deallocate_node(p);
--m_element_count;
}
iterator insert(const_iterator pos, const value_type& e) {
node_type* p = this->_M_allocate_node(e);
p->hook(pos._const_cast()._ptr);
++m_element_count;
return iterator(p);
}
iterator erase(const_iterator pos) {
iterator _ret = iterator(pos._const_cast()._ptr->next);
node_type* p =pos._const_cast()._ptr;
if (p == &mark) {
return end();
}
p->unhook();
--m_element_count;
this->_M_deallocate_node(p);
return _ret;
}
iterator erase(const_iterator first, const_iterator last) {
iterator _ret = iterator(last._const_cast()._ptr);
node_type* p = first._const_cast()._ptr;
while (p != last._ptr) {
auto _tmp = p->next;
p->unhook();
this->_M_deallocate_node(p);
--m_element_count;
p = _tmp;
}
return _ret;
}
void clear() {
if (empty()) return;
node_type* prev = nullptr;
node_type* p = mark.next;
for (; p != nullptr && p != &mark;) {
prev = p;
p = p->next;
this->_M_deallocate_node(prev);
}
_M_init_mark();
m_element_count = 0;
}
void move_2_front(const_iterator _pos) {
node_type* _p = _pos._const_cast()._ptr;
if (_p == &mark) return;
_p->unhook();
_p->hook(mark.next);
}
void move_2_back(const_iterator _pos) {
node_type* _p = _pos._const_cast()._ptr;
if (_p == &mark) return;
_p->unhook();
_p->hook(&mark);
}
/// ostream
template <typename _R> friend std::ostream& operator<<(std::ostream& os, const list<_R>& l) {
os << '[';
for (auto p = l.cbegin(); p != l.cend(); ++p) {
os << p;
if (p + 1 != l.cend()) {
os << ", ";
}
}
os << ']';
return os;
}
protected:
void _M_init_mark() {
mark.prev = &mark;
mark.next = &mark;
}
void _M_assign(const self& _l) {
this->clear();
for (const_iterator _i = _l.cbegin(); _i != _l.cend(); ++_i) {
this->push_back(*_i);
}
}
private:
// node_type* head = nullptr; // head->prev = nullptr
// node_type* tail = nullptr; // tail->next = nullptr
// head = mark.next; tail = mark.prev;
node_type mark;
size_type m_element_count = 0;
};
};
#endif //! #ifndef _ASP_LIST_HPP_