Не удается отобразить правильную частоту целых чисел в массиве

#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 шага.