2012-01-25 12 views
3

私は、std::list<>では、リスト自体のためにswap関数がアンカーノードを交換することによって行われると仮定しています。ノードは、前のノードにアクセスし、前のノードの次のポインタを他のリストのアンカーを指すように容易に更新することができる。しかし、これはstd::forward_listで行うことはできません(まあ、それはちょうど非常に高価です)。C++でのstd :: forward_list swap()の実装

私の前提が正しい場合、swap()は効率的にstd::forward_listに実装されていますか?そして、私たちがそれに就いている間に、はiteratorのためにどのように実装されていますかstd::forward_list

答えて

5

std::forward_listしたがって、あなたは、単にswap()操作を達成するために、リストのheadtailポインタを入れ替えることができ、単にstd::listのような単一リンクではなく、二重リンクリストです。

+0

私は 'std :: list'が内部的に循環リストになっていて、' std :: forward_list'でも同じことを仮定していました。私はそれが完全に実装に依存していると推測しています。 – Samaursa

+0

それらが循環リンクリストであっても、ノード自体のポインタを更新する必要はありません。リスト全体がスワップされているため、ノードリンクのいずれも変更されません。すべての変更は 'std :: list'からノードまでのポインタです。 – bames53

+0

@ bames53:循環リストの場合、各ノードは次のノードまたはリストの末尾を指しています。そして、リストの末尾が先頭を指していて、先頭の要素を指しています。次に、テールポインタをスワップする方法は、テールを指すノードを調整する必要があり、リスト全体をトラバースしない限り、テールポインタに到達できないためです。または、テールポインタは、最後のノードだけでなく、ヘッドを指すオブジェクトですか? – Samaursa

3

これは完全に実装固有のものですが、クラスが最初と最後のリンクリストセルへのポインタを格納するだけでフォワードリストが実装された場合、スワップはこれらの2つのポインタを交換できます。フォワードリンクリストはバックポインタを持たないので、これ以上更新する必要はなく、操作全体はO(1)で行うことができます。

イテレータを使用したスワップでは、実際には2つのリスト間でリンクされたリストセルを交換しません。 2番目のイテレータによって参照されるセルへの最初のイテレータポイントがあり、その逆もあります。あなたが指し示されている値を入れ替える場合は、リンクされたリストのセル内のオブジェクトを変更して値を変更するだけで済みます。あなたは何らかの形でリストを再編成する必要はありません。

+0

ああ、もちろん!私は何らかの理由でノードiteratorと混同していました。(+1) – Samaursa

+1

私はforward_listにテールポインタを格納する必要はなく、一般的な空のイテレータをエンドイテレータとして使うことができます。 –

3

私はあなたが混乱していると思う(またはあなたが求めているものについて混乱している)。 std :: forward_list :: swap(std :: forward_list & other)は簡単です。各リストオブジェクトはstd :: listと同様にリストの先頭(および他のメンバー変数)へのポインタを交換します。

iteratorオブジェクトには、スワップメソッドはありません。含まれているオブジェクトは、グローバルスワップメソッドを使用するかもしれないし、使用するかもしれませんが、オブジェクト上で動作し、リスト自体またはそのノードを変更しません。

関連する問題