Sobes.tech
Middle

Kiedy używać std::set, a kiedy std::unordered_set w C++?

sobes.tech AI

Odpowiedź od AI

std::set i std::unordered_set są używane do przechowywania unikalnych elementów. Wybór między nimi zależy od priorytetów: uporządkowania czy wydajności dostępu/wstawiania/usuwania.

std::set opiera się na zrównoważonym drzewie binarnym (zwykle drzewo czerwono-czarne).

Charakterystyka std::set:

  • Elementy są przechowywane w posortowanej kolejności.
  • Wstawianie, usuwanie i wyszukiwanie elementów zajmuje średnio O(log N), gdzie N to liczba elementów.
  • Nadaje się, gdy ważne jest uporządkowanie elementów lub gdy konieczne jest pobranie elementów w określonym zakresie.

std::unordered_set opiera się na tablicy haszującej.

Charakterystyka std::unordered_set:

  • Elementy nie są przechowywane w uporządkowanej kolejności.
  • Wstawianie, usuwanie i wyszukiwanie elementów w średnim czasie O(1), ale w najgorszym przypadku (przy dużej liczbie kolizji funkcji hash) może osiągnąć O(N).
  • Wymaga, aby typ elementu miał zdefiniowaną funkcję hash (std::hash) i operator porównania równości (operator==).
  • Nadaje się, gdy potrzebna jest maksymalna szybkość wstawiania, usuwania i wyszukiwania, a kolejność elementów nie ma znaczenia.

Tabela podsumowująca:

Kryterium std::set std::unordered_set
Struktura wewnętrzna Zrównoważone drzewo Tablica haszująca
Kolejność elementów Posortowana Nieposortowana
Czas wyszukiwania/wstawiania/usuwania (średni) O(log N) O(1)
Czas wyszukiwania/wstawiania/usuwania (najgorszy) O(log N) O(N)
Wymagania dotyczące typu Operator < std::hash, operator==

Przykład użycia std::set:

#include <iostream>
#include <set>

int main() {
    std::set<int> ordered_set;
    ordered_set.insert(5);
    ordered_set.insert(2);
    ordered_set.insert(8);

    // Elementy zostaną wyświetlone w kolejności: 2 5 8
    for (int val : ordered_set) {
        std::cout << val << " ";
    }
    std::cout << std::endl;

    return 0;
}

Przykład użycia std::unordered_set:

#include <iostream>
#include <unordered_set>

int main() {
    std::unordered_set<int> unordered_set;
    unordered_set.insert(5);
    unordered_set.insert(2);
    unordered_set.insert(8);

    // Kolejność wyświetlania może się różnić
    for (int val : unordered_set) {
        std::cout << val << " ";
    }
    std::cout << std::endl;

    return 0;
}