Scippy

SoPlex

Sequential object-oriented simPlex

islist.h
Go to the documentation of this file.
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /* */
3 /* This file is part of the class library */
4 /* SoPlex --- the Sequential object-oriented simPlex. */
5 /* */
6 /* Copyright (C) 1996-2016 Konrad-Zuse-Zentrum */
7 /* fuer Informationstechnik Berlin */
8 /* */
9 /* SoPlex is distributed under the terms of the ZIB Academic Licence. */
10 /* */
11 /* You should have received a copy of the ZIB Academic License */
12 /* along with SoPlex; see the file COPYING. If not email to soplex@zib.de. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /**@file islist.h
17  * @brief Generic single linked list.
18  */
19 #ifndef _ISLIST_H_
20 #define _ISLIST_H_
21 
22 #include <assert.h>
23 #include <stddef.h>
24 #include <iostream>
25 
26 
27 namespace soplex
28 {
29 
30 //---------------------------------------------------------------------
31 // class IsElement<T>
32 //---------------------------------------------------------------------
33 
34 /**@brief Elements for \ref soplex::IsList "IsList"s.
35  @ingroup Elementary
36 
37  Class IsElement allows to easily construct list elements for an intrusive
38  single linked list IsList out of a template class T. It adds a next
39  pointer to each element. An instance of IdElement<T> a can be used just
40  like an instance of T itself, except that method next() has been
41  added (thereby overriding any method next() defined in T).
42  */
43 template < class T >
44 class IsElement : public T
45 {
46 protected:
47 
48  //--------------------------
49  /**@name Data */
50  //@{
51  IsElement<T>* the_next; ///< pointer to next element in the IsList.
52  //@}
53 
54 public:
55 
56  //---------------------------------
57  /**@name Successor */
58  //@{
59  ///
61  {
62  return the_next;
63  }
64  /// returns the next element in the IsList.
65  IsElement<T>* next() const
66  {
67  return the_next;
68  }
69  //@}
70 
71  //------------------------------------
72  /**@name Constructors / destructors */
73  //@{
74 
75  /// default constructor.
77  {}
78 
79  ///
80  explicit
81  IsElement(const T& old)
82  : T(old)
83  , the_next(0)
84  {}
85 
86  /// copy constructor.
87  /** Only the element itself is copied, while the link to the next list
88  element is set to a zero pointer.
89  */
90  IsElement(const IsElement<T>& old)
91  : T(old)
92  , the_next(0)
93  {}
94 };
95 
96 //---------------------------------------------------------------------
97 // class IsList<T>
98 //---------------------------------------------------------------------
99 
100 /**@brief Generic single linked list.
101  @ingroup Elementary
102 
103  Class IsList implements an intrusive single linked list of elements of a
104  template class T. As an \em intrusive list, the objects of type T
105  must provide methods next() for setting and inquiring a pointer to the
106  next element in a list. The user is responsible for not modifying the
107  next() pointer of elements currently residing in a list, which may destroy
108  the lists integrity. For this, class IsList provides enough methods for
109  modifying a list in a save way. See the method list for a description.
110  */
111 template < class T >
112 class IsList
113 {
114 protected:
115  T* the_first; ///< the first element in the IsList.
116  T* the_last; ///< the last element in the IsList.
118  ///< should the destructor be called for each element when the list is destroyed?
119 
120 public:
122 
123  //--------------------------
124  /**@name Extension */
125  //@{
126  /// appends \p elem to IsList.
127  void append(T* elem)
128  {
129  if (the_last)
130  the_last->next() = elem;
131  else
132  the_first = elem;
133  the_last = elem;
134  }
135 
136  /// prepends \p elem to IsList.
137  void prepend(T* elem)
138  {
139  if (the_first)
140  elem->next() = the_first;
141  else
142  the_last = elem;
143  the_first = elem;
144  }
145 
146  /// inserts \p elem to IsList after its element \p after.
147  void insert(T* elem, T* after)
148  {
149  assert(find(after));
150  if (after == the_last)
151  append(elem);
152  else
153  {
154  elem->next() = after->next();
155  after->next() = elem;
156  }
157  }
158 
159  /// appends all elements of \p list to IsList.
160  /** Appending one list to another keeps the appended \p list. Instead,
161  \p list remains an own IsList which is then part of the
162  concatenated list. This means that modifying \p list will modify the
163  concateneted list as well and vice versa. The programmer is
164  responsible for such changes not to yield inconsistent lists.
165  */
166  void append(IsList<T>& list)
167  {
168  if (list.the_first)
169  {
170  append(list.the_first);
171  the_last = list.the_last;
172  }
173  }
174 
175  /// prepends all elements of \p list to IsList.
176  /** Appending one list to another keeps the appended \p list. Instead,
177  \p list remains an own IsList which is then part of the
178  concatenated list. This means that modifying \p list will modify the
179  concateneted list as well and vice versa. The programmer is
180  responsible for such changes not to yield inconsistent lists.
181  */
182  void prepend(IsList<T>& list)
183  {
184  if (list.the_first)
185  {
186  prepend(list.the_last);
187  the_first = list.the_first;
188  }
189  }
190 
191  /// inserts all elements of \p list after element \p after of an IsList.
192  /** Inserting one list into another keeps the appended \p list. Instead,
193  \p list remains an own IsList which is then part of the
194  concatenated list. This means that modifying \p list will modify the
195  concateneted list as well and vice versa. The programmer is
196  responsible for such changes not to yield inconsistent lists.
197  */
198  void insert(IsList<T>& list, T*after)
199  {
200  assert(find(after));
201  if (list.the_first)
202  {
203  list.the_last->next() = after->next();
204  after->next() = list.first();
205  if (after == last())
206  the_last = list.last();
207  }
208  }
209  //@}
210 
211  //--------------------------
212  /**@name Removal */
213  //@{
214  /// removes the successor of \p after from an IsList.
215  void remove_next(T *after)
216  {
217  assert(find(after));
218  if (after->next())
219  {
220  if (after->next() == last())
221  the_last = after;
222  after->next() = after->next()->next();
223  }
224  }
225 
226  /// removes element \p elem from an IsList.
227  void remove(const T *elem)
228  {
229  if (the_first)
230  {
231  if (elem == the_first)
232  {
233  the_first = next(elem);
234  if (the_first == 0)
235  the_last = 0;
236  }
237  else
238  {
239  T *after = the_first;
240  for (; after != the_last; after = after->next())
241  if (after->next() == elem)
242  {
243  remove_next(after);
244  return;
245  }
246  }
247  }
248  }
249 
250  /// removes all elements of \p list from an IsList.
251  /** Removing \p list from an IsList requires \p list to be part of the
252  IsList. Such a situation can be achieved by previously adding
253  (i.e., #append%ing, #insert%ing or #prepend%ing) a list or
254  explicitely constructing a sublist with method sublist().
255  */
256  void remove(IsList<T>& list)
257  {
258  if (the_first != 0 && list.the_first != 0)
259  {
260  assert(find(list.first()));
261  assert(find(list.last()));
262  if (the_first == list.the_first)
263  {
264  if (the_last == list.the_last)
265  the_first = the_last = 0;
266  else
267  the_first = list.the_last->next();
268  }
269  else
270  {
271  T *after = the_first;
272  for (; after->next() != list.the_first; after = after->next())
273  ;
274  if (the_last == list.the_last)
275  the_last = after;
276  else
277  after->next() = list.the_last->next();
278  }
279  }
280  }
281 
282  /// removes all elements from an IsList.
283  void clear(bool pDestroyElements = false)
284  {
285  if( pDestroyElements )
286  {
287  T* nextElement;
288  for( T* it = the_first; it; it = nextElement )
289  {
290  nextElement = next(it);
291  it->~T();
292  spx_free(it);
293  }
294  }
295 
296  the_first = the_last = 0;
297  }
298  //@}
299 
300  //--------------------------
301  /**@name Access */
302  //@{
303  /// returns the IsList's first element.
304  T* first() const
305  {
306  return the_first;
307  }
308 
309  /// returns the IsList's last element.
310  T* last() const
311  {
312  return the_last;
313  }
314 
315  /// returns successor of \p elem in an IsList.
316  /** The successor of \p elem in a list generally corresponds to the
317  element returned by elem->next(). However, if \p elem is the last
318  element in an IsList, this method will return 0, whereas
319  elem->next() may yield an arbitrary value. For example, if the
320  current list is actually a sublist of another, larger IsList,
321  elem->next() returns the successor of \p elem in this larger
322  IsList.
323  */
324  T* next(const T *elem) const
325  {
326  return (elem == the_last) ? 0 : elem->next();
327  }
328 
329  /// returns the number of elements in IsList.
330  int length() const
331  {
332  int num;
333  if (the_first)
334  {
335  T *test = the_first;
336  for (num = 1; test != the_last; test = test->next())
337  ++num;
338  return num;
339  }
340  return 0;
341  }
342 
343  /// returns the position of element \p elem within IsList.
344  int find(const T* elem) const
345  {
346  const T* test;
347 
348  assert(elem != 0);
349 
350  for(test = the_first; test != 0; test = next(test))
351  if (test == elem)
352  return 1;
353 
354  return 0;
355  }
356 
357  /// constructs sublist of an IsList.
358  /** Returns a new IsList containing a sublist of an IsList starting
359  with element \p start and reaching up to element \p end. Both must be
360  members of the IsList or 0, in which case the first and last
361  element are used, respectively.
362  */
363  IsList<T>sublist(const T* start = 0, const T* end = 0) const
364  {
365  IsList<T>part = *this;
366  if (start)
367  {
368  assert(find(start));
369  part.the_first = const_cast<T*>(start);
370  }
371  if (end)
372  {
373  assert(part.find(end));
374  part.the_last = const_cast<T*>(end);
375  }
376  return part;
377  }
378  //@}
379 
380  //--------------------------
381  /**@name Miscellaneous */
382  //@{
383  /// adjusts list pointers to a new memory address.
384  /** This method is of a rather technical nature. If all list elements
385  are taken form one array of elements, in certain circumstances the
386  user may be forced to realloc this array. As a consequence all
387  next() pointers of the list elements would become invalid.
388  However, all addresses will be changed by a constant offset \p delta.
389  Then move( \p delta ) may be called, which adjusts the next()
390  pointers of all elements in the list.
391  */
392  void move(ptrdiff_t delta)
393  {
394  if (the_first)
395  {
396  T* elem;
397  the_last = reinterpret_cast<T*>(reinterpret_cast<char*>(the_last) + delta);
398  the_first = reinterpret_cast<T*>(reinterpret_cast<char*>(the_first) + delta);
399  for (elem = first(); elem; elem = next(elem))
400  if (elem != last())
401  elem->next() = reinterpret_cast<T*>(reinterpret_cast<char*>(elem->next()) + delta);
402  }
403  }
404 
405  /// consistency check.
406  bool isConsistent() const
407  {
408 #ifdef ENABLE_CONSISTENCY_CHECKS
409  if (first() != 0 && last() == 0)
410  return MSGinconsistent("IsList");
411 
412  if (first() == 0 && last() != 0)
413  return MSGinconsistent("IsList");
414 
415  if (first() && find(last()) == 0)
416  return MSGinconsistent("IsList");
417 #endif
418 
419  return true;
420  }
421  //@}
422 
423  //------------------------------------
424  /**@name Constructors / Destructors */
425  //@{
426  /// default constructor.
427  /** The default constructor may be used to setup a (sub-)list, by
428  specifying a \p first and \p last element. Then \p last must be a
429  successor of \p first.
430  */
431  explicit
432  IsList(T* pfirst = 0, T* plast = 0, bool pDestroyElements = false)
433  : the_first(pfirst)
434  , the_last(plast)
435  , destroyElements(pDestroyElements)
436  {
437  if (pfirst)
438  {
439  assert(plast != 0);
440  assert(find(plast));
441  }
442 
443  assert(isConsistent());
444  }
445 
446  /// destructor
448  {
449  clear(destroyElements);
450  }
451  //@}
452 };
453 
454 } // namespace soplex
455 #endif // _ISLIST_H_
void clear(bool pDestroyElements=false)
removes all elements from an IsList.
Definition: islist.h:283
IsElement< T > *& next()
Definition: islist.h:60
~IsList()
destructor
Definition: islist.h:447
T * last() const
returns the IsList&#39;s last element.
Definition: islist.h:310
T * the_last
the last element in the IsList.
Definition: islist.h:116
void move(ptrdiff_t delta)
adjusts list pointers to a new memory address.
Definition: islist.h:392
T * next(const T *elem) const
returns successor of elem in an IsList.
Definition: islist.h:324
IsList< T > sublist(const T *start=0, const T *end=0) const
constructs sublist of an IsList.
Definition: islist.h:363
Generic single linked list.Class IsList implements an intrusive single linked list of elements of a t...
Definition: islist.h:112
IsElement< T > Element
Definition: islist.h:121
int find(const T *elem) const
returns the position of element elem within IsList.
Definition: islist.h:344
IsElement()
default constructor.
Definition: islist.h:76
IsList(T *pfirst=0, T *plast=0, bool pDestroyElements=false)
default constructor.
Definition: islist.h:432
bool destroyElements
should the destructor be called for each element when the list is destroyed?
Definition: islist.h:117
DLPSV *& next()
Next SVectorBase.
Definition: svsetbase.h:117
T * first() const
returns the IsList&#39;s first element.
Definition: islist.h:304
void insert(IsList< T > &list, T *after)
inserts all elements of list after element after of an IsList.
Definition: islist.h:198
void prepend(IsList< T > &list)
prepends all elements of list to IsList.
Definition: islist.h:182
bool isConsistent() const
consistency check.
Definition: islist.h:406
void remove_next(T *after)
removes the successor of after from an IsList.
Definition: islist.h:215
Everything should be within this namespace.
IsElement< T > * the_next
pointer to next element in the IsList.
Definition: islist.h:51
void prepend(T *elem)
prepends elem to IsList.
Definition: islist.h:137
void insert(T *elem, T *after)
inserts elem to IsList after its element after.
Definition: islist.h:147
IsElement(const IsElement< T > &old)
copy constructor.
Definition: islist.h:90
int length() const
returns the number of elements in IsList.
Definition: islist.h:330
IsElement< T > * next() const
returns the next element in the IsList.
Definition: islist.h:65
void append(T *elem)
appends elem to IsList.
Definition: islist.h:127
IsElement(const T &old)
Definition: islist.h:81
T * the_first
the first element in the IsList.
Definition: islist.h:115
void append(IsList< T > &list)
appends all elements of list to IsList.
Definition: islist.h:166
#define MSGinconsistent(name)
Definition: spxdefines.h:121
void spx_free(T &p)
Release memory.
Definition: spxalloc.h:109
Elements for IsLists.Class IsElement allows to easily construct list elements for an intrusive single...
Definition: islist.h:44