在 C++ 中加速算法

Posted

技术标签:

【中文标题】在 C++ 中加速算法【英文标题】:Speeding up algorithm in C++ 【发布时间】:2016-05-13 17:46:39 【问题描述】:

TL;DR:我的代码在 Java 中“很快”,但在 C++ 中却慢得要命。为什么?

#include <iostream>
#include <vector>
#include <map>
#include <algorithm>


using namespace std;

int read(string data, int depth, int pos, vector<long>& wantedList) 
    // 91 = [
    if (data.at(pos) == 91) 
        pos++;
        // Get first part
        pos = read(data, depth + 1, pos, wantedList);
        // Get second part
        pos = read(data, depth + 1, pos, wantedList);
     else 
        // Get the weight
        long weight = 0;
        while (data.length() > pos && isdigit(data.at(pos))) 
            weight = 10 * weight + data.at(pos++) - 48;
        
        weight *= 2 << depth;
        wantedList.push_back(weight);
    
    return ++pos;



int doStuff(string data) 
    typedef map<long, int> Map;
    vector<long> wantedList;
    Map map;
    read(data, 0, 0, wantedList);
    for (long i : wantedList) 
        if (map.find(i) != map.end()) 
            map[i] = map[i] + 1;
         else 
            map[i] = 1;
        
    

    vector<int> list;
    for (Map::iterator it = map.begin(); it != map.end(); ++it) 
        list.push_back(it->second);
    
    sort(list.begin(), list.begin() + list.size());
    cout << wantedList.size() - list.back() << "\n";
    return 0;



int main() 
    string data;
    int i;
    cin >> i;
    for (int j = 0; j < i ; ++j) 
        cin >> data;
        doStuff(data);
    
    return 0;

我刚刚尝试了我的第一个 C++ 项目,它是用 Java 重写的代码。 最初的任务是计算需要更改多少数字才能“平衡”输入,假设高于某物的每一层的重量是低层的两倍

例如 [1,2] 需要 1 次更改(1->2 或 2->1 以便两边相等,而 [8,[4,2]] 需要 1 次更改(2-> 4)为了让“低级”变成8级,从而在高级上具有同等权重。有兴趣的可以在这里找到问题:

Problem link

对于那些想知道的人来说,这是关于算法的学校作业,但我不是在寻求帮助,因为我已经用 Java 完成了它。问题是我的算法在 C++ 方面似乎很糟糕。

在 Java 中,我得到大约 0.6 秒的时间,而在 C++ 中,“相同”代码给出 >2 秒(超出时间限制)。

有人愿意告诉我这是为什么吗?在处理这类问题时,我的印象是 C++ 应该比 Java 快。

【问题讨论】:

这可能更适合codereview 网站。也就是说,由于您是 C++ 新手,您是否打开了编译器优化? Java 默认启用它们,但对于 C++,您通常必须启用它们。 data 有多大?你到处抄袭 你可能想通过引用传递你的字符串作为开始。 你根本不需要list。您正在对map 中的所有值进行排序,然后取最大值。您可以简单地使用std::max_element 获得map 中的最大值。如果您不需要按键排序,也可以使用std::unordered_map,这可能更好地反映您的 Java 代码。 @nikolap 哈哈,谢谢伙计!这将时间从 >2 缩短到 0.13 【参考方案1】:

可能的原因之一是复制。

每当您在 C++ 中按值传递某些内容时,都会创建一个副本。对于doubleint 或指针之类的东西,这不是问题。

但是对于像std::string 这样的对象,复制可能会很昂贵。由于您不修改 data,因此通过 const 引用传递它是有意义的:

int read(const string &data, int depth, int pos, vector<long>& wantedList)

【讨论】:

以上是关于在 C++ 中加速算法的主要内容,如果未能解决你的问题,请参考以下文章

我可以阻止 C++ dll 在 Python Ctypes 中加载吗?

讲讲网络模块中加解密那点儿事--AES+BASE64

C++使用cuBLAS加速矩阵乘法运算

算法与数据结构整理-排序

使用 C++ 加速 Python

在 C++ 中加速图像过滤器