Close Menu
    Ciekawe

    Jak podłączyć telefon do monitora? Przewodowe i bezprzewodowe sposoby

    2025-12-08

    Co można wrzucić w koszty firmy jednoosobowej? Lista i praktyczne przykłady

    2025-12-03

    Jak podłączyć okulary VR do PS4? Poradnik podłączenia i konfiguracji

    2025-12-02
    Facebook X (Twitter) Instagram
    CPP Polska
    Facebook X (Twitter) Instagram
    • Biznes

      Co można wrzucić w koszty firmy jednoosobowej? Lista i praktyczne przykłady

      2025-12-03

      Jak zapobiec wyciekom danych firmowych?

      2025-11-28

      Ile kosztuje prowadzenie jednoosobowej działalności gospodarczej? Przegląd opłat

      2025-11-10

      Jak wziąć samochód w leasing bez firmy? Poradnik dla osób fizycznych

      2025-10-29

      Jak założyć firmę jednoosobową krok po kroku – koszty, formalności i czas trwania

      2025-10-23
    • Technologie

      Jak podłączyć telefon do monitora? Przewodowe i bezprzewodowe sposoby

      2025-12-08

      Jak podłączyć okulary VR do PS4? Poradnik podłączenia i konfiguracji

      2025-12-02

      Jak zapobiec wyciekom danych firmowych?

      2025-11-28

      Jak sprawdzić rozdzielczość monitora w Windows i macOS?

      2025-11-26

      Jak zresetować laptopa Acer do ustawień fabrycznych? Poradnik krok po kroku

      2025-11-25
    • Programowanie

      Maszyna stanów oparta o std::variant

      2025-10-07

      std::deque w C++ – kiedy wybrać dwukierunkową kolejkę zamiast vectora

      2025-10-07

      Tablice w C++ od podstaw – deklaracja, inicjalizacja, iteracja i typowe pułapki

      2025-10-07

      itoa i std::to_chars – konwersja liczb na tekst bez narzutu wydajności

      2025-10-07

      strcpy vs strncpy vs std::string – bezpieczne kopiowanie łańcuchów w C++

      2025-10-07
    • Inne

      Jak prowadzić blog programistyczny i dzielić się wiedzą?

      2025-06-28
    CPP Polska
    Home»C++»STL w C++ – szybki przegląd kontenerów, adapterów i algorytmów dla początkujących
    C++

    STL w C++ – szybki przegląd kontenerów, adapterów i algorytmów dla początkujących

    Oskar KlimkiewiczBy Oskar KlimkiewiczBrak komentarzy6 Mins Read
    Share Facebook Twitter LinkedIn Email Copy Link
    Follow Us
    RSS
    turned on gray laptop computer
    Share
    Facebook Twitter LinkedIn Email Copy Link

    Wyczerpujący przewodnik po kontenerach, adapterach i algorytmach STL w C++ dla początkujących

    Biblioteka standardowa szablonów (STL) w C++ stanowi fundamentalny zestaw narzędzi programistycznych, oferując gotowe komponenty do efektywnego zarządzania danymi i implementacji algorytmów. Jej architektura opiera się na trzech filarach: kontenerach (przechowujących dane), adapterach (modyfikujących interfejsy kontenerów) oraz algorytmach (operujących na danych). Dla początkujących zrozumienie struktury STL jest kluczowe, gdyż eliminuje konieczność ręcznej implementacji powszechnych struktur danych, przyspieszając rozwój oprogramowania przy zachowaniu optymalnej wydajności.

    1. Architektura STL i jej komponenty

    Standard template library (STL) to zbiór szablonów klas i funkcji, który standaryzuje implementację struktur danych i algorytmów. Projekt STL opiera się na zasadzie separacji danych od operacji, co umożliwia niezależne modyfikowanie kontenerów i algorytmów. Podstawowe komponenty dzielą się na cztery kategorie:

    1. Kontenery – obiekty przechowujące kolekcje elementów (np. vector, map);
    2. Iteratory – mechanizmy dostępu do elementów kontenerów w sposób sekwencyjny lub losowy;
    3. Algorytmy – funkcje operujące na danych poprzez iteratory (np. sort, find);
    4. Obiekty funkcyjne – klasy zachowujące się jak funkcje, używane do dostosowywania działania algorytmów.

    Iteratory pełnią rolę mostu między kontenerami a algorytmami. Dzięki ustandaryzowanemu interfejsowi, algorytmy takie jak std::sort działają identycznie dla std::vector (tablicy dynamicznej) i std::list (listy dwukierunkowej), mimo różnic w wewnętrznej strukturze danych.

    #include <vector>
    #include <algorithm>
    
    int main() {
        std::vector<int> numbers = {5, 2, 4, 1, 3};
        std::sort(numbers.begin(), numbers.end()); // Algorytm działający na iteratorach
    }
    

    2. Kontenery sekwencyjne

    Kontenery sekwencyjne przechowują elementy w ściśle określonej kolejności, umożliwiając dostęp przez indeksy lub iteratory. Implementują klasyczne struktury danych, takie jak tablice dynamiczne, listy czy kolejki dwukierunkowe.

    2.1. Vector – dynamiczna tablica

    std::vector to kontener o dynamicznie zmieniającym się rozmiarze, przechowujący elementy w ciągłym bloku pamięci. Zapewnia stały czas dostępu do dowolnego elementu (O(1)), ale modyfikacje w środku sekwencji są kosztowne (O(n)).

    #include <iostream>
    #include <vector>
    
    int main() {
        std::vector<std::string> fruits = {"Apple", "Banana"};
        fruits.push_back("Orange"); // Dodanie elementu na koniec: O(1)
        std::cout << "First fruit: " << fruits[0] << "\n"; // Dostęp przez indeks
    }
    

    Wydajność operacji:

    Operacja Złożoność czasowa
    push_back() O(1) (amortyzowana)
    insert() O(n)
    operator[] O(1)

    2.2. Lista dwukierunkowa (std::list)

    std::list implementuje listę dwukierunkową, gdzie każdy element przechowuje wskaźniki na poprzednika i następnika. Umożliwia szybkie wstawianie i usuwanie w dowolnym miejscu (O(1)), ale nie zapewnia dostępu swobodnego (brak operatora []).

    #include <list>
    
    std::list<int> values = {10, 20, 30};
    values.insert(std::next(values.begin()), 15); // Wstawienie 15 po pierwszym elemencie
    

    2.3. Kolejka dwustronna (std::deque)

    std::deque łączy cechy wektora i listy. Składa się z bloków pamięci połączonych w sekwencję, umożliwiając efektywne operacje na obu końcach (O(1) dla push_front() i push_back()). Idealny do implementacji buforów cyklicznych.

    #include <deque>
    
    std::deque<double> temperatures = {22.5, 23.0};
    temperatures.push_front(21.8); // Dodanie na początek
    

    3. Kontenery asocjacyjne

    Kontenery asocjacyjne przechowują elementy w sposób posortowany, zwykle implementując drzewa czerwono-czarne (red-black trees). Zapewniają logarytmiczny czas wyszukiwania (O(log n)), ale wymagają zdefiniowania relacji porządku dla elementów.

    3.1. Zbiory (std::set i std::multiset)

    std::set przechowuje unikalne klucze posortowane rosnąco. std::multiset dopuszcza duplikaty kluczy. Oba zapewniają szybkie wyszukiwanie, ale modyfikacje mogą wymagać przebudowy drzewa.

    #include <set>
    
    std::set<std::string> names = {"Alice", "Bob"};
    if (names.find("Alice") != names.end()) {
        std::cout << "Alice istnieje w zbiorze.\n";
    }
    

    3.2. Mapy (std::map i std::multimap)

    std::map to kolekcja par klucz-wartość, gdzie klucze są unikalne i posortowane. std::multimap pozwala na wiele wartości dla jednego klucza. Przydatne w słownikach lub indeksach.

    #include <map>
    
    std::map<std::string, int> ages = {{"Alice", 30}, {"Bob", 25}};
    ages["Charlie"] = 28; // Dodanie nowej pary
    

    Porównanie kontenerów asocjacyjnych:

    Kontener Unikalność kluczy Struktura danych
    std::set Tak Drzewo RB
    std::multiset Nie Drzewo RB
    std::map Tak (klucze) Drzewo RB
    std::multimap Nie (klucze) Drzewo RB

    4. Nieuporządkowane kontenery asocjacyjne

    Wprowadzone w C++11, wykorzystują tablice mieszające (hash tables) do przechowywania danych. Zapewniają średnio stały czas dostępu (O(1)), lecz w najgorszym przypadku (O(n)). Wymagają zdefiniowania funkcji haszującej.

    4.1. Unordered_set i unordered_map

    std::unordered_set i std::unordered_map implementują odpowiednio zbiór i mapę z funkcją haszującą. Elementy nie są posortowane, co przyspiesza wstawianie i usuwanie.

    #include <unordered_map>
    
    std::unordered_map<std::string, int> phonebook;
    phonebook["Alice"] = 123456789;
    

    4.2. Zarządzanie buckietami

    Wydajność zależy od funkcji mieszającej i strategii kolizji. Domyślnie STL stosuje metodę łańcuchową, gdzie kolizje rozwiązuje się przez listy elementów w jednym buckiecie. Możliwość zmiany rozmiaru tablicy mieszającej wpływa na wydajność.

    5. Adaptery kontenerów

    Adaptery to specjalizowane szablony klas, które nie są pełnoprawnymi kontenerami, lecz nakładają ograniczony interfejs na istniejące kontenery (np. std::deque). Nie obsługują iteratorów.

    5.1. Stos (std::stack)

    Implementuje strukturę LIFO (Last-In-First-Out). Używa metod push(), pop() i top(). Domyślnie oparty na std::deque, ale można zmienić kontener bazowy (np. na std::vector).

    #include <stack>
    
    std::stack<int> stack;
    stack.push(10);
    stack.push(20);
    int top = stack.top(); // 20
    stack.pop();
    

    5.2. Kolejka (std::queue)

    Realizuje FIFO (First-In-First-Out). Udostępnia operacje push() (dodanie na koniec), pop() (usunięcie z początku) i front(). Domyślnie oparta na std::deque.

    5.3. Kolejka priorytetowa (std::priority_queue)

    Przechowuje elementy w kolejce według priorytetu (domyślnie największy na początku). Używa push(), pop() i top(). Implementowana zwykle przez kopiec binarny na bazie std::vector.

    #include <queue>
    
    std::priority_queue<int> pq;
    pq.push(30);
    pq.push(10);
    pq.push(20);
    int highest = pq.top(); // 30
    

    6. Algorytmy STL

    Algorytmy to funkcje szablonowe operujące na zakresach określonych iteratorami. Nie modyfikują bezpośrednio kontenerów, lecz wykonują operacje na ich elementach.

    6.1. Klasyfikacja algorytmów

    • Algorytmy niemodyfikujące – find(), count(), for_each();
    • Algorytmy modyfikujące – copy(), transform(), replace();
    • Algorytmy sortujące – sort(), stable_sort(), partial_sort();
    • Algorytmy numeryczne – accumulate(), inner_product().
    #include <algorithm>
    
    std::vector<int> data = {5, 3, 8, 1};
    std::sort(data.begin(), data.end()); // Sortowanie rosnące
    auto it = std::find(data.begin(), data.end(), 8); // Wyszukiwanie
    

    6.2. Zaawansowane użycie z obiektami funkcyjnymi

    Obiekty funkcyjne (funktory) pozwalają dostosować działanie algorytmów. Przykładowo, sortowanie malejące za pomocą std::greater<>:

    std::sort(data.begin(), data.end(), std::greater<int>());
    

    7. Iteratory – łącznik między kontenerami a algorytmami

    Iteratory zapewniają abstrakcję dostępu do elementów, działając jak inteligentne wskaźniki. Dzielą się na pięć kategorii:

    1. Wejściowe – tylko odczyt sekwencyjny;
    2. Wyjściowe – tylko zapis sekwencyjny;
    3. Jednokierunkowe – przesuwanie tylko do przodu;
    4. Dwukierunkowe – przesuwanie w obu kierunkach (np. std::list);
    5. Swobodnego dostępu – przeskakiwanie do dowolnego elementu (np. std::vector).

    7.1. Przykład użycia iteratora

    std::vector<int> vec = {1, 2, 3};
    for (auto it = vec.begin(); it != vec.end(); ++it) {
        std::cout << *it << " "; // Dostęp przez dereferencję
    }
    

    8. Wybór kontenera – wytyczne wydajnościowe

    Optymalny dobór kontenera zależy od dominujących operacji. Poniższa analiza pomaga podjąć decyzję:

    • Częsty dostęp losowy – std::vector lub std::array (stały rozmiar);
    • Częste wstawianie w środku – std::list (O(1) przy znanym iteratorze);
    • Szybkie wyszukiwanie – kontenery asocjacyjne (O(log n)) lub nieuporządkowane (O(1)).

    Złożoność operacji kluczowych:

    Kontener Wstawianie Usuwanie Dostęp Wyszukiwanie
    std::vector O(n) O(n) O(1) O(n)
    std::list O(1) O(1) O(n) O(n)
    std::set O(log n) O(log n) N/A O(log n)
    std::unordered_map O(1) O(1) O(1) O(1)

    8.1. Zalecane praktyki dla początkujących

    1. Unikaj przedwczesnej optymalizacji – startuj z std::vector jako domyślnym kontenerem;
    2. Używaj kontenerów asocjacyjnych przy częstym wyszukiwaniu po kluczu;
    3. Dla danych o dużej zmienności wybieraj std::list lub std::forward_list;
    4. W scenariuszach wymagających zachowania kolejności stosuj adaptery queue lub stack.

    9. Wnioski i dalsze kierunki nauki

    STL stanowi fundament efektywnego programowania w C++, oferując bogaty zestaw optymalizowanych komponentów. Dla początkujących kluczowe jest opanowanie relacji między kontenerami, iteratorami i algorytmami, co pozwala uniknąć redundantnego kodu i błędów implementacyjnych. Przyszłe kroki w nauce powinny obejmować:

    • Eksperymentowanie z niestandardowymi obiektami funkcyjnymi;
    • Zrozumienie semantyki przenoszenia w nowoczesnym C++;
    • Poznanie kontenerów równoległych z C++17 (np. std::unordered_map bezpieczny dla wątków).

    Dokumentacja Microsoft Docs i CPPReference pozostają nieocenionymi źródłami dla pogłębiania wiedzy. Wdrożenie przedstawionych koncepcji gwarantuje tworzenie kodu, który łączy czytelność z wysoką wydajnością.

    Opracowano na podstawie źródeł akademickich i dokumentacji STL.

    Polecane:

    • std::stack w C++ – adapter stosu, implementacja LIFO i przydatne metody
    • std::priority_queue – implementacja kopca, własne komparatory i zastosowania algorytmiczne
    • Erase–remove idiom w C++
    • Semantyka przenoszenia i std::move – zarządzanie zasobami w C++
    • Podstawy pracy z Google Mock – kurs krok po kroku
    Share. Facebook Twitter LinkedIn Email Copy Link
    Oskar Klimkiewicz
    • Website

    Inżynier oprogramowania specjalizujący się w C++, absolwent Wydziału Elektroniki i Technik Informacyjnych Politechniki Warszawskiej. Od ponad 8 lat projektuje i rozwija systemy o wysokiej dostępności, głównie dla branży fintech i IoT. PS. Zdjęcie wyretuszowane przez AI :)

    Podobne artykuły

    Maszyna stanów oparta o std::variant

    8 Mins Read

    Tablice w C++ od podstaw – deklaracja, inicjalizacja, iteracja i typowe pułapki

    4 Mins Read

    std::deque w C++ – kiedy wybrać dwukierunkową kolejkę zamiast vectora

    4 Mins Read
    Leave A Reply Cancel Reply

    Oglądaj, słuchaj, ćwicz - zdobywaj nowe umiejętności online
    Nie przegap

    Jak podłączyć telefon do monitora? Przewodowe i bezprzewodowe sposoby

    Oskar Klimkiewicz6 Mins Read

    Podłączenie telefonu do monitora to jedna z najistotniejszych innowacji ery mobilnej, umożliwiająca przeniesienie doświadczeń z…

    Co można wrzucić w koszty firmy jednoosobowej? Lista i praktyczne przykłady

    2025-12-03

    Jak podłączyć okulary VR do PS4? Poradnik podłączenia i konfiguracji

    2025-12-02

    Jak zapobiec wyciekom danych firmowych?

    2025-11-28
    Social media
    • Facebook
    • Twitter
    • LinkedIn
    O nas
    O nas

    CPP Polska to serwis internetowy poświęcony technologii, programowaniu, IT, biznesowi i finansom. Znajdziesz tu porady, wskazówki i instrukcje dla wszystkich czytelników IT & Tech & Biz.

    Facebook X (Twitter) LinkedIn RSS
    Najnowsze

    Jak podłączyć telefon do monitora? Przewodowe i bezprzewodowe sposoby

    2025-12-08

    Co można wrzucić w koszty firmy jednoosobowej? Lista i praktyczne przykłady

    2025-12-03

    Jak podłączyć okulary VR do PS4? Poradnik podłączenia i konfiguracji

    2025-12-02
    Popularne

    Skrajnie niepotrzebne, skrajne przypadki w C++

    2025-06-28

    Wyszukiwanie testów w Google Test – metody i narzędzia

    2025-06-28

    Czy C jest wolniejszy od C++? Zero-cost abstraction w praktyce

    2025-06-28
    © 2025 CPP Polska. Wszelkie prawa zastrzeżone.
    • Lista publikacji
    • Współpraca
    • Kontakt

    Type above and press Enter to search. Press Esc to cancel.