У меня есть код, который имеет дело с различными объектами std :: list, и в настоящее время я использую очень неэффективный метод передачи содержимого между ними (я выполняю итерацию через произвольные разделы одного списка и перемещение элементов по одному во второй список). Я написал этот код некоторое время назад, прежде чем я был осведомлен о станд :: Список функций :: сплайсинга, который я теперь намерен заменить свой код, например:Сложность std :: list :: сращивание и другие списки контейнеров
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"
У меня есть вопрос о сложности функция сращивания. Согласно этому источнику:
http://www.cplusplus.com/reference/stl/list/splice/
Он должен иметь линейную сложность в диапазоне между первыми и последними элементами которые сращены в (iterator2 и list2.end() в моем примере), и источник предполагает, что это из-за продвижения итератора. Я могу жить с этим, но я надеялся на постоянную сложность.
Мое предположение (прежде чем я нашел этот источник), что функция сращивания сделать что-то вроде этого:
- Sever связь между «х» и «у»
- Sever связь между «г» и list2.end()
- Форма связь между «х» и list2.end()
- Север связь между «а» и «б»
- Форма связь между «а» и «у»
- Форма связи между «y» и «b»
Таким образом, восстановление обоих списков осуществляется до цепей.
Этот же принцип применяется к спискам произвольного размера. Я не уверен, что я вижу, где необходимо, чтобы функция сращивания продвигала любые итераторы, так как я предоставляю ей все итераторы, которые должны выполнять эту работу.
Так что мой вопрос в том, как спецификация C++ справляется с этим? Разрывает ли он и повторно формирует ссылки только в начальной и конечной точках сращивания или продвигается по каждой ссылке один за другим? Если последнее, какие-либо другие контейнеры списка (например, из QT) предоставляют первое? Мой код находится внутри внутреннего цикла программы моделирования, поэтому предоставление ему постоянной, а не линейной сложности было бы весьма ценным.
Спасибо, это объяснение имеет смысл. Хотя, не было бы в таком случае быть возможным, чтобы размер и сплайсинг были постоянными, требуя, чтобы пользователь поставлял размер сплайсингового диапазона как часть функции сращивания (и, как в случае со многими другими функциями C++, возлагая на пользователя ответственность за правильное предоставление этой информации)? – JBentley
Выполняя немного взгляда на C++ 11, я немного озадачен. С одной стороны, в таблице 96 указано, что 'size()' должен иметь постоянную сложность. С другой стороны, в § 23.3.5.5/12 говорится, что «сращивание» также имеет постоянную сложность. Я не уверен, как вы должны это делать. Я помню некоторое обсуждение на comp.std.C++ несколько лет назад об этом - возможно, мне придется искать его снова. –
@JonBentley Да, это необычно, но вполне возможно иметь эту информацию под рукой. (Мой опыт работы с 'splice' был в рекурсивной программе секционирования, которая могла и, возможно, независимо отслеживать эти размеры.) Возможно, это сделало бы небольшое небольшое предложение для комитета по стандартизации библиотеки. – Potatoswatter