在C++中遍历列表的一部分

Iterate through part of a list in C++

本文关键字:一部分 列表 遍历 C++      更新时间:2023-10-16

我是C++的新手,我正在研究合并排序的实现,以帮助自己熟悉该语言。

目前,我有一个整数列表,我想创建2个子列表,并将原始列表的前半部分存储在名为"left"的列表中,其余一半存储在一个名为"right"的列表中

例如:假设我的原始列表数据是16、24、56、12、89;我想在这个列表中反复添加16,24添加到新的子列表"left"在"right"子列表中添加56、12、89因此向左将导致[16,24]右边是[56,1289]

这是我现在拥有的代码;我应该在if语句中写什么条件?('l'是函数参数中传递的列表的名称)

    list<int> left, right;
    int midpt = l.size()/2;
    for(listIt = l.begin(); listIt!= l.end(); listIt++){
       if () left.push_back(*listIt);
       if () right.push_back(*listIt);
    }

这可能更容易:

#include <iterator>
#include <list>
auto middle = std::next(l.begin(), l.size() / 2);
std::list<int> left(l.begin(), middle), right(middle, l.end());

这直接从相应的范围构建了两个新的列表leftrightstd::next算法返回一个迭代器,该迭代器是通过将给定的迭代器前进给定的步数来获得的。注意,std::list<int>::size()在C++11中具有恒定的运行时复杂性,尽管迭代迭代器需要线性工作量。

这会起作用。

list<int> left, right;
int midpt = l.size()/2;
int count = 0;
for(listIt = l.begin(); listIt!= l.end(); listIt++){
   if (count++ < midpt)
       left.push_back(*listIt);
   else
       right.push_back(*listIt);
}

使用std::list::insert而不是for循环。尝试-

left.insert(l.begin(), l.begin() + midpt);
right.insert(l.begin() + midpt, l.end());

鉴于std::list定义了一个双链表,可能值得考虑一种稍微不同的方法。您可以考虑将第一个元素添加到left列表中,将最后一个元素添加在right列表中,推进两个迭代器,然后重复(直到迭代器相遇),而不是找到列表的中间部分,将其左边的部分添加到一个列表中,右边的部分添加另一个列表。

大多数其他方法都需要对列表进行线性遍历以找到中间,然后对两侧进行线性遍历来构建两个新列表。换句话说,您遍历列表1.5次。

通过同时从前面和后面遍历,只需遍历列表一次就可以完成整个工作。就big-O复杂性而言,它们是等效的(在两种情况下都是O(N)),但在更实际的情况下,我们可以预期遍历列表一次的速度大约是遍历列表1.5次的一半(尽管根据列表大小,缓存可能会在一定程度上影响这一点)。