#c #arrays #for-loop
#c #массивы #для цикла
Вопрос:
Я только начал с C . Запрос заключается в том, чтобы » отобразить частоту целых чисел в данном массиве«
Ниже приведен код, который я написал:
#include <iostream>
#include <array>
using namespace std;
int main()
{
array <unsigned int,20> n = {1, 2, 5, 4, 3, 5, 2, 1, 3, 1, 4, 3, 3, 3, 2, 3, 3, 2, 2};
for(size_t i = 0; i < n[i]; i )
{
int count = 0;
for(size_t j = 0; j < n.size(); j )
{
if (n[i] == n[j])
{
count ;
}
}
cout<<"Frequency of "<<n[i]<<" is "<<count<<endl;
}
return 0;
}
Но мой вывод :
Частота 1 равна 3,
частота 2 равна 5,
частота 5 равна 2,
частота 4 равна 2
Почему не отображается частота 3? Я почти уверен, что это глупая ошибка, но я не могу точно указать, где.
Комментарии:
1. Какова цель
i < n[i]
? Кроме того, эту проблему намного проще решить с помощьюstd::map
.2. @cigien да, хорошо. На самом деле это не служит цели. Что мне делать? Кроме того, я еще не изучил map.
3. Обратите внимание, что здесь, после исправления упомянутой ошибки, вы будете отображать одну и ту же информацию несколько раз. Использование
std::map
здесь все упростит. Сортировка также является опцией.4. @VasudhaJhingan Одной из простых возможностей было бы сначала просканировать массив на наличие наименьшего и наибольшего значений, а затем использовать их для основного цикла.
Ответ №1:
Вот простой способ подсчета частот значений:
std::map<int, int> freq;
for (int const i : n)
freq[i] ; // map has the nice property that it
// defaults the value of a key to 0
for (auto const amp;[i, count] : freq) // this loop needs c 17
std::cout << "Frequency of " << i << " is " << count << std::endl;
Комментарии:
1. @VasudhaJhingan Нет проблем 🙂 Рассмотрите возможность принятия ответа, если это решит вашу проблему.
2. Хорошо для реального кода (хотя добавьте немного
const
, черт возьми! :P) — но не дает прямого ответа на вопрос о проблеме с этим кодом и, возможно, продвинут для вводного курса C (в зависимости от того, как он структурирован). Не обучает алгоритмам, просто обучает правильному использованию библиотеки C .3. @AsteroidsWithWings Верно, но код OPs, я думаю, довольно сломан, похоже, что не реализован четкий алгоритм. Но куда я должен добавить
const
? Вы имеете в виду первый цикл? Это простоint
.4. Это
int
вы не меняете 😉5. У меня было ощущение, что это могло быть так: P
Ответ №2:
Потому что это:
for(size_t i = 0; i < n[i]; i )
// ^^^^
… неверно.
Вы должны перейти к n.size()
.
В настоящее время вы переходите только к тому, что должно быть 4
( n[4]
есть 3
и 4 < 3
не выполняется).
Это было сделано правильно для завершения цикла j
.
Ответ №3:
Как указывали другие, есть гораздо лучшие способы сделать это. Например, хэширование
Вы можете прочитать об этом здесь:https://www.geeksforgeeks.org/counting-frequencies-of-array-elements /
Теперь я собираюсь указать, где именно вы ошиблись.
в первом цикле for замените i < n[i]
на i<n.size()
Неправильно:
for(size_t i = 0; i < n[i]; i )
Правильно :
for (size_t i = 0; i < n.size(); i )
Ваш код завершается с ошибкой, так как для i=3
значения n[i]=3
, которое нарушило ваше условие цикла for
Здесь этот код будет выполняться для всех повторений числа, поэтому он будет печатать одни и те же результаты несколько раз, а также будет выполнять все вычисления, поэтому поддерживайте посещенный массив, в котором хранится номер, который вы уже вычислили.
Вот ваш код, но исправленный
#include <iostream>
#include <array>
#include <vector>
using namespace std;
int main()
{
array<unsigned int, 20> n = {1, 2, 5, 4, 3, 5, 2, 1, 3, 1, 4, 3, 3, 3, 2, 3, 3, 2, 2};
vector<bool> visited(n.size(), false);
for (size_t i = 0; i < n.size(); i )
{
int count = 0;
// Skip this element if already processed
if (visited[i] == true) continue;
for (size_t j = 0; j < n.size(); j ){
if (n[i] == n[j]){
count ;
// marking indexes already visited
visited[j] = true;
}
}
cout << "Frequency of " << n[i] << " is " << count << endl;
}
return 0;
}
Но лучший вариант — изучить карты, они чрезвычайно полезны и очень просты в реализации.
https://www.geeksforgeeks.org/map-associative-containers-the-c-standard-template-library-stl/
Комментарии:
1.
n.size()
, неn.size()-1
.2. Ооо, я обычно добавляю равное в циклах, моя ошибка, я исправлю это, спасибо…
Ответ №4:
Поскольку вы используете std::array, я предполагаю, что вы знакомы с STL
, так почему бы не использовать его возможности для решения проблемы.
Сначала найдите уникальные элементы из вашего массива.
std::unordered_set<int> s(n.begin(), n.end());
Чем просто использовать count
, чтобы указать количество каждого элемента в вашем массиве.
#include <algorithm>
#include <array>
#include <iostream>
#include <unordered_set>
int main()
{
std::array<unsigned int, 20> n = { 1, 2, 5, 4, 3, 5, 2, 1, 3, 1, 4, 3, 3, 3, 2, 3, 3, 2, 2 };
std::unordered_set<int> s(n.begin(), n.end());
for (const autoamp; itr : s) {
std::cout << "Count of "<< itr << " Is equal to = " <<std::count(n.begin(), n.end(), itr) << std::endl;
}
}
Комментарии:
1. Человеку, который отрицательно проголосовал за это! Приятель, хотя бы объясни почему?
2. Отклонено, потому что это решение, хотя и выглядит лучше и менее подвержено ошибкам, по сути, является тем же ошибочным неэффективным подходом из OP, который использует неподходящие (в некотором смысле) конструкции STL. Если мы используем unordered_set , почему бы просто не использовать multiset для начала? en.cppreference.com/w/cpp/container/unordered_multiset/count В любом случае, я откажусь от своего отрицательного голоса, если к ответу будет добавлено предостережение о потенциальной неэффективности.
3. Единственная неэффективная вещь, которую я вижу, — это использование ссылочной переменной, используемой внутри цикла for . Если есть что-то еще, пожалуйста, обратитесь к учебному материалу, который был бы очень любезен с вашей стороны.
4. Для начала, ваше решение проходит через весь массив, чтобы построить неупорядоченный набор, затем для каждого элемента в наборе вы снова проходите через весь массив. Для последовательности 1 .. N она будет выполняться за ~ N ^ 2 шага.