производительность — C ++ Как бы я сделал этот код более эффективным?

У меня есть массив слов, и у меня есть текстовый файл. То, что я хочу сделать, это использовать массив слов и искать в текстовом файле, подсчитать, сколько раз каждое слово в массиве появляется в текстовом файле.

Я думал об использовании For Loop, но это просто дало мне общее количество слов, а не отдельные слова для каждого. Я не могу поместить текстовый файл в массив, так как в текстовом файле около 40000 слов.

После подсчета я хочу разделить каждый отсчет на целочисленное значение, известное как «масштаб». А затем умножьте строку на новый номер счета.

Так что в настоящее время я делаю это, как показано ниже. Есть ли способ сделать это более эффективным?

Любая помощь с благодарностью.

Массив слов = тестовые слова.

Имя файла = testF.

inWord = каждое слово в файле.

while(testF >> inWord)
{if (inWord == testwords[0]){
count1++;
}
if (inWord == testwords[1]){
count2++;
}
if (inWord == testwords[2]){
count3++;
}
if (inWord == testwords[3]){
count4++;
}
if (inWord == testwords[4]){
count5++;
}
if (inWord == testwords[5]){
count6++;
}
if (inWord == testwords[6]){
count7++;
}
if (inWord == testwords[7]){
count8++;
}
}
cout << testwords[0] << " " << count1 << " " << s1.append(count1/scale, '*') << endl;
cout << testwords[1] << " " << count2 << " " << s2.append(count2/scale, '*') << endl;
cout << testwords[2] << " " << count3 << " " << s3.append(count3/scale, '*') << endl;
cout << testwords[3] << " " << count4 << " " << s4.append(count4/scale, '*') << endl;
cout << testwords[4] << " " << count5 << " " << s5.append(count5/scale, '*') << endl;
cout << testwords[5] << " " << count6 << " " << s6.append(count6/scale, '*') << endl;
cout << testwords[6] << " " << count7 << " " << s7.append(count7/scale, '*') << endl;
cout << testwords[7] << " " << count8 << " " << s8.append(count8/scale, '*') << endl;

2

Решение

Прежде чем беспокоиться об эффективности, вам следует побеспокоиться о подходе. Вы не используете логические структуры данных. Вместо 8 отдельных отсчетов сохраните массив отсчетов. Или еще лучше, держите карту слова -> считать.

К счастью в этой ситуации, более чистый код будет соответствовать гораздо более быстрому выполнению.

В частности, используйте std::map<std::string, size_t>,

В качестве альтернативы, если вы используете C ++ 11, вы можете использовать std :: unordered_map для повышения производительности.

Предполагая, что вы читаете свои слова из cin:

std::map<std::string, size_t> counts;

std::string word;

while (std::cin >> word) {
++counts[word];
}

for (std::map<std::string, size_t::const_iterator it = counts.begin(),
end = counts.end(); it != end; ++it) {
std::cout << "The word '" << it->first << " appeared "<< it->second << " times" << std::endl;
}

Документация для std :: map.

Документация для std :: unordered_map.

Что бы это ни стоило, std :: unordered_map (вполне вероятно, всегда) реализован как хэш-карта, и std :: map реализован (вполне вероятно, всегда) с использованием сбалансированного бинарного дерева в качестве вспомогательной структуры.

4

Другие решения

Настроить std::map<std::string, unsigned long long>отсканируйте документ слово за словом и увеличьте счетчик для каждого слова:

std::map<std::string, unsigned long long> wordMap;

std::string word; // read words into this string
...
wordMap[word]++; // increase counter each time a word is found. First call will insert 0.

Затем вы можете перебрать массив слов, проверяя записи на карте:

for (unsigned int i = 0; i < nWords; ++i)
{
std::cout << "Word " << testWords[i] << " was found " << wordMap[testWords[i]] << " times\n";
}

Каждый раз, когда новое слово найдено, myMap[word] вставит пару ключ-значение word : 0,

Если у вас есть C ++ 11, вы можете попробовать с std::unordered_map и выберите тот, который работает лучше всего.

1

Имея только 8 значений для сравнения, вы, скорее всего, сможете найти лучший алгоритм хеширования, чем в std. Он может состоять только из первых двух символов, или последнего символа, или длины строки:

while (std::cin >> word) {
int i=my_hash(word);
if (word==my_sparse_hash_table[i].word) my_sparse_hash_table[i].count++;
}

Просто используя ваш метод:

while (std::cin >> word) {
for (int i=0;i<N;i++)
if (word == myTable[i].word) { myTable[i].count++; break; }
}  // earlies break out of the loop

микро-оптимизации включают перемещение найденной записи в начало массива myTable.

0

Все остальные ответы здесь являются очень хорошими предложениями. Одна небольшая оптимизация, которую вы можете сделать, это использовать еще в вашем существующем коде.

if (inWord == testwords[0])
{
count1++;
}
if (inWord == testwords[1])
{
count2++;
}

может быть заменено

if (inWord == testwords[0])
{
count1++;
}
else if (inWord == testwords[1])
{
count2++;
}

Концепция заключается в том, что если в слове соответствует элементу 0, вряд ли он соответствует любому из других элементов.

В любом случае Профайлеры ты друг?

0
По вопросам рекламы [email protected]