web-dev-qa-db-fra.com

Création d'un constructeur de copie pour une liste liée

C'est un devoir

Je travaille sur l'implémentation d'une classe de liste chaînée pour ma classe C++, et le constructeur de copie m'a été très déroutant.

La liste liée est composée de structures appelées Elems:

struct Elem 
    {
        int pri;
        data info;
        Elem * next;
    };
    Elem * head;

info est une classe distincte et personnalisée stockée dans Elem.

la signature du constructeur de copie est:

linkedList::linkedList( const linkedList &v )

Le problème que je rencontre est principalement de prendre ma logique et de l'écrire sous forme de code.

Mon idée générale est de:

  1. Placez la tête sur v.head (head = v.head)
  2. Définissez les valeurs de Elem sur v (pri = v.pri, info = v.info, next = v.next)
  3. Faites une itération en répétant l'étape 2.

Est-ce l'idée générale?

Toute aide est la bienvenue.N'oubliez pas que c'est un devoir, donc pas de réponse directe, s'il vous plaît!

Merci pour votre temps

=============================================== =============================================== =============================================== ==============

Merci pour votre temps tout le monde!

Je pense l'avoir compris:

//Copy Constructor
LinkedList::LinkedList( const LinkedList &v )
{
Elem * p1 = 0;//current
Elem * p2 = 0;//next

if( v.head == 0 )
    head = 0;

else
{
    head = new Elem;
    head -> pri = v.head -> pri;
    head -> info = v.head -> info;

    p1 = head;
    p2 = v.head -> next;
}

while( p2 )
{
    p1 -> next = new Elem;
    p1 = p1 -> next;
    p1 -> pri = p2 -> pri;
    p1 -> info = p2 -> info;

    p2 = p2 -> next;
}
p1 -> next = 0;
}

Je suis sûr que ça marche. J'ai dessiné quelques images logiques pour aider, et je n'ai rencontré aucun problème.

20
Joshua

Vous devez être prudent avec l'étape 1 et une partie de l'étape 2. L'étape 1 doit allouer un nouveau nœud et l'utiliser comme head. À l'étape 2, la partie concernant next = v.next, à moins que votre intention ne soit de créer une copie superficielle, est incorrecte.

Lorsque vous copiez un conteneur, par exemple une liste chaînée, vous souhaitez probablement une copie complète. Par conséquent, vous devez créer de nouveaux nœuds et copier uniquement les données. Les pointeurs next et prior dans les nœuds de la nouvelle liste doivent faire référence aux nouveaux nœuds que vous créez spécifiquement pour cette liste et non aux nœuds de la liste d'origine. Ces nouveaux nœuds auront des copies des données correspondantes de la liste d'origine, de sorte que la nouvelle liste puisse être considérée comme une valeur de référence ou une copie complète.

Voici une image illustrant les différences entre la copie superficielle et profonde:

enter image description here

Notez que, dans la partie Deep Copy du diagramme, aucun des nœuds ne pointe vers des nœuds de l'ancienne liste. Pour plus d'informations sur la différence entre les copies superficielles et profondes, voir l'article de Wikipedia sur copie d'objets .

21
Michael Goldshteyn
  1. Vous ne devriez pas définir this->head = v.head. Parce que la tête est simplement un pointeur. Ce que vous devez faire est de créer une nouvelle tête et de copier les valeurs individuellement de v.head dans votre nouvelle tête. Sinon, vous auriez deux pointeurs pointant vers la même chose.

  2. Vous devez ensuite créer un pointeur Elem temporaire commençant par v.head et parcourir la liste, en copiant ses valeurs dans les nouveaux pointeurs Elem dans la nouvelle copie.

  3. Voir au dessus.

4
Zeenobit

Que doit copier votre constructeur de copie? Il devrait copier pri - facile. Il devrait également copier info- easy. Et si next n'est pas nul, il devrait également le copier. Comment pouvez-vous copier next? Pensez récursif: Eh bien, next est un Elem *, et Elem a un constructeur de copie: utilisez-le pour copier le Elem référencé et y faire référence. 

Vous pouvez également résoudre ce problème de manière itérative, mais la solution récursive est beaucoup plus intuitive.

2
Landei

Voici donc ma réponse (je ne sais pas si cela convient à vos devoirs ou non - les instructeurs ont parfois tendance à avoir leurs propres idées;):

Généralement, un constructeur de copie devrait "copier" votre objet. C'est à dire. disons que vous avez linkedList l1, et faites une linkedList l2 = l1 (qui appelle linkedList :: linkedList (l1)), alors l1 et l2 sont des objets totalement séparés dans le sens où la modification de l1 n’affecte pas l2 et le vice vice versa.

Lorsque vous ne faites qu'attribuer des pointeurs, vous n'obtiendrez pas de copie réelle, car le déréférencement et la modification de l'un ou l'autre affectent les deux objets. 

Vous voulez plutôt faire une copie complète de chaque élément de votre liste de sources (ou faire une copie à la demande uniquement, si vous voulez être sophistiqué).

0
cli_hlt

Vous avez oublié la ligne return; Après

if( v.head == 0 )
    head = 0;

Vous devez sortir, non?

0
andy