Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

linklist.H

Go to the documentation of this file.
00001 
00002 
00003 /****************************************************************/
00004 /*    NAME: Scott Klemmer                                       */
00005 /*    ACCT: srk                                                 */
00006 /*    FILE: linklist.H                                          */
00007 /*    DATE: Wed Apr  7 19:51:04 1999                            */
00008 /****************************************************************/
00009 
00010 
00011 
00012 #ifndef LINKLIST_HEADER
00013 #define LINKLIST_HEADER
00014 
00015 /* The link list has a delimiter node _bound which, as in STL, functions
00016    as both the head and tail. Calling begin() on a non-empty list returns the
00017    first valid node. Calling end() returns the delimiter node.  For this
00018    reason, it often makes sense to compare to end() to check whether we've hit
00019    the end of the list. Iterator compare is overriden to memory compare the
00020    nodes, so if end() and another iterator evaluate to equal, it's hit the end
00021    of the list.
00022 */
00023 
00024 template <class T>
00025 class LINKLIST {
00026  public:
00027    class Iterator;
00028    friend class Iterator;
00029    
00030  protected:
00031    struct Node;
00032    friend struct Node;
00033 
00034 // to get an Iterator from outside the LINKLIST class, it's necessary to
00035 // preface Iterator with LINKLIST:
00036 // e.g. LINKLIST<int>::Iterator iter = my_list.insert(begin(), 7);
00037 
00038  public:
00039    class Iterator {
00040     protected:
00041       friend class LINKLIST<T>;
00042       Node* _node;
00043       bool _reverse; //false(0) means forward, true(!0) means reverse
00044             
00045          
00046     public:
00047 
00048       Iterator() : _node(0) {};
00049       Iterator(Node* n, bool rev=0) : _node(n), _reverse(rev) {};
00050 
00051       Iterator(const Iterator& iter) : _node(iter._node), _reverse(iter._reverse) {}
00052 
00053       bool is_reverse() const { return _reverse; }
00054       
00055       bool operator==(const Iterator& iter) const {
00056          return _node == iter._node;
00057       }
00058     
00059       bool operator!=(const Iterator& iter) const {
00060          return _node != iter._node;
00061       }
00062     
00063       Iterator& operator++() {
00064          _node = _reverse ? _node->prev : _node->next;
00065          return *this;
00066       }     
00067 
00068       
00069       Iterator operator++(int) {
00070          Iterator tmp = *this;
00071          ++*this;
00072          return tmp;
00073       }     
00074       
00075       
00076       Iterator& operator--() {
00077          _node = _reverse ? _node->next : _node->prev;
00078          return *this;
00079       }  
00080 
00081 
00082       Iterator operator--(int) {
00083          Iterator tmp = *this;
00084          --*this;
00085          return tmp;
00086       }     
00087 
00088       
00089       const T& operator*() const { return _node->data; }
00090 
00091       T& operator*()  { return _node->data; }
00092 
00093    
00094       Iterator& next() {
00095          return ++(*this);
00096       }         
00097 
00098          
00099       Iterator& prev() {   
00100          return --(*this);
00101       } 
00102    };
00103 
00104 
00105 
00106  protected:
00107    int _length;
00108    Node* _bound;
00109 
00110  public:
00111    LINKLIST() {
00112       _bound = new Node();
00113       _bound->next = _bound;
00114       _bound->prev = _bound;
00115       _length = 0;
00116    }
00117 
00118    LINKLIST(const LINKLIST<T>& l) {
00119       *this = l;
00120    }
00121 
00122    const LINKLIST<T>& operator=(const LINKLIST<T>& right) {
00123       clear();
00124       Iterator iter = right.begin();
00125       while ( iter != right.end() )
00126          insert(*iter++);
00127 
00128       return *this;
00129    }
00130 
00131     
00132    Iterator insert_before(Iterator position, const T& data) {
00133       Node* tmp = new Node();
00134       tmp->data = data;
00135       tmp->next = position._node;
00136       tmp->prev = (position._node)->prev;
00137       (tmp->prev)->next = tmp;
00138       (position._node)->prev = tmp;
00139       ++_length;
00140       return tmp;
00141    }
00142 
00143    Iterator insert_after(Iterator position, const T& data) { 
00144       Node* tmp = new Node();
00145       tmp->data = data;
00146       tmp->next = (position._node)->next;
00147       tmp->prev = position._node;
00148       (position._node)->next = tmp;
00149       (tmp->next)->prev = tmp;
00150       ++_length;
00151       return tmp;
00152    }
00153 
00154 
00155    Iterator insert(Iterator position, const T& data) { // equivalent to insert_before
00156       return insert_before(position, data);
00157    }
00158 
00159 
00160    Iterator insert(const T& data) { // equivalent to insert_before
00161       return insert_before(begin(), data);
00162    }
00163 
00164    /* erase automatically deletes the erasure node, but the user is responsible
00165       for handling the data. does not allow end node to be deleted.
00166       Returns an Iterator pointing to the element before erasure
00167       */
00168    
00169    Iterator erase(Iterator position) {
00170       Iterator new_position = position;
00171 
00172       if ( position._node != _bound ) {
00173 
00174          (*(*position._node).prev).next = (*position._node).next;
00175          (*(*position._node).next).prev = (*position._node).prev;
00176          Node* to_go = position._node;
00177          --new_position;
00178          delete to_go;
00179          --_length;
00180       }
00181 
00182       return new_position;
00183    }
00184 
00185    const T& front() const { return *(begin()); }
00186    T&       front()       { return *(begin()); }
00187    const T& back() const { return *(--end()); }
00188    T&       back()       { return *(--end()); }
00189 
00190    Iterator begin() const { return _bound->next; }
00191 
00192    Iterator end() const { return _bound; }
00193     
00194    Iterator rbegin() const {
00195       return Iterator(_bound->prev,1); //the 1 makes it a reverse iterator
00196    }
00197 
00198     
00199    // get_iterator_at calls the 1st valid element 0
00200    // so, to get the 4th element in a list, call get_element_at 3
00201    Iterator get_iterator_at(int index) const {
00202       Iterator iter = begin();
00203 
00204       if (index>=_length) return end();
00205       
00206       for (int i=0; i<index; i++) ++iter;
00207 
00208       return iter;
00209    }
00210 
00211     
00212    Iterator rget_iterator_at(int index) const {
00213       Iterator iter = rbegin();
00214          
00215       if (index>=_length) return end();
00216 
00217       for (int i=0; i<index; i++) ++iter;
00218 
00219       return iter;
00220    }
00221 
00222     
00223    Iterator push_front(const T& data) { return insert(begin(), data); }
00224     
00225    Iterator push_back(const T& data)  { return insert(end(), data); }
00226 
00227 
00228    T pop_front() {
00229       T data = _bound->next->data;
00230       if ( _bound->next != _bound ) erase( begin() );
00231       return data;
00232    }
00233 
00234 
00235    T pop_back() {
00236       T data = _bound->prev->data;
00237       erase( --end() );
00238       return data;
00239    }
00240 
00241 
00242 
00243    void swap(Iterator pos1, Iterator pos2) {
00244       Node* node1 = pos1._node;
00245       Node* node2 = pos2._node;
00246 
00247       Node* prev1 = node1->prev;
00248       Node* next1 = node1->next;
00249 
00250       node1->prev = node2->prev;
00251       node1->next = node2->next;
00252 
00253       node2->prev->next = node1;
00254       node2->next->prev = node1;
00255 
00256       node2->prev = prev1;
00257       node2->next = next1;
00258 
00259       prev1->next = node2;
00260       next1->prev = node2;
00261 }
00262 
00263    
00264    Iterator find(const T& data) {
00265       Iterator iter = begin();
00266       while ( iter._node != _bound ) {
00267          if ( *iter == data ) return iter;
00268          ++iter;
00269       }
00270       return _bound; 
00271    }
00272 
00273    void clear() {
00274       while(!empty())
00275          erase(--end());
00276    }
00277    
00278    bool empty() const { return _length == 0; }
00279 
00280    int size() { return _length; }
00281    int num() { return _length; }
00282 
00283    void reverse() { Node* cur = _bound; do {
00284       Node* temp = cur->next;
00285       cur->next = cur->prev;
00286       cur->prev = temp;
00287       cur = cur->next;
00288    } while (cur != _bound);
00289    }
00290    
00291    int operator ==(const LINKLIST<T> &) {
00292       cerr << "Warning - dummy LINKLIST<T>::operator== called" << endl;
00293       return 0;
00294    }
00295     
00296  protected:
00297    struct Node {
00298       Node* prev;
00299       Node* next;
00300       T data;
00301    };
00302 
00303     
00304 };
00305 
00306 #endif  //LINKLIST_HEADER

Generated on Mon Sep 18 11:39:32 2006 for jot by  doxygen 1.4.4