ile razy liczba jest w tablicy

0

Czy ktoś wyjaśni co w tym kodzie jest źle ? Chodzi o to, że chcę sprawdzić ile razy dana liczba występuje w tablicy.

int main(void)
{
    int tab[10]={1,2,2,2,5,6,7,8,9,10};
    int liczba;
    int licznik=0;

    for(int i=0; i<10; i++){
        liczba=tab[i];

        for(int j=0; j<i; j++){
            if(liczba==tab[j]){
                std::cout << "liczba " << liczba << " wystepuje " << licznik << " razy" << std::endl;
            }
            licznik++;
        }
    }
    return 0;
}
3

Nie zerujesz licznik przy przeskakiwaniu do kolejnej liczby.

A tak swoją drogą: std::count

3

Użyj std::unordered_map<unsigned int, unsigned int>

klucz = liczba
wartość = częstotliwość(l. wystąpień)

2

Użyj std::count

#include <iostream>
#include <set>
#include <algorithm>

using namespace std;

int main()
{
    int tab[] {1,2,2,2,5,6,7,8,9,10};

    for( const auto number : set<int>(cbegin(tab),cend(tab)) )
    cout << number << " -> " << count( begin(tab) , end(tab) , number ) << endl;

    return 0;
}
2

Nie zerujesz licznik no i wypisywać powinieneś raczej po skończonym zlliaczniu a nie w trakcie. Poza tym możesz to napisać dużo krócej

int tab[]={1,2,2,2,5,6,7,8,9,10};
for(auto num : tab)
   std::cout << "liczba " << num << " wystepuje " << std::count(std::begin(tab), std::end(tab), num) << " razy\n";

Powyższy kod ma oczywiście ten minus, że wypisze również już wcześniej podliczone liczby, ale to już możesz dodać sobie sam.

0

ten powyższy algorytm nie był zbyt dobry, problem powtarzających się liczb rozwiązałem w ten sposób

int *sort(int[]);

int wiersz=9;

int main(void)
{
    int tDane[9]={4,3,3,3,2,1,1,1,4};
    int tDaneIlePowt[1][1];
    int ile_liczb=0;
    int element=0;
    int ile_danych=0;
    int z_pom;
    int *wDane;

    wDane = sort(&tDane[0]);

    for(int i=0; i<9; i++){
        z_pom = wDane[i];
        for(int j=element; j<9; j++){
            if(z_pom == wDane[j]){
                ile_liczb++;
                element++;
            }
            else{
                break;
            }
        }

        if(ile_liczb != 0){
            std::cout << "liczba " << wDane[i] << " wystepuje " << ile_liczb << " raz(y)" << std::endl;
            ile_danych++;
        }

        ile_liczb=0;
    }

    delete [] wDane;
    wDane = nullptr;

    return 0;
}

int *sort(int tSort[])
{
    int *_tSort = new int [wiersz];
    int zm_pom;

    for(int i=0; i<wiersz; i++){
        _tSort[i] = tSort[i];
    }

    for(int i=0; i<wiersz; i++){
        zm_pom = _tSort[i];

        for(int j=i+1; j<wiersz; j++){
            if(_tSort[j] < zm_pom){
                zm_pom = _tSort[j];
                _tSort[j] = _tSort[i];
                _tSort[i] = zm_pom;
            }
        }
    }

    return &_tSort[0];
}

i teraz mam pytanie - czy da radę napisać algorytm w taki sposób aby możliwe było zliczanie powtarzających się elementów ale bez sortowania ?

np - w tablicy mam takie liczby

4,3,3,3,2,1,1,1,4

czy da radę zliczyć ilość powtarzających się cyfr bez sortowania tablicy ?

Uprzedzam od razu, że nie stosuję się do standardu, co widać gołym okiem (jeszcze za wcześnie na standardy)

0

@kq kod severala zwraca to:

screenshot-20201026113735.png

za dużo tych wyników, skompiluj mój kod i zobacz jak to wygląda

3
template<typename T>
auto histogramize(T&& t) -> std::map<std::decay_t<decltype(*std::begin(t))>, size_t>
{
    std::map<std::decay_t<decltype(*std::begin(t))>, size_t> ret;
    for(auto const& el : t)
        ret[el]++;
    return ret;
}

int main()
{
    int tab[] {1,2,2,2,5,6,7,8,9,10,-1,2};

    for(auto const& [value, count] : histogramize(tab))
        cout << value << " -> " << count << "\n";

    return 0;
}

https://wandbox.org/permlink/PXjg8Q0aEyvfL7vO

0

a tak swoją drogą, ciekawe czy ktoś z was wie jak usunąć wyciek pamięci w tym przypadku ? Zadaję pytanie, ponieważ jakoś ten problem rozwiązano ? I częściowo po to ten algorytm powstał aby zrozumieć jak usuwać wycieki pamięci w różnych przypadkach - tak, wiem, że lubicie gotowe rozwiązania w postaci standardu ale ja chcę się nauczyć i zrozumieć pewne rzeczy — zkubinski dziś, 11:20

Jak? W pełni stosować C++ - a nie tylko C ze strumieniami.
Strzelam, ze być może w pięć sposobów można to pozytywnie rozwiązać. Dwa najszybciej nasuwające się: smartpointery, kontenery C++

4

Ok, co tutaj jest źle, i czemu to jest bardziej C ze strumieniami, a nie C++, to wyjaśnię (nie jest to też dobre C, ale to inna sprawa):

  1. W C++ sygnatura int main(void) jest niepoprawna (ale za to w C jest poprawna).
  2. Mieszana konwencja, z jednej strony snake case (z_pom), z drugiej camel case (wDane).
  3. Magiczne stałe (9), a można było zrobić constexpr size_t size = std::size(tDane)
  4. Nazwy typu element nic sensownego nie wyrażają, tak samo jak z_pom, która by mogła być nazwana np. previous_element.
  5. int tDaneIlePowt[1][1];? Dwuwymiarowa tablica jednoelementowa? Czym to jest w ogóle uzasadnione?
  6. tDane -> czemu służy przedrostek t?
  7. Pętla for(int j=element; j<9; j++){ if (warunek) { coś; } else {break;}} to tak naprawdę powinna być pętla while.
  8. Irracjonalne użycie pary new[] i delete[] - tutaj powinien być std::vector. Dzięki temu zyskasz RAII, jawne wyrażenie tego kiedy i przez kogo zasoby powinny być zwolnione, a także wyrażasz intencję funkcji sort, która notabene powinna mieć sygnaturę int* sort(const int[]), albo jeszcze lepiej wersję gdzie podajesz rozmiar, int* sort(const int[], size_t).
  9. Używanie własnego swapowania zamiast std::swap.
  10. &_tSort[0] zamiast _tSort
  11. W ogóle pisanie takiej funkcji sortującej tylko dla intów, a nie jako funkcja szablonowa dla dowolnych częściowo uporządkowanych typów.
0

częściowo się zgodzę ale po kolei:

enedil napisał(a):

Ok, co tutaj jest źle, i czemu to jest bardziej C ze strumieniami, a nie C++, to wyjaśnię (nie jest to też dobre C, ale to inna sprawa):

  1. W C++ sygnatura int main(void) jest niepoprawna (ale za to w C jest poprawna).

Ad.1 to wszystko "od tych książek" o nauce C++ (nie miałem pojęcia, że to jest jakiś staroć z C

  1. Mieszana konwencja, z jednej strony snake case (z_pom), z drugiej camel case (wDane).

Ad. 2. nie mam pomysłu na nazewnictwo zmiennych, pisałem to, co mi przyszło do głowy... (jeżeli ma ktoś ciekawą lekturę na ten temat, to poproszę)

  1. Magiczne stałe (9), a można było zrobić constexpr size_t size = std::size(tDane)

Ad. 3. a tego to nie wiedziałem, poza tym te '9' stoi tam tymczasowo, dopóki nie rozwiążę reszty problemów do których ma służyć ten kod

  1. Nazwy typu element nic sensownego nie wyrażają, tak samo jak z_pom, która by mogła być nazwana np. previous_element.

Ad.4. zgadza się, bo to jest jakaś zmienna, która coś robi i nie mam sensownej nazwy na nią, więc ją tak nazwałem :D

  1. int tDaneIlePowt[1][1];? Dwuwymiarowa tablica jednoelementowa? Czym to jest w ogóle uzasadnione?

Ad.5. No to już jest dalszy ciąg tego, do czego ma służyć algorytm, a żeby rozwiać wątpliwości, to ta tablica będzie przechowywać ilość liczb które się powtarzają i jakie to są liczby

  1. tDane -> czemu służy przedrostek t?

Ad. 6. W zamyśle 't' to 'tablica`

  1. Pętla for(int j=element; j<9; j++){ if (warunek) { coś; } else {break;}} to tak naprawdę powinna być pętla while.

Ad.7. dlaczego while ? Co jest złego w for ? (jakoś częściej używam for aniżeli while

  1. Irracjonalne użycie pary new[] i delete[] - tutaj powinien być std::vector. Dzięki temu zyskasz RAII, jawne wyrażenie tego kiedy i przez kogo zasoby powinny być zwolnione, a także wyrażasz intencję funkcji sort, która notabene powinna mieć sygnaturę int* sort(const int[]), albo jeszcze lepiej wersję gdzie podajesz rozmiar, int* sort(const int[], size_t).

Ad. 8. Wiem, że jest "vector" ale ja ciągle ćwiczę, a ćwiczę aby być bardziej kumatym. Co to jest RAII ? I ciekawi mnie to -> int* sort(const int[], size_t) - co mi to daje ?

  1. Używanie własnego swapowania zamiast std::swap.

Ad. 9. jakiego swapowania ? Co to jest ten swap i do czego to służy ? Gdzie to jest u mnie w kodzie ?

  1. &_tSort[0] zamiast _tSort

Ad. 10. to są równoważne zapisy, korzystam z tego, bo dla mnie jest czytelniejszy (nie zależy mi na tzw. skrótach aby "oszczędzić" pisania)

  1. W ogóle pisanie takiej funkcji sortującej tylko dla intów, a nie jako funkcja szablonowa dla dowolnych częściowo uporządkowanych typów.

Ad. 11. Celowo ma być tylko dla typów int, bo w tym algorytmie nie przewiduję losowania innych typów

3

@zkubinski:

Proste zadanie, proste rozwiązanie.

#include <iostream>
#include <unordered_map>


int main()
{
    int tab[10] = {1, 2, 2, 2, 5, 6, 7, 8, 9, 10};
    std::unordered_map<int, int> intHistogram;
    for(int i = 0; i < sizeof(tab)/sizeof(tab[0]); ++i)
        intHistogram[tab[i]]++;

    for(const auto& item : intHistogram)
        std::cout<<"number: "<<item.first<<" frequency: "<<item.second<<std::endl;
}

Porównaj swoje z moim, po co to komplikować ?

1

Ja wiem gdzie jest Twój problem.
Wykładowca Cię nie doceni i nie pomyśli, że jesteś inteligentny jak zobaczy, że próbujesz użyć ak47 do zabicia komara. I to jeszcze w niewłaściwy sposób.
Inteligencja jest widoczna w prostocie a nie w komplikacji.

1 użytkowników online, w tym zalogowanych: 0, gości: 1