2010-11-03 22 views
0

J'essaye de trier une liste liée. J'ai des problèmes avec const. Il ne me laissera pas assigner à une variable qui est const ce que c'est supposé faire. Cependant, je ne sais pas comment contourner cela? J'apprécierais toute aide que je pourrais obtenir.Bulle trier un modèle de liste de liens

Tout cela est dans un fichier d'en-tête, la fonction de tri est aussi, je vais essayer de le sortir il est donc facile à trouver:

void LinkedList<T>::BubleSort() 
{ 

T temp; 
ListElement<T>* cur = head; 

    const ListElement<T>* forward = head->Next(); 


while(cur) 
{ 
    while(forward) 
    { 

     if(cur->Datum() > forward->Datum()) 
     { 

        temp = cur->Datum(); 
        cur->Datum() = forward->Datum(); 
        forward->Datum() = temp; 
     } 
    } 
} 

} 

Les erreurs que je reçois

erreur C3892 : 'cur': vous ne pouvez pas affecter à une variable const lors de la compilation de la fonction membre du modèle de classe 'void LinkedList :: BubleSort (void)' voir la référence à l'instanciation du modèle de classe 'LinkedList' en cours de compilation

Bien sûr, si son const je ne peux pas le faire, je ne sais pas comment contourner cela.

Voici le fichier d'en-tête où toutes les informations et est la fonction de tri:

#include <typeinfo> 

template <class T> 
class LinkedList; 

template <class T> 
class ListElement 
{ 
T datum; 
ListElement* next; 

ListElement (T const&, ListElement*); 
public: 
T const& Datum() const; 
ListElement const* Next() const; 

friend class LinkedList<T>; 
}; 

template <class T> 
class LinkedList 
{ 
ListElement<T>* head; 
ListElement<T>* tail; 
public: 
LinkedList(); 
~LinkedList(); 

LinkedList (LinkedList const&); 
LinkedList& operator = (LinkedList const&); 

ListElement<T> const* Head() const; 
ListElement<T> const* Tail() const; 
bool IsEmpty() const; 
T const& First() const; 
T const& Last() const; 

void BubleSort(); 
void Prepend (T const&); 
void Append (T const&); 
void Extract (T const&); 
void Purge(); 
void InsertAfter (ListElement<T> const*, T const&); 
void InsertBefore (ListElement<T> const*, T const&); 
}; 

template <class T> 
ListElement<T>::ListElement (
T const& _datum, ListElement<T>* _next) : 
datum (_datum), next (_next) 
{} 

template <class T> 
T const& ListElement<T>::Datum() const 
{ return datum; } 

template <class T> 
ListElement<T> const* ListElement<T>::Next() const 
{ return next; } 



template <class T> 
LinkedList<T>::LinkedList() : 
head (0), 
tail (0) 
{} 


template <class T> 
void LinkedList<T>::Purge() 
{ 
while (head != 0) 
{ 
ListElement<T>* const tmp = head; 
head = head->next; 
delete tmp; 
} 
tail = 0; 
} 

template <class T> 
LinkedList<T>::~LinkedList() 
{ Purge(); } 



template <class T> 
ListElement<T> const* LinkedList<T>::Head() const 
{ return head; } 

template <class T> 
ListElement<T> const* LinkedList<T>::Tail() const 
{ return tail; } 

template <class T> 
bool LinkedList<T>::IsEmpty() const 
{ return head == 0; } 



template <class T> 
T const& LinkedList<T>::First() const 
{ 
if (head == 0) 
    throw std::domain_error ("list is empty"); 
return head->datum; 
} 

template <class T> 
T const& LinkedList<T>::Last() const 
{ 
if (tail == 0) 
    throw std::domain_error ("list is empty"); 
return tail->datum; 
} 
/**********************************************/ 

template <class T> 

void LinkedList<T>::BubleSort() 
{ 

T temp; 
ListElement<T>* cur = head; 
; 
const ListElement<T>* forward = head->Next(); 


while(cur) 
{ 
    while(forward) 
    { 

     if(cur->Datum() > forward->Datum()) 
     { 

      temp = cur->Datum(); 
      cur->Datum() = forward->Datum(); 
      forward->Datum() = temp; 
     } 
    } 
} 

} 

template <class T> 
void LinkedList<T>::Prepend (T const& item) 
{ 
ListElement<T>* const tmp = new ListElement<T> (item, head); 
if (head == 0) 
tail = tmp; 
head = tmp; 
} 



template <class T> 
void LinkedList<T>::Append (T const& item) 
{ 
ListElement<T>* const tmp = new ListElement<T> (item, 0); 
if (head == 0) 
head = tmp; 
else 
tail->next = tmp; 
tail = tmp; 
} 



template <class T> 
LinkedList<T>::LinkedList (LinkedList<T> const& linkedList) : 
head (0), 
tail (0) 
{ 
ListElement<T> const* ptr; 
for (ptr = linkedList.head; ptr != 0; ptr = ptr->next) 
Append (ptr->datum); 
} 

template <class T> 
LinkedList<T>& LinkedList<T>::operator = (
LinkedList<T> const& linkedList) 
{ 
if (&linkedList != this) 
{ 
Purge(); 
ListElement<T> const* ptr; 
for (ptr = linkedList.head; ptr != 0; ptr = ptr->next) 
    Append (ptr->datum); 
} 
return *this; 
} 



template <class T> 
void LinkedList<T>::Extract (T const& item) 
{ 
ListElement<T>* ptr = head; 
ListElement<T>* prevPtr = 0; 
while (ptr != 0 && ptr->datum != item) 
{ 
prevPtr = ptr; 
ptr = ptr->next; 
} 
if (ptr == 0) 

    throw std::invalid_argument ("item not found"); 

if (ptr == head) 
head = ptr->next; 
else 
prevPtr->next = ptr->next; 
if (ptr == tail) 
tail = prevPtr; 
delete ptr; 
} 




template <class T> 
void LinkedList<T>::InsertAfter (
ListElement<T> const* arg, T const& item) 
{ 
ListElement<T>* ptr = const_cast<ListElement<T>*> (arg); 
if (ptr == 0) 
{ 

} 
throw std::invalid_argument ("invalid position"); 
ListElement<T>* tmp = new ListElement<T> (item, ptr->next); 
ptr->next = tmp; 
if (tail == ptr) 
{ 

} 
tail = tmp; 
} 

template <class T> 
void LinkedList<T>::InsertBefore (
ListElement<T> const* arg, T const& item) 
{ 
ListElement<T>* ptr = const_cast<ListElement<T>*> (arg); 
if (ptr == 0) 
{ 

} 
throw std::invalid_argument ("invalid position"); 
ListElement<T>* const tmp = new ListElement<T> (item, ptr); 
if (head == ptr) 
{ 

} 
head = tmp; 
else 
{ 
ListElement<T>* prevPtr = head; 
while (prevPtr != 0 && prevPtr->next != ptr) 
    prevPtr = prevPtr->next; 
if (prevPtr == 0) 
{ 

} 
throw std::invalid_argument ("invalid position"); 
prevPtr->next = tmp; 
} 
} 

Répondre

0

Tri de la liste est une opération non-const; vous ne pouvez pas le faire avec des accesseurs const uniquement. La solution habituelle est de surcharger les accesseurs avec un const et une variante non-const:

ListElement const* Next() const { return next; } 
ListElement* Next() { return next; } 

Tu ferais la même chose pour les fonctions accesseurs dans votre classe LinkedList (sauf si vous voulez faire la liste immuable, bien sûr).

+0

Merci. J'ai fait ce que vous avez dit et j'ai aussi appliqué cela à la référence. Fonctionne maintenant. –

0

... De plus, vous écrivez que Datum() renvoie une référence const, mais vous utilisez ensuite un appel Datum() comme valeur l dans "cur->Datum() = forward->Datum();". Comment cette mission va-t-elle fonctionner quand la chose à gauche est immuable? De plus, vous déclarez forward comme pointeur vers une constante ListElement, puis utilisez forward sur la LHS d'une affectation: "forward->Datum() = temp;". Vous avez probablement toujours besoin de forward == cur-> Next() dans les deux while() s. (C'est-à-dire toujours mis à jour pour pointer sur ce qui est le suivant.) Donc ça ne peut pas être const.

Vous allez vraiment devoir repenser votre utilisation de const étant donné la quantité de mutabilité que vous semblez vouloir utiliser.

+0

Je sais ce que je faisais est faux. J'avais juste besoin de code pour montrer et comment je pense que cela devrait être fait. Vous ne savez pas exactement ce que vous entendez par "Vous avez probablement toujours besoin de forward == cur-> Next() dans les deux while() s." ???? –

+0

@icelated: Comme indiqué, forward pointe toujours vers le deuxième élément de la liste (en supposant que cet élément existe). Comme vous ne faites jamais avancer ou reculer la liste, il est difficile de deviner comment vous comptez comparer avec un élément autre que le second. –

+0

Je vois ce que tu veux dire! J'ai fixé cela et j'ai appliqué la solution de Fabians ci-dessous et son travail maintenant. –