[英]Sorting a std::list using iterators
是否有可能對由std::sort
這樣的迭代器定義的列表(列表的子集)進行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);
}
該函數將您要排序的節點傳輸到排序器列表中(第一個迭代器參數是插入節點的位置,在本例中是列表的結尾)。
排序器列表(顯然)進行排序,然后將排序后的內容傳輸回源列表,完全轉移到最初填充的原始子范圍內。
由@TC評論下一步是概括它。 它可以像這樣制作成模板:
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的實現可以做到這一點,而無需填充另一個容器。 它是一種自上而下的合並排序,效率低於之前的自下而上合並排序,但它避免了分配先前版本所做的內存,因為先前版本分配了一小部分列表。 Psuedo代碼看起來像這樣:
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;
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.