我如何优化这个C++
How can I optimise this C++?
我正在尝试通过解决一些旧的谷歌代码堵塞问题来练习C++。我发现一个相对简单的方法是将字符串中的单词颠倒。可以在这里找到https://code.google.com/codejam/contest/351101/dashboard#s=p1
到目前为止,我有:
#include<iostream>
using namespace std;
int main(){
int n = 0;
cin >> n;
string rev = "";
string buf = "";
string data = "";
getline(cin, data);
for(int _ = 0; _ < n; _++){
getline(cin, data);
rev = "";
buf = "";
for(char& c : data) {
buf += c;
if(c == ' '){
rev = buf + rev;
buf = "";
}
}
cout << "Case #" << _ + 1 << ": " << buf << " " << rev << endl;
}
return 0;
}
它似乎跑得很快。当使用大约1.2E6
个案例的测试文件运行time ./reverse < in > /dev/null
时,使用g++ -O3
编译大约需要3.5
秒。
因此,作为一个基准,我在python 中创建了一个解决方案
#!/usr/bin/env python
from sys import stdin, stdout
stdout.writelines(map(lambda n: "Case #%d: %sn" % (n + 1, ' '.join(stdin.readline().split()[::-1])), xrange(int(stdin.readline()))))
然而,当我在pypy
和time pypy reverse.py < in > /dev/null
下运行它时,只需要大约1.95
秒。
理论上,pypy
是用C++编写的,C++不应该那么快吗?如果是这样,如何优化此代码以使其更快?
一个简单的不复制/不分配标记器是讨厌的std::strtok
以下内容在我的测试中击败了您的python程序
#include <iostream>
#include <iterator>
#include <algorithm>
#include <vector>
#include <cstring>
int main()
{
std::cout.sync_with_stdio(false); // we don't need C in the picture
std::string line;
getline(std::cin, line);
int num_cases = stoi(line);
std::vector<char*> words;
for(int n = 0; getline(std::cin, line) && n < num_cases; ++n)
{
words.clear();
char* p = std::strtok(&line[0], " ");
while (p) {
words.push_back(p);
p = std::strtok(nullptr, " ");
}
std::cout << "Case #" << n + 1 << ": ";
reverse_copy(words.begin(), words.end(),
std::ostream_iterator<char*>(std::cout, " "));
std::cout << 'n'; // never std::endl!
}
}
PS:您的C++和python输出不完全匹配;该程序与您的C++输出相匹配
我认为当你连接字符串时,你的C++代码会进行相当多的内存复制(std::string的大多数实现都会在内存中保持整个字符串的连续性。)我认为下面的代码在没有复制的情况下可以做到这一点,但我没有对它进行太多测试。至于为什么python表现得很好,我不完全确定。
#include<iostream>
int main()
{
size_t numCases;
std::cin >> numCases;
std::cin.ignore();
for( size_t currentCase = 1; currentCase <= numCases; ++currentCase )
{
std::cout << "Case #" << currentCase << ": ";
std::string line;
getline(std::cin, line);
size_t wordEnd = line.length() - 1;
size_t lastSpace = std::string::npos;
for ( int pos = wordEnd - 1; pos >= 0; --pos )
{
if ( line[pos] == ' ' )
{
for ( int prt = pos + 1; prt <= wordEnd; ++prt )
std::cout << line[prt];
std::cout << ' ';
lastSpace = pos;
wordEnd = pos - 1;
--pos;
}
}
for ( int prt = 0; prt < lastSpace; ++prt )
std::cout << line[prt];
std::cout << std::endl;
}
return 0;
}
您可以利用算法和迭代器库来实现这一切,而不是使用两个缓冲区和大量串联。我不确定它会快多少(尽管我想会快很多),但它也更紧凑。
#include<iostream>
#include<algorithm>
#include<iterator>
#include<sstream>
using namespace std;
int main(){
int n = 0;
cin >> n;
string data = "";
getline(cin, data);
for(int _ = 0; _ < n; _++){
getline(cin, data);
stringstream ss(data);
reverse(istream_iterator<string>(ss), istream_iterator<string>());
cout << "Case #" << _ + 1 << ": " << ss.str() << endl;
}
return 0;
}
相关文章:
- 空基优化子对象的地址
- 关闭||运算符优化
- 如何解决gcc编译器优化导致的centos双编译器设置中的分段错误
- 返回值优化:显式移动还是隐式
- 人脸跟踪arduino代码的优化
- 使用仅使用一次的变量调用的复制构造函数.这可能是通过调用move构造函数进行编译器优化的情况吗
- 纯函数,为什么没有优化
- 为什么大多数 pair 实现默认不使用压缩(空基优化)?
- 如何以优化的方式同时迭代两个间距不相等的数组
- 小字符串优化(调试与发布模式)
- 浮点定向舍入和优化
- Visual Studio 调试优化如何工作?
- 为什么开关的优化方式与 c/c++ 中的链接不同?
- 线性优化目标函数中的绝对值
- GCC 会优化内联访问器吗?
- gcc 如何优化此循环?
- 如何防止 CUDA-GDB 中的<优化输出>值
- 为什么我的程序在 O0 和 O2 的优化级别返回不同的结果
- 这个C++编译器优化(在自身的实例上调用对象自己的构造函数)的名称是什么,它是如何工作的?
- 使用 std::p air 进行返回值优化