2011-10-18 28 views
21

Đây là bài tập về nhàTạo một constructor sao chép cho một danh sách liên kết

Tôi đang làm việc về việc thực hiện một lớp danh sách liên kết cho ++ lớp C của tôi, và các nhà xây dựng bản sao đó có thể rất khó hiểu đối với tôi.

Danh sách liên kết bao gồm các cấu trúc được gọi là Elems:

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

thông tin là một lớp tùy chỉnh riêng biệt mà được lưu trữ trong Elem.

chữ ký cho các nhà xây dựng bản sao là:

linkedList::linkedList(const linkedList &v) 

Vấn đề tôi đang gặp chủ yếu dùng logic của tôi và thực sự viết nó dưới dạng mã.

ý tưởng chung của tôi là để:

  1. Set đầu đến v.head (head = v.head)
  2. Đặt giá trị của Elem đến (v.pri pri = v, info = v.info , bên cạnh = v.next)
  3. Duyệt qua, lặp lại bước 2.

đây có phải là ý tưởng chung?

Mọi trợ giúp đều tuyệt vời. Hãy nhớ, đây là bài tập về nhà, vì vậy không có câu trả lời trực tiếp nào!

Cảm ơn bạn đã dành thời gian

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

Cảm ơn thời gian của bạn!

Tôi nghĩ rằng tôi có nó đã tìm ra:

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

Tôi khá chắc chắn rằng công trình. Tôi đã vẽ một số hình ảnh hợp lý để trợ giúp và tôi không gặp phải bất kỳ vấn đề nào.

+0

Chính xác thì người tạo bản sao phải làm gì? Sản xuất một bản sao của mỗi nút với các liên kết thích hợp có vẻ hợp lý, nhưng đó không phải là khả năng duy nhất. –

+2

+1 Để ghi rõ bài tập về nhà * và yêu cầu không có câu trả lời trực tiếp *. –

+0

Cảm ơn bạn đã cho tôi gợi ý đúng!Tôi đã triển khai một hàm tạo bản sao sâu cho các nút của mình, để có thể trả về một đối tượng của nút "cuối cùng" với cấu trúc tham chiếu cho nút cha và nút cha của nó ... để giữ nguyên. Sử dụng nó cho thuật toán tìm kiếm cây – mtosch

Trả lời

21

Bạn phải cẩn thận với Bước 1 và một phần của Bước 2. Bước 1 nên cấp phát một nút mới và sử dụng nút đó làm head. Ở Bước 2, phần khoảng next = v.next, trừ khi bạn có ý định tạo bản sao nông, không chính xác.

Khi bạn sao chép một vùng chứa, chẳng hạn như danh sách được liên kết, bạn có thể muốn có một bản sao sâu, do đó, cần phải tạo các nút mới và chỉ sao chép dữ liệu. Các con trỏ nextprior trong các nút của danh sách mới nên tham chiếu đến các nút mới mà bạn tạo cụ thể là cho danh sách đó chứ không phải các nút từ danh sách gốc. Các nút mới này sẽ có các bản sao của dữ liệu tương ứng từ danh sách gốc, do đó danh sách mới có thể được coi là một giá trị hoặc bản sao sâu.

Dưới đây là một bức tranh miêu tả sự khác nhau giữa nông và sao chép sâu:

enter image description here

Chú ý trong các Sâu Sao chép phần của sơ đồ, không ai trong số các nút trỏ đến nút trong danh sách cũ . Để biết thêm thông tin về sự khác biệt giữa bản sao nông và sâu, hãy xem bài viết trên Wikipedia về số object copying.

+3

Ooh! Những bức ảnh! Điều đó chắc chắn sẽ giúp làm rõ. +1 –

4
  1. Bạn không nên đặt this->head = v.head. Bởi vì đầu chỉ đơn giản là một con trỏ. Những gì bạn cần làm là tạo một đầu mới và sao chép các giá trị riêng lẻ từ v.head vào đầu mới của bạn. Nếu không, bạn sẽ có hai con trỏ trỏ đến cùng một thứ.

  2. Sau đó, bạn sẽ phải tạo một con trỏ tạm thời Elem bắt đầu bằng v.head và lặp qua danh sách, sao chép giá trị của nó vào con trỏ mới Elem vào bản sao mới.

  3. Xem ở trên.

+3

Lưu ý: Khi bạn sao chép giá trị của nó, hãy _not_ sao chép con trỏ của nó. Nói chung, đừng bao giờ sao chép một con trỏ trong một hàm tạo bản sao. Sao chép đối tượng đang được chỉ vào. –

2

Nhà xây dựng bản sao của bạn nên sao chép? Nó sẽ sao chép pri - dễ dàng. Nó nên sao chép info - cũng dễ dàng. Và nếu next không phải là null, nó cũng nên sao chép nó. Làm cách nào để sao chép next? Hãy suy nghĩ đệ quy: Vâng, next là một Elem *Elem có một hàm tạo bản sao: Chỉ cần sử dụng nó để sao chép tham chiếu Elem và tham chiếu đến nó.

Bạn cũng có thể giải quyết điều này theo cách lặp lại, nhưng giải pháp đệ quy trực quan hơn nhiều.

+0

Đúng, điều này khá dễ dàng nếu Elem có một nhà xây dựng bản sao –

+0

Chúng tôi đang cố ý không thực hiện đệ quy, vì vậy chúng tôi có thể thấy điều gì xảy ra dễ dàng hơn. Anh ấy chỉ cho chúng tôi cách đệ quy và cố ý nói rằng chúng tôi sẽ thất bại nếu chúng tôi làm theo cách này. O_O – Joshua

+0

@Joshua: Bạn nên đề cập đến những hạn chế như vậy. – Landei

0

Vì vậy, đây là câu trả lời của tôi (không biết nếu điều đó phù hợp với bài tập về nhà của bạn hay không - giáo viên hướng dẫn có xu hướng có những ý tưởng riêng của họ đôi khi;):

chung một constructor sao chép nên "sao chép" đối tượng của bạn. I E. nói rằng bạn đã liên kếtList l1, và thực hiện một linkedList l2 = l1 (gọi là linkedList :: linkedList (l1)), sau đó l1 và l2 là các đối tượng hoàn toàn riêng biệt theo nghĩa là sửa đổi l1 không ảnh hưởng đến l2 và ngược lại.

Khi bạn chỉ định các con trỏ, bạn sẽ không nhận được một bản sao thực, vì dereferencing và sửa đổi một trong hai ảnh hưởng đến cả hai đối tượng.

Bạn muốn tạo bản sao thật sâu của mọi phần tử trong danh sách nguồn của bạn (hoặc chỉ sao chép theo yêu cầu, nếu bạn muốn được ưa thích).

0

Bạn quên dòng return; sau

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

Bạn cần phải nhận ra, phải không?

Các vấn đề liên quan