2011-10-18 28 views
21

Esta es la tareaCreación de un constructor de copia de una lista enlazada

estoy trabajando en la implementación de una clase de lista enlazada para mi clase de C++, y el constructor de copia tiene ser muy confuso para mí.

La lista enlazada se compone de estructuras denominadas elems:

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

información es una clase separada, a medida que se almacena en el Elem.

la firma para el constructor de copia es:

linkedList::linkedList(const linkedList &v) 

El problema que estoy teniendo es sobre todo tomando mi lógica y escribir realmente como código.

Mi idea general es:

  1. Conjunto cabeza para v.head (= cabeza v.head)
  2. Establecer los valores de la Elem a (v.pri pri = de v, info = v.info , junto = v.next)
  3. Iterar a través, repitiendo el paso 2.

Es esta la idea general?

Cualquier ayuda sería genial. Recuerda, esto es tarea, ¡así que no hay respuestas directas, por favor!

Gracias por su tiempo

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

Gracias por su tiempo a todos!

creo que tengo todo resuelto:

//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; 
} 

Estoy bastante seguro de que las obras. Dibujé algunas imágenes lógicas para ayudar, y no me encontré con ningún problema.

+0

Exactamente ¿qué se supone que debe hacer el constructor de copias? Producir una copia de cada nodo con enlaces apropiados suena razonable, pero esa no es la única posibilidad. –

+2

+1 Por decir sin rodeos la tarea * y no pedir respuestas directas *. –

+0

¡Gracias por darme la pista correcta!Implementé un constructor de copia profunda para mis nodos, para poder devolver un objeto del nodo "final" con la estructura de referencia para el nodo padre y su nodo padre ... para mantenerme intacto. Lo usé para algoritmos de búsqueda de árbol – mtosch

Respuesta

21

Debe tener cuidado con el paso 1 y parte del paso 2. El paso 1 debe asignar un nuevo nodo y usarlo como el head. En el paso 2, la parte sobre next = v.next, a menos que su intención sea hacer una copia superficial, es incorrecta.

Al copiar un contenedor como una lista vinculada, es probable que desee una copia profunda, por lo que se deben crear nuevos nodos y solo se deben copiar los datos. Los punteros next y prior en los nodos de la nueva lista deben hacer referencia a los nuevos nodos que cree específicamente para esa lista y no los nodos de la lista original. Estos nuevos nodos tendrían copias de los datos correspondientes de la lista original, de modo que la nueva lista puede considerarse por valor o copia profunda.

Aquí es una imagen que representa las diferencias entre superficial y una copia completa:

enter image description here

Note como en el parte profundo copia del diagrama, ninguno de los nodos apuntan a los nodos en la lista de edad . Para obtener más información acerca de la diferencia entre copias superficiales y profundas, consulte el artículo de Wikipedia en object copying.

+3

Ooh! ¡Imágenes! Eso definitivamente ayudará a aclarar. +1 –

4
  1. No debe establecer this->head = v.head. Porque la cabeza es simplemente un puntero. Lo que debe hacer es crear un nuevo encabezado y copiar los valores individualmente desde v.head en su nuevo encabezado. De lo contrario, tendría dos punteros apuntando a la misma cosa.

  2. A continuación, tendría que crear un Elem puntero temporal que comienza con v.head y recorrer la lista, la copia de sus valores a las nuevas Elem punteros en la nueva copia.

  3. Ver arriba.

+3

Nota: Cuando copie sus valores, no _copia_ su puntero. En general, nunca copie un puntero en un constructor de copia. Copie el objeto al que apunta. –

2

¿Qué debe copiar el constructor de copia? Debe copiar pri - fácil. Debe copiar info, también es fácil. Y si next no es nulo, debería copiarlo también. ¿Cómo se puede copiar next? Piensa recursivamente: Bueno, next es un Elem *, y Elem tiene un constructor de copia: solo utilízalo para copiar el Elem referenciado y refiérete a él.

También puede resolver esto iterativamente, pero la solución recursiva es mucho más intuitiva.

+0

Cierto, esto es bastante fácil si Elem tiene un constructor de copia –

+0

Todavía no estamos haciendo recursividad intencionalmente, por lo que podemos ver qué sucede más fácilmente. Nos mostró de manera recursiva y dijo deliberadamente que fallaríamos si lo hiciéramos de esta manera. O_O – Joshua

+0

@Joshua: Debería mencionar tales restricciones. – Landei

0

Así que aquí es mi respuesta (no sé si eso se ajusta a su tarea o no - instructores tienden a tener sus propias ideas a veces;):

En general, un constructor de copia debe "copiar" su objeto. Es decir. Supongamos que ha vinculado la Lista l1, y realiza una Lista enlazada l2 = l1 (que llama a la Lista enlazada :: Lista enlazada (l1)), y luego l1 y l2 son objetos totalmente separados en el sentido de que la modificación de l1 no afecta a l2 y viceversa.

Cuando acaba de asignar punteros no obtendrá una copia real, ya que la eliminación de referencias y la modificación de cualquiera de ellos afectaría a ambos objetos.

Prefiere hacer una copia real profunda de cada elemento en su lista fuente (o hacer una copia bajo demanda, si quiere ser elegante).

0

se le olvidó la línea return; después

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

Usted necesita salir, ¿verdad?

Cuestiones relacionadas