Strona główna » Algorytmy » Artykuły » Moda
 

Moda

Wstęp

Moda jest to wartość ze zbioru, która najczęściej występuje. Takich elementów może być więcej niż jeden i wtedy wszystkie takie wartości nazywa się dominantami. W tym artykule zostanie wyjaśnione jak zaimplementować algorytm do wyszukiwania dominant.

Algorytm

W celu znalezienia dominanty należy policzyć ile razy występuje, który element, a następnie sprawdzić, które pary element×liczba wystąpień ma największą liczbę wystąpień. Podczas formułowania odpowiedzi należy pamiętać, że może być kilka dominant tj. elementów, które występują najczęściej.

Przykład

Weźmy przykładowo zbiór {1, 3, 5, 2, 4, 3, 1, 5, 5}. Dla podanego zbioru liczb utwórzmy tablicę, gdzie dla każdej wartości policzymy ile razy występuje. Dane zostały zebrane w tabelce:

Wartość12345
Wystąpień21213

Z tabelki wyraźnie wynika, że najczęściej występuje wartość 5, a więc jest to dominanta tego zbioru. Jednak gdyby w zbiorze nie istniała wartość 5 to dominantami byłyby wartości 1 oraz 3.

Implementacja

Strategia

Do przechowywania par wartość oraz ilość wystąpień warto napisać własną strukturę, albo skorzystać z dwuelementowych krotek. Wszystkie takie pary powinny być odkładane na specjalną listę. Elementy na niej umieszczone powinny zostać posortowane w trakcie wstawiania - dzięki temu do wyszukania czy dana wartość została już znaleziona wystarczy logn kroków, a nie n. Jest to możliwe dzięki wykorzystaniu wyszukiwaniu binarnemu.

Na koniec pozostaje przeanalizować utworzoną listę tak, aby można było określić, które wartości są dominantami, a które nie. W tym celu zostanie utworzona pusta lista, a maksymalna ilość wystąpień ustawiona na 0. Nastepnie przeszukując po kolei pary jeśli liczba wystąpień jest taka sama jak aktualne maksimum to wartość należy dopisać, a jeśli większa to lista jest czyszczona, maksimum ustawiane na ilość wystapień danej wartości, a następnie dopisywana na listę jest aktualna wartość.

Złożoność

Złożoność pamięciowa jest liniowa O(n), a złożoność czasowa to O(n·logn). Wynika to z faktu, że dla każdego z n elementów wykonujemy wyszukiwanie binarne o złożności O(logn), a następnie wykonujemy przejście po całej tablicy o maksymalnej długości n jeśli każda wartosć występuje raz, więc O(n·logn + n) = O(n·logn).

Strategia

Przykładowo dla zbioru {1, 3, 2, 3, 2, 3, 1} zostaną otrzymane następujące pary:

Wartość123
Wystąpień223

Z kolei wyszukiwanie dominant odbędzie się w następujący sposób:

WynikMaksimumWartośćWystąpieńKomentarz
[]012Liczba wystąpień 1 jest większa od maksimum, więc lista jest czyszczona, a 1 zostaje dopisane
[1]222Liczba wystapień 2 jest taka sama jak maksimum, więc dopisujemy dwa na listę
[1, 2]233Liczba wystąpień 3 jest większa niż maksimum, więc lista jest czyszczona, a 3 zostaje dopisane
[3]3---

Na podstawie uzyskanego wyniku można stwierdzić, że istnieje tylko jedna dominanta tj. 3.

Kod źródłowy

Szukanie dominanty

Poniższa funkcja szukajDominanty() dla podanej tablicy dane zwraca listę dominant.

C++C#
Python
  1. def szukajDominanty(dane):
  2.   lista = []
  3.   lista.append(Para(dane[0], 1))
  4.   for i in range(1, len(dane)):
  5.     poz = wyszukaj(lista, dane[i])
  6.     if (poz < len(lista) and lista[poz].wartosc == dane[i]):
  7.       lista[poz].ilosc = lista[poz].ilosc + 1
  8.     else:
  9.       lista.insert(poz, Para(dane[i], 1))
  10.   max, wynik = 0, [];
  11.   for i in range(0, len(lista)):
  12.     if (lista[i].ilosc > max):
  13.       wynik.clear()
  14.       max = lista[i].ilosc
  15.     if (lista[i].ilosc == max):
  16.       wynik.append(lista[i].wartosc)
  17.   lista.clear()
  18.   return wynik

(2.) Przygotuj nową listę, a następnie (3.) umieść na liście pierwszy element z listy wejściowej. Następnie (4.) dla każdego elementu: (5.) znajdź gdzie powinna znajdować się para wartości odpowiadająca elementowi. (6.) Jeśli na tej pozycji występuja para z szukaną wartością to (7.) zwiększ ilość. (8.) W przeciwnym razie (9.) dodaj nową parę na znalezionej pozycji. Dzięki temu mamy pewność, że lista jest posortowana i można korzystać z wyszukiwania binarnego. Drugi etap polega na (10.) przypisaniu, że najczęstsza wartość wystąpiła zero razy, a lista wynikowa jest pusta. (11.) Dla każdej pary: (12.) jeśli występuje częściej niż aktualne maksimum to (13.) oczyść listę i (14.) ustal nowe maksimum. Niezależnie od poprzedniego warunku (15.) sprawdź czy ilość wystąpień jest równa maksimum i jeśli tak to (16.) dopisz element na koniec. Po tej procedurze (17.) warto usunąć zbędne pary i (18.) zwrócić wynik.

Wyszukiwanie

Z kolei funkcja wyszukaj() to modyfikacja wyszukiwania binarnego. Nie zwraca ona informacji czy dana wartość wystepuje wśród par, a pozycję na której ta wartość powinna wystąpić. Dokładny opis wyszukiwania binarnego można znaleźć tutaj.

C++C#
Python
  1. def wyszukaj(lista, szukana):
  2.   L, P, sr = 0, len(lista) - 1, 0;
  3.   while (L <= P):
  4.     sr = int((L + P) / 2)
  5.     if (lista[sr].wartosc == szukana):
  6.       return sr
  7.     if (lista[sr].wartosc > szukana):
  8.       P = sr - 1
  9.     else:
  10.       L = sr + 1
  11.   return L

Testowanie funkcji

W celu przetestowania kodu można skorzystać z poniższego fragmentu kodu:

C++C#
Python
  1. print("Podaj liczby:")
  2. dane = [int(x) for x in input().split()]
  3. wynik = szukajDominanty(dane)
  4. print(wynik)

Zadania

Zadanie 1

Wyszukiwanie dominanty można też zrealizować poprzez posortowanie danych, a następnie liniowo sprawdzeniu wszystkich elementów i wykrycia grup, które mają największą liczbę elementów. Przykładowo dla tablicy {1, 3, 2, 3, 2, 3, 1} wpierw zostanie posortowana jako {1, 1, 2, 2, 3, 3, 3}, a potem zostaną policzone kolejne grupy elementów o tym samych wartościach. Napisz funkcję szukajDominantaSort(), aby znaleźć dominantę (dominanty). Przetestuj działanie progrmau.