Main Page   Class Hierarchy   Compound List   File List   Compound Members   File Members  

linklist.H

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

Generated on Mon Sep 15 16:25:56 2003 for gluebase by doxygen1.2.18