00001 00027 // ************************************************************* 00028 // 00029 // Class Chain<C> for implementing double-linked lists 00030 // 03/05/2002 Manchester 00031 // 00032 // ************************************************************* 00033 00034 00035 #ifndef __chain__ 00036 # define __chain__ 00037 00038 00039 #include "Memory.hpp" 00040 #include "Sort.hpp" 00041 00042 00043 // *******************Class Chain******************************* 00044 00045 template <class C,ClassID ID> 00046 class Chain 00047 { 00048 public: 00049 class Link 00050 { 00051 private: 00052 Link* _prev; 00053 Link* _next; 00054 C _elem; 00055 public: 00056 inline Link (C elem) 00057 : _elem (elem) 00058 { 00059 } 00060 00061 inline Link () // for making the header to a chain only 00062 { 00063 _prev = this; 00064 _next = this; 00065 } 00066 00067 inline Link* prev () const { return _prev; } 00068 inline void prev ( Link* p ) { _prev = p; } 00069 inline Link* next () const { return _next; } 00070 inline void next ( Link* n ) { _next = n; } 00071 00072 inline bool less (const Link* lnk) const 00073 { return _elem.less (lnk->_elem); } 00074 00075 void insertAfter (C elem) 00076 { 00077 Link* l = new Link (elem); 00078 l->_prev = this; 00079 l->_next = _next; 00080 _next->_prev = l; 00081 _next = l; 00082 } 00083 00084 void insertBefore (C elem) 00085 { 00086 Link* l = new Link (elem); 00087 l->_next = this; 00088 l->_prev = _prev; 00089 _prev->_next = l; 00090 _prev = l; 00091 } 00092 00093 void del () 00094 { 00095 TRACER( "Chain::del" ); 00096 ASS(_next != this && _prev != this); 00097 00098 _prev->_next = _next; 00099 _next->_prev = _prev; 00100 delete this; 00101 } 00102 00103 const C& content () const { return _elem; } 00104 }; // Class Chain::Link 00105 00106 // I had to make this public since VC++ ignores my declaration of DelIterator as friend 00107 inline const Link* header () const { return &_header; } 00108 00109 // Chain public members 00110 inline void addLast (C elem) 00111 { _header.insertBefore (elem); } 00112 00113 inline void addFirst (C elem) 00114 { _header.insertAfter (elem); } 00115 00116 inline void delLast () 00117 { _header.prev()->del(); } 00118 00119 void delFirst () 00120 { _header.next()->del(); } 00121 00122 inline bool isEmpty () const 00123 { return _header.prev() == &_header; } 00124 00125 Link* first () const 00126 { ASS(! isEmpty()); 00127 return _header.next(); } 00128 00129 C last () const 00130 { ASS(! isEmpty()); 00131 return _header.prev(); } 00132 00133 void sort () // sort links using the less function on C 00134 { 00135 int len = length (); 00136 Sort<Link*> srt (len); 00137 00138 for (Link* lnk = _header.next (); 00139 lnk != &_header; 00140 lnk = lnk->next () ) { 00141 srt.add (lnk); 00142 } 00143 00144 // sort the chain using the comparison function less () 00145 srt.sortF (); 00146 00147 // sort now contains a sorted array of links 00148 // insert them one by one to the chain 00149 Link* last = &_header; // the last link 00150 for (int i = len - 1; i >= 0; i--) { 00151 Link* nxt = srt[i]; 00152 // remove nxt from the chain 00153 nxt->prev()->next (nxt->next()); 00154 nxt->next()->prev (nxt->prev()); 00155 // insert before the last link 00156 nxt->next (last); 00157 nxt->prev (last->prev()); 00158 nxt->prev()->next (nxt); 00159 last->prev (nxt); 00160 last = nxt; 00161 } 00162 } 00163 00164 int length () const 00165 { int len = 0; 00166 Iterator links (*this); 00167 while (links.more()) { 00168 links.next (); 00169 len ++; 00170 } 00171 return len; 00172 } // length () 00173 00174 00175 class Iterator { 00176 public: 00177 inline explicit 00178 Iterator (Chain& c) 00179 : _header (c.header()), 00180 _current (_header->next()) 00181 {} 00182 Iterator (const Chain& c) 00183 : _header (c.header()), 00184 _current (_header->next()) 00185 {} 00186 00187 inline 00188 bool more () 00189 { return _header != _current; } 00190 00191 inline 00192 C next () 00193 { ASS(more()); 00194 00195 C result = _current->content(); 00196 _current = _current->next(); 00197 00198 return result; 00199 } 00200 00201 private: 00202 const Link* _header; 00203 Link* _current; 00204 }; 00205 00206 class DelIterator { 00207 public: 00208 00209 inline 00210 DelIterator ( Chain& c ) : 00211 _header ( c.header() ), 00212 _current ( _header->next() ) 00213 {} 00214 00215 inline 00216 bool more () 00217 { return _header != _current; } 00218 00219 inline 00220 C next () 00221 { 00222 ASS(_current != _header); 00223 00224 C result = _current->content(); 00225 _current = _current->next(); 00226 return result; 00227 } 00228 00229 inline 00230 void del () 00231 { 00232 ASS( _current->prev() != _header ); 00233 00234 _current->prev()->del(); 00235 } 00236 00237 // 07/05/2002 Manchester 00238 inline 00239 void replace (C elem) 00240 { 00241 ASS( _current->prev() != _header ); 00242 00243 _current->prev()->del(); 00244 _current->insertBefore (elem); 00245 } 00246 00247 private: 00248 const Link* _header; 00249 Link* _current; 00250 }; 00251 00252 private: 00253 Link _header; 00254 00255 friend class Iterator; 00256 }; // class Chain 00257 00258 00259 #endif 00260 00261