私はさまざまなstd :: listオブジェクトを扱うコードをいくつか持っていますが、現在は非常に非効率的な方法でそれらの間でコンテンツを転送しています( 1つのリストの任意のセクション、およびその要素を1つずつ第2のリストに移動する)。std :: list :: spliceと他のリストコンテナの複雑さ
list<string> list1, list2;
list1.push_back("a");
list1.push_back("b");
list1.push_back("c"); // list1: "a", "b", "c"
list<string>::iterator iterator1 = list1.begin();
iterator1++: // points to "b"
list2.push_back("x");
list2.push_back("y");
list2.push_back("z"); // list2: "x", "y", "z"
list<string>::iterator iterator2 = list2.begin();
iterator2++; // points to "y"
list1.splice(iterator1, list2, iterator2, list2.end());
// list1: "a", "y", "z", "b", "c"
// list2: "x"
私はの複雑さに関する質問がある:私は今と私のコードを置き換えるつもりはstd ::リスト::スプライス機能、を知っていた前に、私には、例えば、いくつかの時間前にこのコードを書きましたスプライス機能それは(私の例では)iterator2とlist2.end()にスプライシングされている最初と最後の要素の間の範囲で線形複雑度を有するべきである
http://www.cplusplus.com/reference/stl/list/splice/
、ソースは、このことを示唆している:このソースによれば、イテレーターの進歩によるものです。私はこれで生きることができますが、私は一定の複雑さを望んでいました。
私の仮定(私はこのソースを見つける前)であった。このような何かスプライス機能することを:「x」および「y」との間のリンクを切断
- を
- 「Z」との間のリンクを切断そしてlist2.end()
- フォーム( "X" とlist2.end間のリンク)
- "a" および "Y" との間のリンクを形成する "a" および "b"
- との間のリンクを切断します
- "y"と "b"の間のリンクを形成する
こうして両方のリストを復元してチェーンを完成させます。
同じ原則が任意のサイズのリストに適用されます。スプライス関数がイテレータを進める必要がある場所がわかりません。イテレータの仕事をするために必要なイテレータをすべて提供しているからです。
私の質問は、どのようにC + +の仕様はこれを扱うのですか?スプライスの開始点と終了点でのみリンクを壊して再形成するのですか、それとも各リンクを1つずつ進めますか?後者の場合、他のリストコンテナ(QTなど)が前者を提供していますか?私のコードはシミュレーションプログラムの内部ループの内部にあるので、線形の複雑さよりもむしろ一定にすることは非常に貴重です。
ありがとう、その説明は意味をなさない。その場合、スプライス関数の一部としてスプライスされた範囲のサイズをユーザーに指定することによって、サイズとスプライスの両方を一定にすることはできません(また、他の多くのC++機能の場合と同様に、この情報を正しく提供するためにユーザーに責任を負う) – JBentley
C++ 11を少し見て、私はちょっと困惑しています。一方で、テーブル96は 'size()'は一定の複雑さを持つべきだと言います。一方、§23.3.5.5/ 12では、「スプライス」も複雑さが一定であるとしています。私はあなたがそれをどうやってやろうとしているのか分かりません。私はcomp.std.C++に関するいくつかの議論を数年前に覚えています - 私は再びそれを探しなければならないかもしれません。 –
@JonBentleyはい、それは珍しいことですが、完全にその情報を手に入れることは可能です。 (スプライスの私の経験は、再帰的な分割プログラムにありました。それは、おそらくそれらのサイズを独立して追跡することができました)おそらく、ライブラリ標準化委員会に小さな提案をするでしょう。 – Potatoswatter