Kontenery STL
Część sekcji Programowanie obiektowe ścieżki C++ w Coddy. Lekcja 71 z 104.
Kontenery STL to klasy szablonowe, które przechowują i organizują kolekcje obiektów. Każdy typ kontenera jest zoptymalizowany pod kątem różnych wzorców dostępu i operacji. Wybór odpowiedniego kontenera do Twoich potrzeb może znacząco wpłynąć na wydajność programu.
Kontenery sekwencyjne przechowują elementy w określonej kolejności:
#include <vector>
#include <list>
std::vector<int> vec = {1, 2, 3}; // Tablica dynamiczna, szybki dostęp swobodny
vec.push_back(4); // Dodanie na końcu: amortyzowany koszt O(1)
int x = vec[2]; // Dostęp przez indeks: O(1)
std::list<int> lst = {1, 2, 3}; // Lista dwukierunkowa
lst.push_front(0); // Dodanie na początku: O(1)
lst.push_back(4); // Dodanie na końcu: O(1)Kontenery asocjacyjne przechowują elementy w posortowanej kolejności, aby umożliwić szybkie wyszukiwanie:
#include <map>
#include <set>
std::set<int> s = {3, 1, 4, 1}; // Unikalne posortowane elementy: {1, 3, 4}
s.insert(2); // Wstawianie: O(log n)
bool found = s.count(3); // Sprawdzanie istnienia: O(log n)
std::map<std::string, int> ages; // Pary klucz-wartość, posortowane według klucza
ages["Alice"] = 25; // Wstawianie/aktualizacja: O(log n)
ages["Bob"] = 30;
std::cout << ages["Alice"]; // Dostęp: O(log n)Kontenery nieuporządkowane używają tablic mieszających, aby zapewnić jeszcze szybsze wyszukiwanie w przypadku średnim:
#include <unordered_map>
std::unordered_map<std::string, int> scores;
scores["player1"] = 100; // Wstawianie: średnio O(1)
scores["player2"] = 200;
std::cout << scores["player1"]; // Dostęp: średnio O(1)Używaj vector, gdy potrzebujesz szybkiego dostępu swobodnego, list przy częstym wstawianiu elementów w środku, map/set, gdy potrzebujesz uporządkowanych danych, oraz unordered_map, gdy szybkość wyszukiwania ma kluczowe znaczenie, a kolejność nie ma znaczenia.
Wyzwanie
ŁatwyStwórzmy system zarządzania ocenami uczniów, który pokazuje, jak różne kontenery STL służą różnym celom. Użyjesz wielu typów kontenerów, aby efektywnie organizować dane uczniów, dobierając odpowiedni kontener do każdego zadania.
Utworzysz dwa pliki, aby uporządkować swój kod:
GradeManager.h: Zdefiniuj klasęGradeManager, która używa wielu kontenerów STL do zarządzania informacjami o uczniach.Twoja klasa powinna używać:
std::vector<std::string>do przechowywania imion i nazwisk uczniów w kolejności ich dodaniastd::map<std::string, int>do powiązania imienia i nazwiska każdego ucznia z jego ocenąstd::set<int>do śledzenia wszystkich unikalnych przypisanych ocen
Zaimplementuj te metody:
addStudent(const std::string& name, int grade): dodaje ucznia wraz z jego oceną do wszystkich trzech kontenerówgetGrade(const std::string& name): zwraca ocenę danego ucznia na podstawie jego imienia i nazwiska, używając mapyprintRoster(): wypisuje imiona i nazwiska wszystkich uczniów w kolejności ich dodania (z wektora), każde w nowym wierszuprintGrades(): wypisuje wszystkich uczniów wraz z ich ocenami w kolejności alfabetycznej (mapa sortuje je automatycznie), w formaciename: grade, każdy wpis w osobnym wierszuprintUniqueGrades(): wypisuje wszystkie unikalne oceny w kolejności rosnącej (set zajmuje się tym automatycznie), oddzielone spacjami, po czym wypisuje znak nowej linii
main.cpp: Wczytaj dane i pokaż, jak każdy typ kontenera służy innemu celowi.Wczytaj sześć danych wejściowych (każdą w osobnym wierszu):
- Imię i nazwisko pierwszego ucznia
- Ocena pierwszego ucznia (liczba całkowita)
- Imię i nazwisko drugiego ucznia
- Ocena drugiego ucznia (liczba całkowita)
- Imię i nazwisko trzeciego ucznia
- Ocena trzeciego ucznia (liczba całkowita)
Utwórz obiekt
GradeManageri dodaj wszystkich trzech uczniów. Następnie pokaż różne zachowania kontenerów:- Wypisz
Roster (insertion order):, a następnie wywołajprintRoster() - Wypisz
Grades (alphabetical):, a następnie wywołajprintGrades() - Wypisz
Unique grades:, a następnie wywołajprintUniqueGrades() - Odczytaj ocenę drugiego ucznia i wypisz
<name>'s grade: <grade>
Na przykład dla danych wejściowych Charlie, 85, Alice, 90, Bob, 85:
Roster (insertion order):
Charlie
Alice
Bob
Grades (alphabetical):
Alice: 90
Bob: 85
Charlie: 85
Unique grades:
85 90
Alice's grade: 90Zwróć uwagę, że wektor zachowuje kolejność dodawania (Charlie, Alice, Bob), mapa automatycznie sortuje według klucza (Alice, Bob, Charlie), a zbiór przechowuje tylko unikalne wartości w posortowanej kolejności (85 pojawia się raz, a nie dwa razy). Każdy typ kontenera sprawdza się w innych zadaniach!
Spróbuj swoich sił
#include <iostream>
#include <string>
#include "GradeManager.h"
using namespace std;
int main() {
// Wczytaj dane trzech uczniów
string name1, name2, name3;
int grade1, grade2, grade3;
cin >> name1;
cin >> grade1;
cin >> name2;
cin >> grade2;
cin >> name3;
cin >> grade3;
// TODO: Utwórz obiekt GradeManager
// TODO: Dodaj wszystkich trzech uczniów do GradeManager
// TODO: Wypisz "Roster (insertion order):" i wywołaj printRoster()
// TODO: Wypisz "Grades (alphabetical):" i wywołaj printGrades()
// TODO: Wypisz "Unique grades:" i wywołaj printUniqueGrades()
// TODO: Znajdź ocenę drugiego ucznia i wypisz "<name>'s grade: <grade>"
return 0;
}
Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.
Wszystkie lekcje w sekcji Programowanie obiektowe
1Podstawy programowania obiektowego
Pliki zewnętrzneBudowanie i kompilacja C++Pliki nagłówkowe i pliki źródłowePrzestrzenie nazw i zakresWprowadzenie do programowania obiektowego w C++Klasy a obiektyWskaźnik „this”Metody (funkcje składowe)Atrybuty (składowe danych)Podstawy konstruktorów i destruktorówPowtórzenie – prosty kalkulator4Właściwości klas
Elementy instancji a elementy statyczneGettery i setteryStałe funkcje składoweSłowo kluczowe mutableMetody i zmienne statyczneFunkcje i klasy zaprzyjaźnionePodsumowanie – menedżer konta bankowego7Dziedziczenie
Podstawy dziedziczeniaPoziomy dostępu w dziedziczeniuKolejność wywołań konstruktora i destruktoraNadpisywanie metodFunkcje wirtualne i VTableWielokrotne dziedziczenieDziedziczenie wirtualnePowtórzenie — hierarchia pracowników2Zarządzanie pamięcią
Pamięć stosu a stertyWskaźniki i referencjePamięć dynamiczna (new/delete)Inteligentne wskaźniki w C++RAII w C++Podsumowanie — menedżer tablicy dynamicznej5Hermetyzacja
Specyfikatory dostępu w C++Specyfikatory dostępu — szczegółowoUkrywanie informacjiStruktura a klasaKlasy zagnieżdżone i wewnętrznePodsumowanie — system ewidencji studentów8Polimorfizm
Polimorfizm czasu kompilacji i wykonaniaPrzeciążanie funkcjiFunkcje wirtualne — powtórkaCzysto wirtualne funkcjeKlasy abstrakcyjneProjektowanie interfejsów w C++Rzutowanie dynamiczne i RTTIPodsumowanie — kalkulator kształtów3Konstruktory i destruktory
Konstruktor domyślnyKonstruktor z parametramiKonstruktor kopiującyKonstruktor przenoszącyListy inicjalizacyjne konstruktoraKonstruktory delegująceDestruktor — szczegółowe omówienieZasada trzech / pięciu / zeraPodsumowanie — klasa String6Przeciążanie operatorów
Wprowadzenie do przeciążania operatorówPrzeciążanie operatorów arytmetycznychPrzeciążanie operatorów porównaniaOperatory strumieniowePrzeciążanie operatora przypisaniaPrzeciążanie operatorów [] i ()Operatory konwersji typówPodsumowanie — klasa Matrix9Szablony
Szablony funkcjiSzablony klasSpecjalizacja szablonówSzablony wariadycznePodstawy SFINAE i cech typówPodsumowanie — kontener generycznyPoćwicz samodzielnie: Kompilator C++ online