STL - Untermenge Von STL-Container "List"



  • Hallo,

    So, es geht um folgendes:

    ich muss leider STL Conteiner-Klasse "List" selbst implementieren als z.B. mit der Name "Clist" und muss selber alle memberfunktion

    · list::assign
    · list::back
    · list::begin
    · list::clear
    · list::empty
    · list::end
    · list::erase
    · list::front
    · list::get_allocator
    · list::insert
    · list::max_size
    · list::merge
    · list::operator=
    · list::pop_back
    · list::pop_front
    · list::push_back
    · list::push_front
    · list::rbegin
    · list::remove
    · list::remove_if
    · list::rend
    · list::resize
    · list::reverse
    · list::size
    · list::sort
    · list::splice
    · list::swap
    · list::unique

    implementieren. Kann jemand mir vielleicht helfen, ob es dafür eine Quelle gibt oder eine Idee vielleicht, wie ich diese Aufgabe lösen kann?? Die Aufgaben von Funktionen sind schon klar. Aber selbst implementieren kann ich leider nicht 😞

    Noch mal meine Aufgabe:

    list::unique() -> Clist:unique()

    usw. für alle member Funktionen(oben) von STL Containerklasse "List".

    Viele Grüße

    Strong



  • die Implementierungen kannst du alle hier nachlesen:
    http://www.cplusplus.com/reference/algorithm



  • Die sind die Algorithmen. Ich brauche die Implementierung von Member Fuktionen von Klasse List.



  • // +---------------------------------------------------------------------------
    // +  Datei: SWE3/2007.07/rotate/Clist.hpp
    // +  AutorIn: 
    // +  Beschreibung: Die Schnittstelle zu Clist<T>
    // +  Revision: 2007/06/22
    // +---------------------------------------------------------------------------
    #if !defined(Clist_hpp) 
      #define Clist_hpp
    
    // --- Zusätzliche Deklarationen
    #include <cstddef>
    #include <iterator>  // für std::bidirectional_iterator_tag
    
    // +---------------------------------------------------------------------------
    // +  namespace swe3
    // +  
    // +---------------------------------------------------------------------------
    namespace swe3 {
    
    // +---------------------------------------------------------------------------
    // +  Vorwärtsdeklaration der Listenelemente - als Schablone.
    // +  
    // +---------------------------------------------------------------------------
    template <typename T> class ClistElem;
    
    // +---------------------------------------------------------------------------
    // +  Clist<T> - eine funktionelle Untermenge von std::list<T>
    // +  2007/06/12
    // +---------------------------------------------------------------------------
    template <typename T>
    class Clist {
      public:
        // Die STL Typen - neu
        typedef T value_type;
        typedef value_type *pointer;
        typedef value_type const *const_pointer;
        typedef value_type &reference;
        typedef value_type const &const_reference;
        typedef std::ptrdiff_t difference_type;
        typedef std::size_t size_type;
        typedef void reverse_iterator;        // nicht definiert
        typedef void const_reverse_iterator;  // nicht definiert
        typedef void allocator;               // nicht definiert
    
        // iterator
        class iterator {
          public:
            // Die STL Typen - neu
            typedef typename Clist<T>::value_type value_type;
            typedef typename Clist<T>::pointer pointer;
            typedef typename Clist<T>::reference reference;
            typedef typename Clist<T>::difference_type difference_type;
            typedef std::bidirectional_iterator_tag iterator_category;
    
            // Kon- und Destruktoren
            iterator() throw();
            iterator(iterator const&) throw();
            ~iterator() throw();
    
            // In- und Dekrement-Operatoren
            iterator& operator++() throw();      // Präfix
            iterator operator++(int) throw();    // Postfix
            iterator& operator--() throw();
            iterator operator--(int) throw();
    
            // Zuweisungsoperator
            iterator& operator=(iterator const&) throw();
    
            // Vergleichsoperatoren
            bool operator==(iterator const&) const throw();
            bool operator!=(iterator const&) const throw();
    
            // Zugriff auf die Elemente im Vektor
            T &operator*();
            T *operator->();
    
          private:
            ClistElem<T> *prev_, *current_, *next_;
          friend class Clist<T>;
        };
    
        // const_iterator
        class const_iterator {
          public:
            // Die STL Typen - neu
            typedef typename Clist<T>::value_type const value_type;
            typedef typename Clist<T>::const_pointer pointer;
            typedef typename Clist<T>::const_reference reference;
            typedef typename Clist<T>::difference_type difference_type;
            typedef std::bidirectional_iterator_tag iterator_category;
    
            // Kon- und Destruktoren
            const_iterator() throw();
            const_iterator(const_iterator const&) throw();
            const_iterator(iterator const&) throw();
            ~const_iterator() throw();
    
            // In- und Dekrement-Operatoren
            const_iterator& operator++() throw();      // Präfix
            const_iterator operator++(int) throw();    // Postfix
            const_iterator& operator--() throw();
            const_iterator operator--(int) throw();
    
            // Zuweisungsoperator
            const_iterator& operator=(const_iterator const&) throw();
    
            // Vergleichsoperatoren
            bool operator==(const_iterator const&) const throw();
            bool operator!=(const_iterator const&) const throw();
    
            // Zugriff auf die Elemente im Vektor
            T const &operator*() const;
            T const *operator->() const;
    
          private:
            ClistElem<T> *prev_, *current_, *next_;
          friend class Clist<T>;
        };
    
        // Kon- und Destruktoren
        Clist() throw();
        Clist(Clist<T> const&);
        Clist(size_type, T const &);
        ~Clist();
    
        // Den Zustand abfragen
        size_t size() const throw();
        bool empty() const throw();
    
        // Elemente einfügen, löschen (die "modifiers")
        void push_back(T const&);
        void pop_back();
        void push_front(T const&);
        void pop_front();
        iterator insert(iterator position, T const&);
        void insert(iterator position, size_type, T const&);
        iterator erase(iterator position);
        iterator erase(iterator first, iterator last);
        void clear();
    
        // Zugriff auf einzelne Elemente (kein wahlfreier Zugriff)
        T &front();
        T const &front() const;
        T &back();
        T const &back() const;
    
        // Operationen auf ganzen Listen - neu mit sort
        Clist<T>& operator=(Clist<T> const &);
        void swap(Clist<T>&) throw();
        // Die speziellen Sortieralgorithmen für Clist<T>
        //   die zweite Form als sogenannte Methoden-Schablone
        //   (member template)
        void sort();
        template <typename Compare> void sort(Compare);
    
        // begin, end
        iterator begin() throw();
        const_iterator begin() const throw();
        iterator end() throw();
        const_iterator end() const throw();
    
      private:
        // Die Datenelemente
        ClistElem<T> *head_, *tail_;
        size_type size_;
        // Hilfsmethoden
        void del_();
    };
    
    // +---------------------------------------------------------------------------
    // +  void Clist<T>::sort(char const *) - Spezialisierung für nullterminierte
    // +    Zeichenketten.
    // +  
    // +---------------------------------------------------------------------------
    template < >
    void Clist<char const *>::sort();
    
    // +---------------------------------------------------------------------------
    // +  ClistElem<T> - die Listenelemente einer doppelt verketteten Liste mit
    // +    Anker. Hier definiert für Zugriff durch den Testtreiber.
    // +  2007/05/09
    // +---------------------------------------------------------------------------
    template <typename T>
    class ClistElem {
      private:
        // Elemente anlegen nur für "friends"
        explicit ClistElem(T const & =T());
    
      private:
        // Die Datenelemente
        ClistElem<T> *prev_, *next_; T value_;
        // Hilfsfunktionen
        void link_(ClistElem<T> *, bool append =true) throw();
        void link_(ClistElem<T> *, ClistElem<T> *, bool append=true) throw();
        void unlink_() throw();
        void unlink_(ClistElem<T> *) throw();
    
      private:  // Keine Kopien
        ClistElem(const ClistElem<T>&);
        ClistElem<T>& operator=(const ClistElem<T>&);
      friend class Clist<T>; friend class Clist<T>::iterator;
      friend class Clist<T>::const_iterator;
    };
    
    // +---------------------------------------------------------------------------
    // +  operator==(Clist<T> const&, Clist<T> const&)
    // +    externer Operator entsprechend den STL Gepflogenheiten
    // +  ------------------------------------------------------------------------
    template <typename T>
    inline bool operator==(Clist<T> const &a, Clist<T> const &b) {
      if (a.size() != b.size()) return false;
      typename Clist<T>::const_iterator aiter(a.begin()), biter(b.begin());
      for( ; aiter!=a.end() && biter!=b.end() && *aiter==*biter; ++aiter, ++biter);
      return aiter==a.end() && biter==b.end();
    }
    
    // +---------------------------------------------------------------------------
    // +  operator!=(Clist<T> const&, Clist<T> const&)
    // +    externer Operator entsprechend den STL Gepflogenheiten
    // +  
    // +---------------------------------------------------------------------------
    template <typename T>
    inline bool operator!=(Clist<T> const &a, Clist<T> const &b) {
      return !(a==b);
    }
    
    } // namespace
    
    // --- Die Implementierungsdatei einbinden ------------------------------------
    #include "Clist.cpp"
    //
    #endif
    //
    //  Ende der Datei
    //
    


  • //+---------------------------------------------------------------------------
    //+  Datei: SWE3/Clist.cpp
    //+  
    //+  Beschreibung: Implementierung der Klassenschablone Clist<T> als
    //+    Untermenge von std::list<T>.
    //+  KorrektorIn:
    //+   
    //+  Revision:  - Details am Ende der Datei
    //+---------------------------------------------------------------------------
    #if !defined(Clist_cpp) 
      #define Clist_cpp
    
    #include <cstddef>
    #include <stdexcept>
    #include "Clist.hpp"
    
    // --- using directives
    using namespace std;
    
    // +---------------------------------------------------------------------------
    // +  namespace swe3
    // +  
    // +---------------------------------------------------------------------------
    namespace swe3 {
    
    // +---------------------------------------------------------------------------
    // +  Clist::Clist() - Standardkonstruktor
    // +  , 20.12.2007
    // +---------------------------------------------------------------------------
    template <typename T>
    Clist<T>::Clist() throw() : head_(0), tail_(0), size_(0) {}
    
    // +---------------------------------------------------------------------------
    // +  Clist<T>::Clist(Clist const&) - Kopierkonstruktor; wird vom Zuweisungs-
    // +    operator benutzt zur einfacheren Gewährleistung der "exception 
    // +    safety" - es wird eine vollständige Kopie erzeugt oder nur ein
    // +    leeres Objekt. Auftretende Ausnahmen werden weitergereicht.
    // +  , 20.12.2007
    // +---------------------------------------------------------------------------
    template <typename T>
    Clist<T>::Clist(Clist<T> const & list )  : head_( 0 ), tail_( 0 ), size_( 0 ) {
    
      //Liste leer?
      if( list.empty() ) 
    	return;
      //Wenn Objekt gleiche ist, muss nichts getan werden. 
      if( this == &list ) 
        return; 
    
      try{
        for(ClistElem<T> *elem=list.head_; elem ; elem=elem->next_) 
          push_back(elem->value_);
      }catch(...) { del_(); throw("Kopierkonstruktor\n"); }
    }
    
    // +---------------------------------------------------------------------------
    // +  Clist<T>::Clist(size_t n, T const &s) - neue Liste mit n gleichen 
    // +    Elementen. Exception safety wie beim Kopierkonstruktor: Es wird
    // +    eine vollständige Liste mit n Elementen angelegt oder eine leere
    // +    Liste. Auftretende Ausnahmen werden weitergereicht.
    // +  , 20.12.2007
    // +---------------------------------------------------------------------------
    template <typename T>
    Clist<T>::Clist(std::size_t n, T const & s ): head_( 0 ), tail_( 0 ), size_( 0 ) {
    
      //Wenn n null ist
      if( !n ) 
    	return;
      try{
        for(size_t i=0; i<n; ++i)
    	  push_back(s);
      }catch(...) { del_(); throw("Clist(size_t n, T const &s)\n"); }
    }
    // +---------------------------------------------------------------------------
    // +  Clist<T>::~Clist() - Destruktor - wirft keine Ausnahmen, falls ~T keine
    // +    Ausnahmen wirft.
    // +  , 20.12.2007
    // +---------------------------------------------------------------------------
    template <typename T>
    Clist<T>::~Clist() {
    
      //Destruktor ruft Funktion clear() auf 
      clear();	
    }
    
    // +---------------------------------------------------------------------------
    // +  Clist<T>::size() const throw() - liefert die Anzahl enthaltener Elemente
    // +  , 20.12.2007
    // +---------------------------------------------------------------------------
    template <typename T>
    size_t Clist<T>::size() const throw() { 
    
      //Anzahl von Elementen der Listen zurückgeben
      return size_; 
    } 
    
    // +---------------------------------------------------------------------------
    // +  Clist<T>::empty() const throw() - liefert true, falls die Liste leer
    // +    ist, sonst false,
    // +  , 20.12.2007
    // +---------------------------------------------------------------------------
    template <typename T>
    bool Clist<T>::empty() const throw() {
    
      return !size_; 
    } 
    
    // +---------------------------------------------------------------------------
    // +  Clist<T>::push_back(T const&) - neues Element am Ende einfügen
    // +    Exception safe: Einfügen oder die Liste unverändert lassen.
    // +    Die Funktion kann bei Mangel an freiem Speicher Ausnahmen werfen,
    // +    bzw. falls der T Konstruktor eine Ausnahme wirft.
    // +  , 20.12.2007
    // +---------------------------------------------------------------------------
    template <typename T>
    void Clist<T>::push_back(T const & s) {
    
      //dynamisch (mit *elem new ClistElem<T>(s)) erzeugen
      ClistElem<T> *elem = new ClistElem<T>( s ); 
      //Wenn es Speicherplatz nicht gibt
      if( !elem ) 
        throw bad_alloc();
      //Wenn noch kein Element eingefügt
      if( !head_ )
      //zeigt head auf das erste Element  
    	head_ = elem; 
      else
      //das neue Element mit dem letzten Element (tail) verlinken (link_(elem))
      	tail_->link_( elem );
      //Tail zeigt auf auf das neue Element
      tail_ = elem; 
      //Size eins erhoehen, da ein Element mehr in der Liste
      ++size_;		
    } 
    
    // +---------------------------------------------------------------------------
    // +  Clist<T>::pop_back() - das Element am aktuellen Ende löschen.
    // +    Die Funktion wirft keine Ausnahmen, falls ~T keine wirft.
    // +  , 20.12.2007
    // +---------------------------------------------------------------------------
    template <typename T>
    void Clist<T>::pop_back() {
    
      //Wenn tail nichts zeigt,
      if( !tail_ ) 
    	throw out_of_range("pop_back()-Clist ist leer");
      //Neue ClistElem initialisieren mit tail-prev 
      ClistElem<T> *letzte =  tail_->prev_; 
      //Letze Element muss aus der Liste unlinken
      tail_->unlink_(); 
      //tail zeigt auf letzte
      tail_ = letzte;
      //Wenn tail =0, dann head ist auch =0
      if( !tail_ )  
        head_ = 0;  
      //Size eins erniedrigen, da ein Element weniger in der Liste
      --size_;
    }
    
    // +---------------------------------------------------------------------------
    // +  Clist<T>::push_front(T const&) - neues Element am Anfang einfügen
    // +    Exception safe: Einfügen oder die Liste unverändert lassen.
    // +    Die Funktion kann bei Mangel an freiem Speicher Ausnahmen werfen,
    // +    bzw. falls der T Konstruktor eine Ausnahme wirft (vgl. push_back).
    // +  , 20.12.2007
    // +---------------------------------------------------------------------------
    template <typename T>
    void Clist<T>::push_front(T const&s) {
    
      //dynamisch (mit *elem new ClistElem<T>(s)) erzeugen
      ClistElem<T> *elem = new ClistElem<T>( s );
      //Wenn es Speicherplatz nicht zur Verfuegung steht
      if( !elem ) 
    	throw bad_alloc();
      //Wenn noch kein Element eingefügt
      if( !head_ )
      {
         //zeigt head auf das erste Element
         head_ = elem;	
         //tail ist head
         tail_ = head_; 
      }
        else 
        //ansonsten vor head_ linken deswegen 2.Parameter false
         head_->link_( elem, false );	
    
      //Neues head_ ist elem
      head_ = elem; 
      //Size eins erhoehen, da ein Element mehr in der Liste
      ++size_;
    }
    
    // +---------------------------------------------------------------------------
    // +  Clist<T>::pop_front() - das Element am aktuellen Anfang löschen.
    // +    Die Funktion wirft keine Ausnahmen, falls ~T keine wirft.
    // +  , 20.12.2007
    // +---------------------------------------------------------------------------
    template <typename T>
    void Clist<T>::pop_front() {
    
      //Wenn head nichts zeigt, 
      if( !head_ ) 
    	throw out_of_range("pop_front() CList is empty \n");
      //Neue ClistElem initialisieren mit head->next
      ClistElem<T> *erste =  head_->next_;
      //Letze Element muss aus der Liste unlinken
      head_->unlink_();
      //head mit erste zuweisen
      head_ = erste;
      //wenn head nichts zeigt, dann tail ist 0
      if( !head_ ) 
    	tail_ = 0;
      //Size eins erniedrigen, da ein Element weniger in der Liste
      --size_;
    }
    
    // +---------------------------------------------------------------------------
    // +  Clist<T>::insert(iterator pos, T const &t) - ein Element einfügen
    // +    vor pos. Gibt einen Iterator zum neu eingefügten Element zurück.
    // +    Exception safe: Einfügen oder die Liste unverändert lassen.
    // +    Die Funktion kann bei Mangel an freiem Speicher Ausnahmen werfen,
    // +    bzw. falls der T Konstruktor eine Ausnahme wirft (wie push_back).
    // +  , 20.12.2007
    // +---------------------------------------------------------------------------
    template <typename T>
    typename Clist<T>::iterator Clist<T>::insert(Clist<T>::iterator pos, T const & t) {
    
      if( !pos.prev_ && !pos.next_ && pos.current_ != head_ ){
        return typename Clist<T>::iterator(); 
      }
    
      //Überprüfen, ob pos == begin() 
      if (pos==begin()){
        insert(pos, 1, t); 
    	return begin(); 
      }
    
      //Überprüfen, ob pos == end() 
      if( pos==end() ){ 
        insert(pos, 1, t); 
    	return (--end());
      }
      //Wenn in die Mitte der Liste
      else {
        insert(pos, 1, t); 
        typename Clist<T>::iterator iter;
        iter.prev_ = pos.prev_; 
        iter.current_ = pos.current_->prev_;  
        iter.next_ = pos.current_;
        return iter; 
      }
    
    }
    
    // +---------------------------------------------------------------------------
    // +  Clist<T>::insert(iterator pos, size_type n, T const &t) - n neue
    // +    Element mit Wert t vor pos einfügen.
    // +    Exception safe: Einfügen oder die Liste unverändert lassen.
    // +    Die Funktion kann bei Mangel an freiem Speicher Ausnahmen werfen,
    // +    bzw. falls der T Konstruktor eine Ausnahme wirft (wie insert).
    // +  , 20.12.2007
    // +---------------------------------------------------------------------------
    template <typename T>
    void Clist<T>::insert(iterator pos, size_type n, T const & t) {
    
      //Wenn n = 0 ist, muss nichts zurückgeben
      if (!n) return; 
      //Temporaer Clist Element erzeugen durch Clist<T> tmp(n,t)
      Clist<T> temp(n, t); 
      //Wenn aktuelle Element->empty() 
      if (this->empty()) {
        *this = temp; 
        return; 
      }
      //Wenn pos == begin() 
      if (pos == begin()) {
        pos.current_->link_(temp.head_, temp.tail_, false); 
        head_ = temp.head_; 
      }
      //Wenn pos == end()
      else if (pos == end()) {
        pos.prev_->link_(temp.head_, temp.tail_, true);
        tail_ = temp.tail_;
      }
       else 
         pos.current_->link_(temp.head_, temp.tail_, false);
      //size muss n mal erhöht werden
      size_ = n + size_; 
      //Temporaer Objekt loeschen(head, tail, size) 
      temp.head_ = temp.tail_ =  0; temp.size_ = 0; 
    }
    
    // +---------------------------------------------------------------------------
    // +  Clist<T>::erase(iterator pos) - das Element beim Iterator pos löschen.
    // +   Rückgabewert ist ein Iterator zum ersten Element nach pos, end() falls
    // +   das Element am Ende der Liste gelöscht wurde (pos==--end()).
    // +    Die Funktion wirft keine Ausnahmen, falls ~T keine wirft.
    // +  , 20.12.2007
    // +---------------------------------------------------------------------------
    template <typename T>
    typename Clist<T>::iterator Clist<T>::erase(iterator pos) {
    
      if( !pos.prev_ && !pos.next_ && pos.current_ != head_ ){
        return typename Clist<T>::iterator(); 
      }
      if( (pos==--begin()) || (pos==end()) )
        return typename Clist<T>::iterator();
    
      //Am Anfang der Liste kann pop_front() verwendet werden 
      //Vorteil: pop_front() setzt auch den head_ Zeiger entsprechend 
      //bzw. passt die Groesse an
      if( pos == begin() ) {
        pop_front(); 
        return begin(); 
      }
      //Am Ende der Liste kann pop_back() verwendet werden
      //Vorteil: pop_back() setzt auch den tail_ Zeiger entsprechend 
      //bzw. passt die Groesse an
      if( pos == --end() ) {
        pop_back(); 
        return end(); 
      }
    
      //Wenn es nicht zu loeschen ist, dann leere Iterator zurück
    
      //irgendwo in der Mitte der Liste loeschen -> unlink_() Funktion 
      //für ein Element der Liste 
      else {
        typename Clist<T>::iterator iter; 
        iter.prev_ = pos.prev_; 
        iter.current_ = pos.next_; 
        iter.next_= pos.next_->next_; 
    	//pos.current unlinken
        pos.current_->unlink_();
    	//Size eins erniedrigen, da ein Element weniger in der Liste
        --size_; 
        return iter; 
      }
    }
    
    // +---------------------------------------------------------------------------
    // +  Clist<T>::erase(iterator first, iterator last) - die Elemente im Inter-
    // +    vall [frst,lst) löschen. Rückgabewert ist ein Iterator zum ersten
    // +    Element nach den gelöschten Elementen, end() falls auch das Element
    // +    am Ende der Liste gelöscht wurde (last==end()).
    // +    Die Funktion wirft keine Ausnahmen, falls ~T keine wirft.
    // +  , 20.12.2007
    // +---------------------------------------------------------------------------
    template <typename T>
    typename Clist<T>::iterator Clist<T>::erase(iterator first, iterator last) {
      //Wenn first ist gleich last ist, dann last zurückgeben
      if (first==last) return last;
      //2 ClistElem<T> temporaer element erzeugen und erste mit first.current, 
      //zweite mit last.prev_ initialisieren
      ClistElem<T> *p(first.current_), *q(last.prev_);
      // head_, tail_
      if (head_==p) head_=q->next_;
      if (tail_==q) tail_=p->prev_;
    
      // Aushaengen
      p->unlink_(q);
    
      // garbage collection
      q->next_ = 0;
      size_t anz(0);
      ClistElem<T> *n(p->next_);
      while (p) {
        ++anz;
        delete p; p=n; n=(n)?n->next_:0;
      }
    
      //size ist size - anz
      size_ -= anz;    
    
      //Rueckgabewert ist iterator
      typename Clist<T>::iterator iter;
      iter.current_ = last.current_; iter.next_ = last.next_;
      iter.prev_=first.prev_;
    
      return iter;
    
    }
    
    // +---------------------------------------------------------------------------
    // +  Clist<T>::clear - alles löschen. Die Funktion wirft keine Ausnahmen, 
    // +    falls ~T keine wirft.
    // +  , 20.12.2007
    // +---------------------------------------------------------------------------
    template <typename T>
    void Clist<T>::clear(){
      //Solange tail_ darauf zeigt, durch pop_back() von hinten
      while(tail_)
        pop_back();
    }
    
    // +---------------------------------------------------------------------------
    // +  Clist<T>::front() - Zugriff zum ersten Element
    // +  , 20.12.2007
    // +---------------------------------------------------------------------------
    template <typename T>
    T& Clist<T>::front(){ 
      if(!head_) throw("Front"); 
      return head_->value_; 
    
    }
    
    // +---------------------------------------------------------------------------
    // +  Clist<T>::front() const - Zugriff zum ersten Element
    // +  , 20.12.2007
    // +---------------------------------------------------------------------------
    template <typename T>
    const T& Clist<T>::front() const {
      if(!head_) throw("Front");
      return head_->value_; 
    }
    
    // +---------------------------------------------------------------------------
    // +  Clist<T>::back() - Zugriff zum letzten Element
    // +  , 20.12.2007
    // +---------------------------------------------------------------------------
    template <typename T>
    T& Clist<T>::back(){
      if(!tail_) throw("Front");	
      return tail_->value_;
    
    }
    
    // +---------------------------------------------------------------------------
    // +  Clist<T>::back() const - Zugriff zum letzten Element
    // +  , 20.12.2007
    // +---------------------------------------------------------------------------
    template <typename T>
    const T& Clist<T>::back() const {
      if(!tail_) throw("Front");
      return tail_->value_; 
    
    }
    
    // +---------------------------------------------------------------------------
    // +  Clist<T>::operator=(Clist const&) - Zuweisungsoperator. 
    // +    Exception safe: Die Zuweisung wird vollständig durchgeführt, oder
    // +    die Zielliste (lvalue) wird nicht verändert. Auftretende Ausnahmen
    // +    werden weitergegeben.
    // +  , 20.12.2007
    // +---------------------------------------------------------------------------
    template <typename T>
    Clist<T>& Clist<T>::operator=(Clist<T> const &list){
      //wenn this gleich &list dann gibt einfach this zurück
      if( this == &list ) 
        return *this; 
      //Neue Clist erzeugen und  mit list initialisieren
      Clist<T> listCopy( list );
      //swap funktion aufrufen um neue Clist zu vertauschen 
      //swap als Parameter mit neuen Element aufrufen
      swap( listCopy );
      // Ende this zurück
      return *this;
    }
    
    // +---------------------------------------------------------------------------
    // +  Clist<T>::swap throw() - Inhalte tauschen in O(1) Zeit , dh. unab-
    // +    hängig von der Länge der Listen.
    // +  , 20.12.2007
    // +---------------------------------------------------------------------------
    template <typename T>
    void Clist<T>::swap(Clist<T> & list )throw(){ 
      //2 Elemente als temporaer vom Typ ClistElem<T> für head und tail
      ClistElem<T> *anfang = list.head_;
      ClistElem<T> *ende = list.tail_;  
      size_t size = list.size_;
      //Memberdaten von List tauschen
      list.head_ = head_; 
      list.tail_ = tail_; 
      list.size_ = size_;
      //Neue werte von head,tail und size zuweisen
      head_ = anfang; 
      tail_ = ende; 
      size_ = size;	
    }
    
    // +---------------------------------------------------------------------------
    // +  Clist<T>::sort() - die Liste sortieren mittels des < Operators für T.
    // +    Als Algorithmus wird bubble-sort verwendet - nicht optimal!
    // +  , 20.12.2007
    // +---------------------------------------------------------------------------
    template <typename T>
    void Clist<T>::sort()throw(){
      for (ClistElem<T> *p(head_); p; p=p->next_) {
        for (ClistElem<T> *q(p->next_); q; q=q->next_) {
          if(q->value_ < p->value_) std::swap(p->value_,q->value_);
        }
      }
    }
    
    // +---------------------------------------------------------------------------
    // +  Clist<T>::sort(Compare comp) - die Liste sortieren nach der von comp
    // +    bestimmten Ordung. Als Algorithmus wird bubble-sort verwendet.
    // +    Eine Methoden-Schablone: template geschachtelt!
    // +  , 20.12.2007
    // +---------------------------------------------------------------------------
    template <typename T> 
    template <typename Compare>  //sort() ist selbst ein template
    void Clist<T>::sort(Compare comp)throw() {
      for (ClistElem<T> *p(head_); p; p=p->next_) {
        for (ClistElem<T> *q(p->next_); q; q=q->next_) { 
          if (comp(q->value_, p->value_)) std::swap(p->value_,q->value_);
        }
      }
    }
    
    // +---------------------------------------------------------------------------
    // +  Clist<char const *>::sort() - die Liste sortieren nach dem < Operator
    // +    für T; Spezialisierung für const char * mit strcmp.
    // +    Als Algorithmus wird bubble-sort verwendet - nicht optimal!
    // +  , 20.12.2007
    // +---------------------------------------------------------------------------
    template < >
    inline void Clist<char const *>::sort()throw(){
      for (ClistElem<char const *> *p(head_); p; p=p->next_) {
        for (ClistElem<char const *> *q(p->next_); q; q=q->next_) { 
          if (strcmp(q->value_, p->value_) < 0) std::swap(p->value_,q->value_);
        }
      }
    }
    
    // +---------------------------------------------------------------------------
    // +  Clist<T>::begin() - Iterator auf den Anfang der Liste -> Rückgabewert iterator
    // +  , 20.12.2007
    // +---------------------------------------------------------------------------
    template <typename T>
    typename Clist<T>::iterator Clist<T>::begin()throw(){
      //Neu iterator definieren
     iterator it; 
     //für neue iterator prev ist gleich Null
     it.prev_ = 0; 
     //für neue iterator current ist gleich head
     it.current_ = head_; 
     if (head_) it.next_ = head_->next_; 
       else it.next_ = 0;  
     //neue iterator zurueck geben
     return it;
    }
    
    // +---------------------------------------------------------------------------
    // +  Clist<T>::begin() const - Iterator auf den Anfang der Liste
    // +  , 20.12.2007-> ist wie begin(), aber als const
    // +  Kommentare: Wie iterator begin(), allerdings als const
    // +---------------------------------------------------------------------------
    template <typename T>
    typename Clist<T>::const_iterator Clist<T>::begin() const throw(){
      const_iterator it;
      it.prev_ = 0; 
      it.current_ = head_; 
      if (head_) it.next_ = head_->next_; 
        else it.next_ = 0;   
      return it; 
    }
    
    // +---------------------------------------------------------------------------
    // +  Clist<T>::end() - Iterator auf erste Element "nach" dem Vektor:
    // +    "off-the-end iterator"
    // +  , 20.12.2007
    // +---------------------------------------------------------------------------
    template <typename T>
    typename Clist<T>::iterator Clist<T>::end()throw(){
    	//Neue Iterator it definieren
    	iterator it; 
    	//it.prev ist gleich tail
    	it.prev_ = tail_; 
    	//it.current und it.next ist gleich null
        it.current_ = it.next_ = 0;
    	//Neue Iterator zurückgeben
    	return it;
    }
    
    // +---------------------------------------------------------------------------
    // +  Clist<T>::end() const - Iterator auf erste Element "nach" dem Vektor:
    // +    "off-the-end iterator"
    // +  , 20.12.2007-> wie end(), aber als const
    // +  Kommentare: Wie iterator end(), allerdings als const
    // +---------------------------------------------------------------------------
    template <typename T>
    typename Clist<T>::const_iterator Clist<T>::end() const throw() {
      const_iterator iter; 
      iter.prev_ = tail_;
      iter.current_ = iter.next_ = 0; 
      return iter; 
    }
    
    // +---------------------------------------------------------------------------
    // +  Clist<T>::del_() - alle Elemente einer Clist löschen. Die Methode 
    // +    arbeitet vom Ende her. Sie wirft keine Ausnahmen, falls ~T keine
    // +    wirft.
    // +  , 20.12.2007
    // +---------------------------------------------------------------------------
    template <typename T>
    void Clist<T>::del_() {
      //Solange tail was zeigt durch pop_back (von hinten) elemente loeshen
      while( tail_ )
        this->pop_back();
    }
    
    // +--------------------------------------------------------------------------
    // +  Implementierung von Iteratoren
    // +  Innerhalb Clist Klasse gibt es auch andere Klassen wie z.B. class iterator und
    // +  class const_iterator. Die müssen auch in Clist.cpp implementiert werden. 
    // +  A.Güclü Ercin, 20.12.2007
    // +--------------------------------------------------------------------------
    
    // +---------------------------------------------------------------------------
    // +  Clist<T>::iterator::iterator() - Standard-Konstruktor; die Einträge
    // +    werden über begin() und end() gesetzt, bzw. über die In- und De-
    // +    krement-Operatoren verändert
    // +  Standard-Konstruktor setzt alle Member Daten(prev_,current_, next_) auf 0
    // +  , 20.12.2007
    // +---------------------------------------------------------------------------
    
    template <typename T>
    Clist<T>::iterator::iterator()throw(): prev_(0), current_(0), next_(0){ }
    
    // +---------------------------------------------------------------------------
    // +  Clist<T>::iterator::iterator(iterator const&) - Kopier-Konstruktor
    // +   , 20.12.2007
    // +  Kopier-Konstruktor setzt alle Member Daten auf als parameter übergegebene Werte
    // +  mit sich selbt z.B. prev(it.prev_)
    // +---------------------------------------------------------------------------
    template <typename T>
    Clist<T>::iterator::iterator(iterator const &it) throw(): 
              prev_( it.prev_ ),current_( it.current_ ), next_( it.next_ ) { }
    
    // +---------------------------------------------------------------------------
    // +  Clist<T>::iterator::~iterator() - Destruktor
    // +  , 20.12.2007
    // +  Destruktor setzt alle Member Daten auf Null in Funktionskörper.
    // +---------------------------------------------------------------------------
    template <typename T>
    Clist<T>::iterator::~iterator() throw() {prev_ = 0; current_ = 0; next_ = 0; }
    
    // +---------------------------------------------------------------------------
    // +  Clist<T>::iterator::operator++() - Inkrement, Präfix
    // +    Keine Plausibilitätsprüfung! Spezielle Behandlung der Fälle "vor" und
    // +    "nach" der Liste.
    // +  , 20.12.2007
    // +---------------------------------------------------------------------------
    template <typename T>
    typename Clist<T>::iterator& Clist<T>::iterator::operator++()throw(){      
    
      if( current_ ){      
        prev_ = current_; 
        current_ = next_;	
        if( current_ ) next_ = current_->next_ ;
    	  else next_ = 0; 
      }
      else 
      if( next_ ){   // vor dem Anfang
        prev_ = 0; 
        current_ = next_; 
        if( current_ )next_ = current_->next_;
    	  else next_ = 0; 
      }
    
      return *this;
    }
    
    // +---------------------------------------------------------------------------
    // +  Clist<T>::iterator::operator++(int) - Inkrement, Postfix
    // +    Keine Plausibilitätsprüfung!
    // +  , 20.12.2007
    // +---------------------------------------------------------------------------
    template <typename T>
    typename Clist<T>::iterator Clist<T>::iterator::operator++(int)throw(){    
    
      iterator it( *this );
      ++( *this );	
      return it;
    }
    
    // +---------------------------------------------------------------------------
    // +  Clist<T>::iterator::operator--() - Dekrement, Präfix
    // +    Keine Plausibilitätsprüfung! Spezielle Behandlung der Fälle "vor" und
    // +    "nach" der Liste.
    // +  , 20.12.2007
    // +---------------------------------------------------------------------------
    template <typename T>
    typename Clist<T>::iterator& Clist<T>::iterator::operator--()throw(){
    
      if( current_ ){ 
    	next_ = current_; 
        current_ = prev_; 
        if( current_ ) prev_ = current_->prev_ ;
    	  else prev_ = 0;
      }
      else 
      if( prev_ ){
    	next_ = 0; 
        current_ = prev_; 
        if( current_ ) prev_ = current_->prev_;
    	  else prev_ = 0; 
      } 
    
      return *this;
    }
    
    // +---------------------------------------------------------------------------
    // +  Clist<T>::iterator::operator--(int) - Dekrement, Postfix
    // +    Keine Plausibilitätsprüfung!
    // +  , 20.12.2007
    // +---------------------------------------------------------------------------
    template <typename T>
    typename Clist<T>::iterator Clist<T>::iterator::operator--(int)throw(){
    
    	iterator it( *this );
    	--(*this);
    	return it;
    }
    
    // +---------------------------------------------------------------------------
    // +  Clist<T>::iterator::operator=(iterator const&)
    // +  , 20.12.2007
    // +  "Operator =" setzt alle Member Daten auf als parameter übergegebene Werte
    // +  mit sich selbt z.B. prev(it.prev_) und gibt *this zurück
    // +---------------------------------------------------------------------------
    template <typename T>
    typename Clist<T>::iterator& Clist<T>::iterator::operator=(iterator const& it)
    throw(){
    
     prev_ = it.prev_; 
     current_ = it.current_; 
     next_ = it.next_;
    
     return (*this);
    }
    
    // +----------------------------------------------------------------------------------
    // +  Clist<T>::iterator::operator==(iterator const&) - nur iteratoren zum
    // +    selben Container können gleich sein!
    // +  , 20.12.2007
    // +  Gibt true zurück wenn Member Daten gleich mit als parameter übergegebene
    // +  Objekt ist. so z.B. prev_==it.prev_ && current_==it.current_ && next_==it.next_
    // +-----------------------------------------------------------------------------------
    template <typename T>
    bool Clist<T>::iterator::operator==(iterator const & it ) const throw(){
    
    	return  prev_==it.prev_ && current_==it.current_ 
                && next_==it.next_;
    }
    
    // +---------------------------------------------------------------------------
    // +  Clist<T>::iterator::operator!=(iterator const&)
    // +  , 20.12.2007
    // +---------------------------------------------------------------------------
    template <typename T>
    bool Clist<T>::iterator::operator!=(iterator const & it) const throw(){
    
    	return !( *this == it );
    }
    
    // +---------------------------------------------------------------------------
    // +  Clist<T>::iterator::operator*() - Zugriff auf das Element, auf das der
    // +    aktuelle Iterator "verweist". Die Plausibilitätskontrolle ist bei
    // +    den gängigen STL Implementierungen nicht vorhanden wegen der Lauf-
    // +    zeitverschlechterung.
    // +  , 20.12.2007
    // +---------------------------------------------------------------------------
    template <typename T>
    T& Clist<T>::iterator::operator*(){
    
      if ( ((!current_) && (!next_)) || ((!prev_) && (!current_)) ) 
        throw out_of_range("*op bad iterator");
      // (!current_) && (!next_) -> am hinteren Ende der Liste?
      // (!prev_) && (!current_) -> am vorderen Ende der Liste?
    
      return current_->value_; 
    }
    
    // +---------------------------------------------------------------------------
    // +  Clist<T>::iterator::operator->() - Zugriff auf Elemente des Ts,
    // +    auf den der aktuelle Iterator "verweist". 
    // +    Die Plausibilitätskontrolle ist bei den gängigen STL Implementierungen
    // +    nicht vorhanden wegen der Laufzeitverschlechterung.
    // +  , 20.12.2007
    // +---------------------------------------------------------------------------
    
    template <typename T>
    T* Clist<T>::iterator::operator->(){
    
      if ( ((!current_) && (!next_)) || ((!prev_) && (!current_)) ) 
       throw out_of_range("->op bad iterator"); 
        //Erklärung siehe operator*()
        //(!current_) && (!next_) -> am hinteren Ende der Liste?
        //(!prev_) && (!current_) -> am vorderen Ende der Liste?
      return &(current_->value_); 
    }
    
    // +---------------------------------------------------------------------------
    // + Implementierung von Const_Iteratoren - class const_iterator
    // +---------------------------------------------------------------------------
    // +---------------------------------------------------------------------------
    // +  Clist<T>::const_iterator::const_iterator() - Standard-Konstruktor; die
    // +    Einträge werden über begin() const und end() const gesetzt, bzw. über
    // +    die In- und Dekrement-Operatoren verändert
    // +  , 20.12.2007
    // + Standard-Konstruktor setzt alle Member Daten auf Null
    // +---------------------------------------------------------------------------
    template <typename T>
    Clist<T>::const_iterator::const_iterator()throw(): 
    prev_(0), current_(0), next_(0) {}
    
    // +---------------------------------------------------------------------------
    // +  Clist<T>::const_iterator::const_iterator(const_iterator const&) -
    // +    Kopier-Konstruktor
    // +  , 20.12.2007
    // +  wie oben bei der Klasse iterator-> Kopierkonstruktor
    // +---------------------------------------------------------------------------
    template <typename T>
    Clist<T>::const_iterator::const_iterator(const_iterator const & it) throw(){
    
      prev_ = it.prev_; 
      current_ = it.current_; 
      next_ = it.next_; 
    }
    
    // +---------------------------------------------------------------------------
    // +  Clist<T>::const_iterator::const_iterator(iterator const&) -
    // +    Konvertierung von iterator zu const_iterator
    // +  , 20.12.2007
    // +---------------------------------------------------------------------------
    template <typename T>
    Clist<T>::const_iterator::const_iterator(iterator const & it) throw() {
    
      prev_ = it.prev_; 
      current_ = it.current_; 
      next_ = it.next_; 
    }
    
    // +---------------------------------------------------------------------------
    // +  Clist<T>::const_iterator::~const_iterator() - Destruktor
    // +  , 20.12.2007
    // +  wie bei der Klasse iterator Destruktor
    // +---------------------------------------------------------------------------
    template <typename T>
    Clist<T>::const_iterator::~const_iterator() throw(){
    
      prev_ = 0; current_ = 0; next_ = 0; 
    }
    
    // +---------------------------------------------------------------------------
    // +  Clist<T>::const_iterator::operator++() - Inkrement, Präfix
    // +    Keine Plausibilitätsprüfung! Spezielle Behandlung der Fälle "vor" und
    // +    "nach" der Liste.
    // +  , 20.12.2007
    // +---------------------------------------------------------------------------
    template <typename T>
    typename Clist<T>::const_iterator& Clist<T>::const_iterator::operator++() throw(){
    
       if( current_ ){      
        prev_ = current_; 
        current_ = next_;	
        if( current_ ) next_ = current_->next_ ;
    	  else next_ = 0; 
      }
      else 
      if( next_ ){   // vor dem Anfang
        prev_ = 0; 
        current_ = next_; 
        if( current_ )next_ = current_->next_;
    	  else next_ = 0; 
      }
    
      return *this;
    }
    
    // +---------------------------------------------------------------------------
    // +  Clist<T>::const_iterator::operator++(int) - Inkrement, Postfix
    // +    Keine Plausibilitätsprüfung!
    // +  , 20.12.2007
    // +---------------------------------------------------------------------------
    template <typename T>
    typename Clist<T>::const_iterator Clist<T>::const_iterator::operator++(int)
    throw(){  
      //die Werte des alten Operanden "sichern" 
      iterator It; It.prev_ = prev_; It.current_ = current_;
      It.next_ = next_; 
      ++( *this );	
      return It;
    }
    
    // +---------------------------------------------------------------------------
    // +  Clist<T>::const_iterator::operator--() - Dekrement, Präfix
    // +    Keine Plausibilitätsprüfung! Spezielle Behandlung der Fälle "vor" und
    // +    "nach" der Liste.
    // +  , 20.12.2007
    // +---------------------------------------------------------------------------
    template <typename T>
    typename Clist<T>::const_iterator& Clist<T>::const_iterator::operator--()
    throw(){
    
      if( current_ ){ 
    	next_ = current_; 
        current_ = prev_; 
        if( current_ ) prev_ = current_->prev_ ;
    	  else prev_ = 0;
      }
      else 
      if( prev_ ){
    	next_ = 0; 
        current_ = prev_; 
        if( current_ ) prev_ = current_->prev_;
    	  else prev_ = 0; 
      } 
    
      return *this;
    }
    
    // +---------------------------------------------------------------------------
    // +  Clist<T>::const_iterator::operator--(int) - Dekrement, Postfix
    // +    Keine Plausibilitätsprüfung!
    // +  , 20.12.2007
    // +---------------------------------------------------------------------------
    template <typename T>
    typename Clist<T>::const_iterator Clist<T>::const_iterator::operator--(int)
    throw(){
    	//die Werte des alten Operanden "sichern"
      iterator It; It.prev_ = prev_; It.current_ = current_;
      It.next_ = next_; 
      --( *this );	
      return It;
    }
    
    // +---------------------------------------------------------------------------
    // +  Clist<T>::const_iterator::operator=(const_iterator const&)
    // +  , 20.12.2007
    // +---------------------------------------------------------------------------
    template <typename T>
    typename Clist<T>::const_iterator& Clist<T>::const_iterator::
                       operator=(const_iterator const&it)throw(){
    
     prev_ = it.prev_; 
     current_ = it.current_; 
     next_ = it.next_;
     return (*this);
    }
    
    // +---------------------------------------------------------------------------
    // +  Clist<T>::const_iterator::operator==(const_iterator const&) - nur
    // +    const_iteratoren zum selben Container können gleich sein!
    // +  , 20.12.2007
    // +---------------------------------------------------------------------------
    template <typename T>
    bool Clist<T>::const_iterator::
                   operator==(const_iterator const & it ) const throw(){
    
      return prev_==it.prev_ && current_==it.current_ && next_==it.next_;
    }
    
    // +---------------------------------------------------------------------------
    // +  Clist<T>::const_iterator::operator!=(const_iterator const&)
    // +  , 20.12.2007
    // +---------------------------------------------------------------------------
    template <typename T>
    bool Clist<T>::const_iterator::
                   operator!=(const_iterator const & it) const throw(){
    
    	return !( *this == it );
    }
    
    // +---------------------------------------------------------------------------
    // +  Clist<T>::const_iterator::operator*() - Zugriff auf das Element, auf
    // +    das der aktuelle const_Iterator "verweist".
    // +    Die Plausibilitätskontrolle ist bei den gängigen STL Implementierungen
    // +     nicht vorhanden wegen der Laufzeitverschlechterung.
    // +  , 20.12.2007
    // +---------------------------------------------------------------------------
    template <typename T>
    const T& Clist<T>::const_iterator::operator*()const {
    
      if( ((!current_) && (!next_)) || ((!prev_) && (!current_)) ) 
        throw out_of_range("*op bad iterator");
      // (!current_) && (!next_) -> am hinteren Ende der Liste?
      // (!prev_) && (!current_) -> am vorderen Ende der Liste?
      return current_->value_; 
    }
    
    // +---------------------------------------------------------------------------
    // +  Clist<T>::const_iterator::operator->() - Zugriff auf das Elemente, 
    // +    auf das der aktuelle const_Iterator "verweist". 
    // +    Die Plausibilitätskontrolle ist bei den gängigen STL Implementierungen
    // +    nicht vorhanden wegen der Laufzeitverschlechterung.
    // +  , 20.12.2007
    // +---------------------------------------------------------------------------
    template <typename T>
    const T* Clist<T>::const_iterator::operator->() const {
    
      if( ((!current_) && (!next_)) || ((!prev_) && (!current_)) ) 
        throw out_of_range("->op bad iterator"); 
        //Erklärung siehe operator*()
        //(!current_) && (!next_) -> am hinteren Ende der Liste?
       //(!prev_) && (!current_) -> am vorderen Ende der Liste?
      return &(current_->value_); 
    }
    
    // +---------------------------------------------------------------------------
    // + Implementierung von Klasse ClistElem 
    // +---------------------------------------------------------------------------
    
    // +---------------------------------------------------------------------------
    // +  ClistElem<T>::ClistElem(T const & =T()) - der einzige Konstruktor;
    // +    definiert den Standardkonstruktor mit, da der einzige Parameter
    // +    wegen der Vorbesetzung auch fehlen kann.
    // +  , 20.12.2007
    // +---------------------------------------------------------------------------
    template <typename T>
    ClistElem<T>::ClistElem(T const &s) : prev_(0), next_(0), value_(s) {}
    
    // +---------------------------------------------------------------------------
    // +  ClistElem<T>::link_(ClistElem *, bool) - ein neues Element p beim
    // +    aktuellen Listenelement einfügen.
    // +  
    // +---------------------------------------------------------------------------
    template <typename T>
    void ClistElem<T>::link_(ClistElem *elem, bool append) throw() {
      if (!elem) return;
      if (append) {  // elem nach dem aktuellen einhängen
        elem->prev_ = this; elem->next_ = next_;
        if (next_) next_->prev_ = elem;
        next_ = elem;
      } else {  // ... vor dem aktuellen 
        elem->next_ = this;  elem->prev_ = prev_;
        if (prev_) prev_->next_ = elem;
        prev_ = elem;
      }
    }
    
    // +---------------------------------------------------------------------------
    // +  ClistElem<T>::link_(ClistElem *first, ClistElem *last, bool append) -
    // +    beim aktuellen Element eine ganze bereits verkettete Liste einfügen
    // +    ("merge"): [first,last] - also inklusive last!
    // +  
    // +---------------------------------------------------------------------------
    template <typename T>
    void ClistElem<T>::link_(ClistElem *first, ClistElem *last, bool append)
       throw() {
      if (!first || !last) return;
      if (append) {  // nach dem aktuellen Element einhängen
        first->prev_ = this; last->next_ = next_;
        if (next_) next_->prev_ = last;
        next_ = first;
      } else {  // vor dem aktuellen Element einhängen
        last->next_ = this;  first->prev_ = prev_;
        if (prev_) prev_->next_ = first;
        prev_ = last;
      }
    }
    
    // +---------------------------------------------------------------------------
    // +  ClistElem<T>::unlink_() - das aktuelle Element aus der Liste aushängen.
    // +  
    // +---------------------------------------------------------------------------
    template <typename T>
    void ClistElem<T>::unlink_() throw() {
      if (prev_) prev_->next_ = next_;
      if (next_) next_->prev_ = prev_;
    }
    
    // +---------------------------------------------------------------------------
    // +  ClistElem<T>::unlink_(ClistElem *last) - den Teil der Liste vom
    // +    aktuellen Element bis einschließlich(!) last aushängen ("splice")
    // +    [this,last] - also inklusive last!
    // +  
    // +---------------------------------------------------------------------------
    template <typename T>
    void ClistElem<T>::unlink_(ClistElem *last)  throw() {
      if (!last) return;
      if (prev_) prev_->next_ = last->next_;
      if (last->next_) last->next_->prev_ = prev_;
    }
    
    template<typename T>
    void Clist<T>::resize(size_type sz, T c ){
    
    }
    
    template<typename T>
    void Clist<T>::reverse(){
    /*
      if(!head_) return;
      while( head_ != tail_ ){  // ---> endlose Schleife, falls die Liste nicht
       std::swap(head_-> value_ , tail_ -> value_);  // ---> leer ist!!!
       //head_ ++;
        }
    */
    
    ClistElem<T> *p(head_);
    ClistElem<T> *q(tail_);
    
      for( ; p !=q ; p=p->nxt_,--q)
        std::swap(p->value, q->value);
    
    }
    /* 
      for( ;head_ != tail_; head_=head_->next_)
        head_ = tail_;
    */
    
    } // namespace swe3
    //
    #endif
    //
    // +---------------------------------------------------------------------------
    // +  Liste der Änderungen
    // +  Datenelement       Datum        AutorIn       Beschreibung
    // +---------------------------------------------------------------------------
    // +  Modul         20.12.2007     erste Version
    // +				24.12.2007     zweite Version
    // +                04.12.2007     letzte Version
    // +
    //
    //  Ende der Datei
    


  • Ich muss jetzt oben stehende Klasse-Clist mit anderen Funktionen wie resize,rend usw. erweitern.



  • strong schrieb:

    Ich muss jetzt oben stehende Klasse-Clist mit anderen Funktionen wie resize,rend usw. erweitern.

    Woran haperts denn genau?



  • Einer von diesen Funktionen wird Klausur-Aufgabe. Wir müssen Implementierungen selbst schreiben. Der will nicht, dass man einfach die Funktionen aus der Bibliothek nutzt.


  • Mod

    Hier Lösungen oder Lösungsskizzen zu zeigen, wäre so etwas wie Hausaufgaben machen. Der bisherige Aufbau ist nicht ganz unbrauchbar, aber es haben sich auch einige Fehler (die ich hier nicht aufzählen will, das wäre nach der Klausur denkbar) eingeschlichen und es wird an einigen Stellen - wahrscheinlich aus Unwissenheit - ohne Not vom Verhalten von std::list abgewichen. Der Verzicht auf einen Allokator gehört sicherlich nicht dazu, aber logischerweise führt das natürlich dazu, dass get_allocator überflüssig wird. max_size ist eher uninteressant, wenn man ohne Allokatoren arbeitet. Gleiches gilt dann entsprechend für rbegin,rend.
    Was am meisten auffällt, ist, dass offenbar das Wesen - oder die spezielle Eigenheit - doppelt verketteter Listen nicht erkannt wurde: im Gegensatz zu Container wie vector oder deque kann man (im Prinzip - wenn man auf konstante Laufzeit von size() verzichtet, was erlaubt ist) alle interessanten Listenoperationen ausschließlich über Iteratoren implementieren, ohne jedesmal das konkrete Containerobjekt als solches anfassen zu müssen. Oder möglicherweise ist das auch ein fehlendes Verständnis dafür, was ein Iterator ist - jedenfalls ist dessen Implementierung etwas seltsam.

    Ein paar Kleinigkeiten, die nichts direkt mit dem Problem zu tun haben, kann ich anmerken:
    So etwas wie Selbstzuweisung gibt es im Copy-ctor nicht, eine entsprechende Prüfung ist dort fehl am Platz (und ein exceptionsicherer Zuweisungsoperator bedarf einer solchen Prüfung normalerweise auch nicht). Zudem sollten Funktionen durchlässig für Exceptions sein: wenn eine Funktion fehlschlägt, weil zum Beispiel das Kopieren eines Elements fehlschlägt, sollte diese Exception - nach den entsprechenden Aufräumaktionen - unverändert weitergeworfen werden. Dem Aufrufer anzuzeigen, welche Funktion fehlgeschlagen ist, ist schließlich sinnlos: das weis der Aufrufer sowieso - nicht aber welche konkrete elementare Funktion nicht durchgeführt werden konnte. new liefert niemals 0 zurück.
    Destruktoren sollten (im Zusammenhang mit der Standardbibliothek) niemals Exceptions auslösen. Es ist praktisch unmöglich, excptionsicher zu progammieren, wenn diese Regel nicht eingehalten wird, das muss daher dann auch nicht behandelt werden. der Vollständigkeit halber kannst du dem Destruktor auch noch die entsprechende leere Exceptionspezifikation verpassen.
    Die Iterator-Operatoren * und -> sollten const sein.
    Der value_type eines const_iterators bleibt ohne zusätzliches const (wird nicht vorgeschrieben - aber Analogie zu iterator_traits<T*>)

    Die einzig wirklich interessante und sehr wichtige Operation mit Listen ist splice - damit lassen sich andere Funktionen leichter implementieren: indem swaps durch splice durchgeführt werden, entfallen potentielle Quellen für das Werfen von Exceptions, und zum Einhalten der Komplexitätsgarantien ist es ebenfalls unverzichtbar.


Anmelden zum Antworten