web-dev-qa-db-ja.com

リンクリストのコピーコンストラクターの作成

これは宿題です

私は自分のC++クラスのリンクリストクラスの実装に取り​​組んでおり、コピーコンストラクターは非常に混乱しています。

リンクされたリストは、Elemsと呼ばれる構造体で構成されています。

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

infoはElemに格納される個別のカスタムクラスです。

コピーコンストラクターの署名は次のとおりです。

linkedList::linkedList( const linkedList &v )

私が抱えている問題は、主に私のロジックを取り、実際にそれをコードとして書くことです。

私の一般的な考えは:

  1. 頭をv.headに設定します(head = v.head)
  2. Elemの値をvに設定します(pri = v.pri、info = v.info、next = v.next)
  3. ステップ2を繰り返して繰り返します。

これは一般的な考えですか?

どんな助けでも素晴らしいでしょう。 これは宿題ですので、直接回答しないでください!

お時間をいただきありがとうございます

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

皆さん、ありがとうございました!

私はそれを理解していると思います:

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

私はそれがうまくいくと確信しています。私は助けるためにいくつかの論理的な絵を描きました、そして、私はどんな問題にも遭遇しませんでした。

21
Joshua

ステップ1とステップ2の一部に注意する必要があります。ステップ1で新しいノードを割り当て、それをheadとして使用する必要があります。ステップ2では、next = v.next、あなたの意図が浅いコピーを作成することでない限り、正しくありません。

リンクされたリストなどのコンテナをコピーする場合、おそらく深いコピーが必要になるため、新しいノードを作成してデータのみをコピーする必要があります。新しいリストのノードのnextおよびpriorポインタは、そのリストに対して作成した新しいノードを特定してからのノードではなく、元のリスト。これらの新しいノードには、元のリストからの対応するデータのコピーがあるため、新しいリストは値ごと、またはディープコピーと見なすことができます。

以下は、浅いコピーと深いコピーの違いを描いた画像です。

enter image description here

図のDeep Copy部分で、どのノードも古いリストのノードをポイントしていないことに注意してください。浅いコピーと深いコピーの違いの詳細については、ウィキペディアの記事 オブジェクトのコピー を参照してください。

22
  1. this->head = v.headは設定しないでください。頭は単なるポインタだからです。新しいヘッドを作成し、v.headから新しいヘッドに値を個別にコピーする必要があります。それ以外の場合は、同じものを指す2つのポインターがあります。

  2. 次に、v.headで始まる一時的なElemポインターを作成し、リストを反復処理して、その値を新しいElemポインターにコピーして、新しいコピーにする必要があります。

  3. 上記を参照。

4
Zeenobit

コピーコンストラクターは何をコピーする必要がありますか? priをコピーする必要があります-簡単です。 info-も簡単にコピーできます。そして、nextがnullでない場合は、それもコピーする必要があります。 nextをコピーするにはどうすればよいですか?再帰的に考える:まあ、nextElem *、およびElemにはコピーコンストラクターがあります。これを使用して、参照されているElemをコピーし、参照するだけです。

これを反復的に解決することもできますが、再帰的ソリューションの方がはるかに直感的です。

2
Landei

だからここに私の答えがあります(それがあなたの宿題に合うかどうかわからない-インストラクターは時々独自のアイデアを持っている傾向があります;):

通常、コピーコンストラクターはオブジェクトを「コピー」する必要があります。つまりlinkedList l1があり、linkedList l2 = l1(linkedList :: linkedList(l1)を呼び出す)を実行するとします。l1とl2は、l1の変更がl2に影響を与えず、その逆も同様であるという意味で、完全に別個のオブジェクトです。

ポインターを割り当てるだけでは、実際のコピーは得られません。どちらかを逆参照して変更すると、両方のオブジェクトに影響するためです。

ソースリスト内のすべての要素の実際の詳細なコピーを作成したい場合(または、ファンシーになりたい場合は、オンデマンドコピーのみを実行する場合)。

0
cli_hlt

行を忘れましたreturn;

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

外に出る必要がありますよね?

0
andy