使用迭代器对 std::list 进行排序
Sorting a std::list using iterators
是否可以像std::sort
一样对迭代器定义的列表的一部分(列表的子集(进行排序?
即对于std::list
唯一可用的排序是通过方法 (http://en.cppreference.com/w/cpp/container/list/sort(,我希望能够使用std::sort
从其迭代器中对列表的一部分进行排序。 例如
std::sort(listItrStart, listItrEnd, [](T& a, T& b){ return a.something() < b.something()});
我很欣赏一旦对项目完成移动操作,迭代器就会失效,我认为这意味着在下一次"比较"之前,如果不重新迭代到所需的位置,就无法通过迭代器对列表进行排序?
在这种情况下,在不为此过程填充另一个容器(如果有(的情况下对列表的子项进行排序的最佳实践是什么?
非常感谢。
填充另一个容器是不可避免的。但是,您不必移动或复制自己的任何数据。您可以使用std::list::splice
提取要处理的节点并将其重新插入到排序顺序中。
using list_t = std::list<widget>;
void process(list_t& in, list_t::const_iterator begin, list_t::const_iterator end) {
list_t sorter;
sorter.splice(sorter.end(), in, begin, end);
sorter.sort();
in.splice(end, sorter);
}
该函数将您希望排序的节点传输到排序器列表中(第一个迭代器参数是插入节点的位置,在本例中为列表的末尾(。
排序器列表被排序(显然(,然后将排序的内容传输回源列表,正好转移到它最初填充的原始子范围中。
正如@T.C.所评论的那样。下一步是概括它。它可以制作成一个模板,就像这个模板一样:
template<class List, class Compare = std::less<>>
void sort_subrange(List& in,
typename List::const_iterator begin,
typename List::const_iterator end,
Compare c = {}) {
List sorter(in.get_allocator());
sorter.splice(sorter.end(), in, begin, end);
[[maybe_unused]] ScopeGuard sg([&]() { in.splice(end, sorter); });
sorter.sort(std::move(c));
}
比较器在这里也被视为一个参数,sorter
是使用输入分配器的副本构造的,以实现最大的通用性。拼接回来是在我们选择的范围防护中完成的,以支持比较函数抛出的情况,所以我们的基础现在被覆盖了。
这是一个活生生的例子,出于说明目的,它对范围守卫有一个幼稚且有些愚蠢的实现。
是否可以对由迭代器定义的列表(列表的子集(的一部分进行排序,例如 std::sort 确实如此?
我假设你的意思是std::list::sort。Visual Studio 2015的实现可以做到这一点,而不必填充另一个容器。它是一种自上而下的合并排序,其效率低于先前的自下而上的合并排序,但它避免了分配先前版本所做的内存,因为先前版本分配了一小组列表。伪代码看起来像这样:
right = std::next(right, 1); // right = end of sub-list
size = std::distance(left, right);
left = MyListSort(list, left, right, size);
right = std::next(left, size-1); // right = last element of sub-list
// ...
MyListSort(list, left, right, size)
{
if(size < 2)
return left;
mid = std::next(left, size/2);
MyListSort(list, left, mid, size/2);
MyListSort(list, mid, right, size-size/2);
firstloop = true;
newleft = left;
while(true){
if(*left <= *mid){
if(++left == mid)
return newleft;
} else {
if(firstloop)
newleft = mid;
list.splice(left, list, mid);
if(++mid == right)
return newleft;
}
firstloop = false;
}
}
- 使用std::multimap迭代器创建std::list
- 来自 std::list 的迭代器 .end() 按预期返回"0xcdcdcdcdcdcdcdcd"但 .begin()
- 二叉排序树无法编译
- 仅使用绝对值对数组进行排序,并在C++中显示实际值
- 使用迭代器对 std::list 进行排序
- std::list::使用自定义比较器排序时出现分段故障
- 为什么tha std :: list ::排序不起作用
- 为什么没有针对STD :: MAP的find/lower_bound过载,而STD :: list没有排序的过载
- 使用 myclass::operator[](int i) 对 std::list<myclass*> 进行排序
- 如何使用list::sort()对STL列表对象进行排序,同时将自定义排序函数作为参数传递给list::排序
- 使用 std::sort 对 std::list 进行排序
- 在排序的std::list中搜索的复杂性是多少
- 如何在 std::vector 中查找重复项<strings>并返回一个 std::list 它们按字母顺序排序,在该结果列表中没有重复项
- std::list指针上排序算法的STL谓词
- 当需要成员数据时,如何对std:list进行排序
- 如何将元素添加到List (c++)中进行排序
- std::list::排序和指向元素的指针
- List的c++排序函数
- 插入时保持stdvector/list排序,或对所有对象进行排序
- 部分排序 std::list