繁体   English   中英

优化循环C ++

[英]Optimizing For Loops C++

我有一个小的功能,可以通过一个向量循环找到给定的动物并返回其栖息地。 我需要对其进行优化,但是我的工作陷入僵局。 突然出现在我size_t三件事是size_ti++和我正在遍历向量的事实。 我读到size_t非常适合具有大尺寸索引的数组。 我知道pre-incrementpost-increment pre-increment更好,因为它会更改原始值,而不是创建临时和增量。 但是编译器通常无论如何都会优化这一小差异。 最后,我想到的最后一件事是该向量可能未排序,因此性能下降。 我当时正在考虑根据动物的物种变量对向量进行排序,然后可能将其移植到BST进行搜索,因为时间复杂度为O(log(n)) 这是我正在使用的代码:

string GetAnimalHabitat(vector<Animal> animals, string species)
{
    for (size_t i = 0; i < animals.size(); i++)
    {
        if (animals[i].species == species)

        {
            return animals[i].habitat;
        }
    }
    return "Animal not within records.";
}

有什么我可能会缺少的东西可以改善此功能吗? 任何提示都很好。 谢谢!

一个std::map肯定比在这里遍历一个向量更好:

string GetAnimalHabitat(const map<string, string>& animals, const string& species)
{
    auto search = animals.find(species);
    if (search != animals.end())
        return search->second;
    return string("Animal not within records.");
}

但是,它需要先构建地图。 但是,一次构建就足够了,您只需向其添加新的密钥对:

map<string, string> build_map(const vector<Animal>& animals)
{
    map<string, string> ret;
    for (const auto& x : animals)
        ret[x.species] = x.habitat;
    return ret;
}

您可以做的一件事是通过执行以下操作来减少调用.size()方法的次数:

size_t vectorSize = animals.size();
for (size_t i = 0; i < vectorSize; i++)
{
    if (animals[i].species == species)

    {
        return animals[i].habitat;
    }
}

另一个较小的问题是将i++更改为++i 这样做的目的是避免每次i的值递增时都将其存储在寄存器中。

从高层次上讲,您希望在每次调用此函数时停止对向量及其所有元素进行完整复制。 如果需要优化,我假设向量很大,那么为什么不将引用传递给const向量呢?

其次,另一个问题是向量中有多少个元素将与您的输入字符串匹配? 如果只是少数几个,则扫描整个向量会加载大量内存,只是为了查看它来决定您是否不需要它。 由于您是在第一场比赛后返回的,因此可以合理地认为每个物种中最多有一个,并且在这种情况下,关联容器会更好。

一些对延迟敏感的地方会将数据划分为不同的组,因此不需要“过滤”。 只需查看您关心的一组事物,然后进行处理即可。

要考虑的另一件事是,字符串比较比整数比较慢得多。 您可以将种类预先哈希到类中,在循环之前对种类参数进行哈希,然后比较哈希值。 如果它们相等,则比较字符串以确保它是真正的匹配。

但是我的猜测是,您大部分时间都花在复制输入和输出上。

std::unordered_map最有意义,因为顺序并不重要

string GetAnimalHabitat(const std::unordered_map<string, string>& animals, const string& species)
{
    auto search = animals.find(species);
    if (search != animals.end())
        return search->second;
    return string("Animal not within records.");
}

但是,它需要先构建地图。 但是,一次构建就足够了,您只需向其添加新的密钥对。 请注意,第一次传递空的unordered_map,然后传递新值的向量和当前映射:

build_map(const std::vector<Animal>& animals, std::unordered_map<string_string> * ret)
{
    for (const auto& x : animals)
        ret[x.species] = x.habitat;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM