1 #ifndef doubly_linked_lists_h
2 #define doubly_linked_lists_h
4 #include <AD/generic/generic.h>
6 //////////////////////////////////////////////////////////////////////////////
7 // Linked node structure; this class is be made visible to the
8 // client. Notice that the link structure is made hidden to the user
10 //////////////////////////////////////////////////////////////////////////////
11 template <class T
> class DLinkList
;
14 ////////////////////////////////////////////////////////////////////////
16 ////////////////////////////////////////////////////////////////////////
18 DNode
* _prev
, * _next
;
19 friend class DLinkList
<T
>;
20 inline DNode
* set_prev(DNode
* p
) { _prev
= p
; }
21 inline DNode
* set_next(DNode
* n
) { _next
= n
; }
23 ////////////////////////////////////////////////////////////////////////
25 ////////////////////////////////////////////////////////////////////////
26 inline DNode(const T
& e
, DNode
* p
= 0, DNode
* n
= 0)
27 : element(e
), _prev(p
), _next(n
) {}
28 inline DNode
* prev() const { return _prev
; }
29 inline DNode
* next() const { return _next
; }
30 inline const T
& value() const { return element
; }
31 inline T
& value() { return element
; }
35 //////////////////////////////////////////////////////////////////////////////
37 // Doubly linked lists template.
38 // This class implements a double linked list datatype.
39 // The list nodes can be manipulated directly using the link/unlink methods,
40 // while the insert/remove methods provide an encapsulated interface to
43 //////////////////////////////////////////////////////////////////////////////
47 ////////////////////////////////////////////////////////////////////////
49 ////////////////////////////////////////////////////////////////////////
50 typedef T Element
; // element type
51 typedef DNode
<T
> * Ix
; // index type
53 ////////////////////////////////////////////////////////////////////////
55 ////////////////////////////////////////////////////////////////////////
56 int count
; // number of elements in list
57 DNode
<T
> * front
, * back
; // link to first and last element
61 ////////////////////////////////////////////////////////////////////////
62 // Constructors and destructor
63 ////////////////////////////////////////////////////////////////////////
65 DLinkList(const DLinkList
&);
68 ////////////////////////////////////////////////////////////////////////
70 ////////////////////////////////////////////////////////////////////////
71 DLinkList
& operator = (const DLinkList
&);
73 ////////////////////////////////////////////////////////////////////////
75 ////////////////////////////////////////////////////////////////////////
76 inline int size () const { return count
; }
77 inline Bool
is_empty () const { return front
== 0; }
79 ////////////////////////////////////////////////////////////////////////
81 ////////////////////////////////////////////////////////////////////////
82 inline DNode
<T
> * first() const { return front
; }
83 inline DNode
<T
> * last () const { return back
; }
84 inline DNode
<T
> * next (DNode
<T
> * i
) const { return i
->next(); }
85 inline DNode
<T
> * prev (DNode
<T
> * i
) const { return i
->prev(); }
86 inline const T
& operator () (DNode
<T
> * i
) const { return i
->value(); }
87 inline T
& operator () (DNode
<T
> * i
) { return i
->value(); }
89 ////////////////////////////////////////////////////////////////////////
91 // Two interfaces are provided:
93 ////////////////////////////////////////////////////////////////////////
96 inline DLinkList
& insert_before (DNode
<T
> *, const T
&);
97 inline DLinkList
& insert_after (DNode
<T
> *, const T
&);
98 inline DLinkList
& insert_to_front (const T
& e
);
99 inline DLinkList
& insert_to_back (const T
& e
);
100 inline DLinkList
& remove (DNode
<T
> *);
101 inline DLinkList
& remove_from_front();
102 inline DLinkList
& remove_from_back ();
104 inline DNode
<T
> * unlink (DNode
<T
> *);
105 inline DNode
<T
> * unlink_from_front();
106 inline DNode
<T
> * unlink_from_back ();
107 inline DLinkList
& link_to_front (DNode
<T
> *);
108 inline DLinkList
& link_to_back (DNode
<T
> *);
109 inline DLinkList
& link_before (DNode
<T
> *, DNode
<T
> *);
110 inline DLinkList
& link_after (DNode
<T
> *, DNode
<T
> *);
112 ////////////////////////////////////////////////////////////////////////
114 ////////////////////////////////////////////////////////////////////////
115 inline DLinkList
& operator , (const T
& e
) { return insert_to_back(e
); }
116 inline DLinkList
& operator , (DNode
<T
> * n
) { return link_to_back(n
); }
117 inline DLinkList
& operator += (const T
& e
) { return insert_to_back(e
); }
118 inline DLinkList
& operator += (DNode
<T
> * n
) { return link_to_back(n
); }
119 inline DLinkList
& operator = (const T
& e
) { clear(); return insert_to_back(e
); }
120 inline DLinkList
& operator = (DNode
<T
> * n
) { clear(); return link_to_back(n
); }
123 //////////////////////////////////////////////////////////////////////////////
124 // Implementation of the template methods.
125 //////////////////////////////////////////////////////////////////////////////
127 //////////////////////////////////////////////////////////////////////////////
128 // Constructors and destructors
129 //////////////////////////////////////////////////////////////////////////////
131 DLinkList
<T
>::DLinkList() : count(0), front(0), back(0) {}
133 DLinkList
<T
>::DLinkList(const DLinkList
<T
>& l
)
134 : count(0), front(0), back(0) { *this = l
; }
136 DLinkList
<T
>::~DLinkList() { clear(); }
138 //////////////////////////////////////////////////////////////////////////////
140 //////////////////////////////////////////////////////////////////////////////
142 DLinkList
<T
>& DLinkList
<T
>::operator = (const DLinkList
<T
>& list
)
143 { if (this != &list
) {
145 for(DNode
<T
> * n
= list
.first(); n
; n
= list
.next(n
))
146 insert_to_back(n
->value());
147 count
+= list
.size();
152 //////////////////////////////////////////////////////////////////////////////
153 // Emptying the list and frees all nodes.
154 //////////////////////////////////////////////////////////////////////////////
156 DLinkList
<T
>& DLinkList
<T
>::clear()
157 { DLinkList
<T
>::Ix l
;
158 while (l
= unlink_from_front()) delete l
;
164 //////////////////////////////////////////////////////////////////////////////
165 // Insert an element to the front of the list.
166 //////////////////////////////////////////////////////////////////////////////
168 inline DLinkList
<T
>& DLinkList
<T
>::insert_to_front (const T
& e
)
169 { // Make ``e'' the head of the list
170 DNode
<T
> * n
= new DNode
<T
>(e
,0,front
);
171 if (front
) front
->set_prev(n
);
177 //////////////////////////////////////////////////////////////////////////////
178 // Insert an element to the back of the list.
179 //////////////////////////////////////////////////////////////////////////////
181 DLinkList
<T
>& DLinkList
<T
>::insert_to_back(const T
& e
)
182 { // Make ``e'' the tail of the list
183 DNode
<T
> * n
= new DNode
<T
>(e
,back
,0);
184 if (back
) back
->set_next(n
);
190 //////////////////////////////////////////////////////////////////////////////
191 // Insert an element 'e' before position ``pos''.
193 // ``pos'' must be non-null and on the list.
194 //////////////////////////////////////////////////////////////////////////////
196 DLinkList
<T
>& DLinkList
<T
>::insert_before (DNode
<T
> * pos
, const T
& e
)
197 { // Insert a new element before position ``pos''.
198 // ``pos'' must be non-null.
200 DNode
<T
> * n
= new DNode
<T
>(e
,pos
->prev(),pos
);
202 if (pos
== front
) front
= n
;
208 //////////////////////////////////////////////////////////////////////////////
209 // Insert an element 'e' after position ``pos''.
211 // ``pos'' must be non-null and on the list.
212 //////////////////////////////////////////////////////////////////////////////
214 DLinkList
<T
>& DLinkList
<T
>::insert_after (DNode
<T
> * pos
, const T
& e
)
215 { // Insert a new element after position ``pos''.
216 // ``pos'' must be non-null.
218 DNode
<T
> * n
= new DNode
<T
>(e
,pos
,pos
->next());
220 if (pos
== back
) back
= n
;
226 //////////////////////////////////////////////////////////////////////////////
227 // Delete a node from a list.
229 // The node ``n'' must be on the list.
230 //////////////////////////////////////////////////////////////////////////////
232 inline DLinkList
<T
>& DLinkList
<T
>::remove (DNode
<T
> * n
)
234 if (n
== front
) front
= n
->next();
235 if (n
== back
) back
= n
->prev();
236 if (n
->prev()) n
->prev()->set_next(n
->next());
237 if (n
->next()) n
->next()->set_prev(n
->prev());
244 //////////////////////////////////////////////////////////////////////////////
245 // Delete a node from the front of the list.
246 //////////////////////////////////////////////////////////////////////////////
248 inline DLinkList
<T
>& DLinkList
<T
>::remove_from_front()
249 { DNode
<T
> * n
= front
;
252 if (n
== back
) back
= n
->prev();
253 if (n
->next()) n
->next()->set_prev(n
->prev());
260 //////////////////////////////////////////////////////////////////////////////
261 // Delete a node from the back of the list.
262 //////////////////////////////////////////////////////////////////////////////
264 inline DLinkList
<T
>& DLinkList
<T
>::remove_from_back()
265 { DNode
<T
> * n
= back
;
268 if (n
== front
) front
= n
->next();
269 if (n
->prev()) n
->prev()->set_next(n
->next());
276 //////////////////////////////////////////////////////////////////////////////
277 // Unlink a node ``n'' from a list.
279 // Node ``n'' must be on the list.
280 //////////////////////////////////////////////////////////////////////////////
282 DNode
<T
> * DLinkList
<T
>::unlink(DNode
<T
> * n
)
284 if (n
== front
) front
= n
->next();
285 if (n
== back
) back
= n
->prev();
286 if (n
->prev()) n
->prev()->set_next(n
->next());
287 if (n
->next()) n
->next()->set_prev(n
->prev());
293 //////////////////////////////////////////////////////////////////////////////
294 // Unlink a node from the front of the list.
295 //////////////////////////////////////////////////////////////////////////////
297 DNode
<T
> * DLinkList
<T
>::unlink_from_front()
298 { DNode
<T
> * n
= front
;
301 if (front
= n
->next())
309 //////////////////////////////////////////////////////////////////////////////
310 // Unlink a node from the back of the list.
311 //////////////////////////////////////////////////////////////////////////////
313 DNode
<T
> * DLinkList
<T
>::unlink_from_back ()
318 if (back
= n
->prev())
326 //////////////////////////////////////////////////////////////////////////////
327 // Linking operations.
328 //////////////////////////////////////////////////////////////////////////////
330 //////////////////////////////////////////////////////////////////////////////
331 // Link ``n'' to front of list.
332 // Node ``n'' must not be already on any list.
333 //////////////////////////////////////////////////////////////////////////////
335 inline DLinkList
<T
>& DLinkList
<T
>::link_to_front(DNode
<T
> * n
)
348 //////////////////////////////////////////////////////////////////////////////
349 // Link ``n'' to end of list.
351 // Node ``n'' must not be already on any list.
352 //////////////////////////////////////////////////////////////////////////////
354 inline DLinkList
<T
>& DLinkList
<T
>::link_to_back(DNode
<T
> * n
)
367 //////////////////////////////////////////////////////////////////////////////
368 // Link node ``n'' before ``pos''.
370 // Node ``pos'' must be somewhere on the list.
371 // Node ``n'' must not be already on any list.
372 //////////////////////////////////////////////////////////////////////////////
374 inline DLinkList
<T
>& DLinkList
<T
>::link_before (DNode
<T
> * pos
, DNode
<T
> * n
)
378 if (pos
== front
) front
= n
;
379 n
->set_next(pos
->next());
390 //////////////////////////////////////////////////////////////////////////////
391 // Link node ``n'' after ``pos''.
393 // Node ``pos'' must be somewhere on the list.
394 // Node ``n'' must not be already on any list.
395 //////////////////////////////////////////////////////////////////////////////
397 inline DLinkList
<T
>& DLinkList
<T
>::link_after (DNode
<T
> * pos
, DNode
<T
> * n
)
401 if (pos
== back
) back
= n
;
402 n
->set_prev(pos
->prev());