STL-Container
Teil des Abschnitts Objektorientierte Programmierung der C++-Journey von Coddy. Lektion 71 von 104.
STL-Container sind Template-Klassen, die Sammlungen von Objekten speichern und organisieren. Jeder Containertyp ist für unterschiedliche Zugriffsmuster und Operationen optimiert. Die Wahl des richtigen Containers für deine Anforderungen kann die Leistung deines Programms erheblich beeinflussen.
Sequenz containers verwalten elements in einer bestimmten Reihenfolge:
#include <vector>
#include <list>
std::vector<int> vec = {1, 2, 3}; // Dynamisches Array, schneller wahlfreier Zugriff
vec.push_back(4); // Am Ende hinzufügen: O(1) amortisiert
int x = vec[2]; // Zugriff per Index: O(1)
std::list<int> lst = {1, 2, 3}; // Doppelt verkettete Liste
lst.push_front(0); // Am Anfang hinzufügen: O(1)
lst.push_back(4); // Am Ende hinzufügen: O(1)Assoziative containers speichern elements in sortierter Reihenfolge für fast lookup:
#include <map>
#include <set>
std::set<int> s = {3, 1, 4, 1}; // Eindeutige sortierte Elemente: {1, 3, 4}
s.insert(2); // Einfügen: O(log n)
bool found = s.count(3); // Existenz prüfen: O(log n)
std::map<std::string, int> ages; // Schlüssel-Wert-Paare, sortiert nach Schlüssel
ages["Alice"] = 25; // Einfügen/Aktualisieren: O(log n)
ages["Bob"] = 30;
std::cout << ages["Alice"]; // Zugriff: O(log n)Ungeordnete containers verwenden Hash-Tabellen für eine noch schnellere Suche im Durchschnittsfall:
#include <unordered_map>
std::unordered_map<std::string, int> scores;
scores["player1"] = 100; // Einfügen: O(1) durchschnittlich
scores["player2"] = 200;
std::cout << scores["player1"]; // Zugriff: O(1) durchschnittlichVerwende vector, wenn du schnellen wahlfreien Zugriff benötigst, list für häufige Einfügungen in der Mitte, map/set, wenn du sortierte Daten benötigst, und unordered_map, wenn die Suchgeschwindigkeit entscheidend ist und die Reihenfolge keine Rolle spielt.
Aufgabe
EinfachErstellen wir ein Studenten-Notenverwaltungssystem, das zeigt, wie verschiedene STL-Container unterschiedlichen Zwecken dienen. Du wirst mehrere Containertypen verwenden, um Studentendaten effizient zu organisieren, und für jede Aufgabe den passenden Container auswählen.
Du wirst zwei Dateien erstellen, um deinen Code zu organisieren:
GradeManager.h: Definiere eineGradeManager-Klasse, die mehrere STL-Container verwendet, um Informationen über Studenten zu verwalten.Deine Klasse sollte Folgendes verwenden:
- Einen
std::vector<std::string>, um die Namen der Studenten in der Reihenfolge zu speichern, in der sie hinzugefügt wurden - Eine
std::map<std::string, int>, um jeden Studentennamen mit seiner Note zu verknüpfen - Ein
std::set<int>, um alle vergebenen eindeutigen Noten zu verfolgen
Implementiere diese Methoden:
addStudent(const std::string& name, int grade): fügt einen Studenten mit seiner Note zu allen drei Containern hinzugetGrade(const std::string& name): gibt mithilfe der Map die Note für einen bestimmten Studentennamen zurückprintRoster(): gibt alle Studentennamen in der Reihenfolge aus, in der sie hinzugefügt wurden (aus dem Vektor), jeweils in einer neuen ZeileprintGrades(): gibt alle Studenten mit ihren Noten in alphabetischer Reihenfolge aus (die Map übernimmt dies automatisch), formatiert alsname: gradein jeder ZeileprintUniqueGrades(): gibt alle eindeutigen Noten in aufsteigender Reihenfolge aus (das Set übernimmt dies), durch Leerzeichen getrennt und gefolgt von einem Zeilenumbruch
- Einen
main.cpp: Lies Eingaben ein und zeige, wie jeder Containertyp einem anderen Zweck dient.Lies sechs Eingaben ein (jeweils in einer eigenen Zeile):
- Name des ersten Studenten
- Note des ersten Studenten (Ganzzahl)
- Name des zweiten Studenten
- Note des zweiten Studenten (Ganzzahl)
- Name des dritten Studenten
- Note des dritten Studenten (Ganzzahl)
Erstelle einen
GradeManagerund füge alle drei Studenten hinzu. Zeige anschließend das unterschiedliche Verhalten der Container:- Gib
Roster (insertion order):aus und rufe anschließendprintRoster()auf - Gib
Grades (alphabetical):aus und rufe anschließendprintGrades()auf - Gib
Unique grades:aus und rufe anschließendprintUniqueGrades()auf - Rufe die Note des zweiten Studenten ab und gib
<name>'s grade: <grade>aus
Zum Beispiel mit den Eingaben 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: 90Beachte, wie der Vektor die Einfügereihenfolge (Charlie, Alice, Bob) beibehält, die Map automatisch nach dem Schlüssel sortiert (Alice, Bob, Charlie) und das Set nur eindeutige Werte in sortierter Reihenfolge speichert (85 erscheint einmal, nicht zweimal). Jeder Containertyp eignet sich besonders gut für unterschiedliche Aufgaben!
Probier es selbst
#include <iostream>
#include <string>
#include "GradeManager.h"
using namespace std;
int main() {
// Eingaben für drei Studenten lesen
string name1, name2, name3;
int grade1, grade2, grade3;
cin >> name1;
cin >> grade1;
cin >> name2;
cin >> grade2;
cin >> name3;
cin >> grade3;
// TODO: Erstelle ein GradeManager-Objekt
// TODO: Füge alle drei Studenten zum GradeManager hinzu
// TODO: Print "Roster (insertion order):" and call printRoster()
// TODO: Print "Grades (alphabetical):" and call printGrades()
// TODO: Print "Unique grades:" and call printUniqueGrades()
// TODO: Schlage die Note des zweiten Studenten nach und gib "<name>'s grade: <grade>" aus
return 0;
}
Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.
Alle Lektionen in Objektorientierte Programmierung
1Grundlagen der OOP
Externe DateienC++ Build & KompilierungHeader-Dateien & QuelldateienNamespaces & GültigkeitsbereichEinführung in OOP mit C++Klassen vs. ObjekteDer „this“-ZeigerMethoden (Member-Funktionen)Attribute (Datenmember)Grundlagen zu Ctors & DtorsRückblick – Einfacher Taschenrechner4Klassenattribute
Instanz- vs. statische MemberGetter und SetterConst-MemberfunktionenMutable-SchlüsselwortStatische Methoden und VariablenFriend-Funktionen und -KlassenZusammenfassung – Bankkontoverwaltung7Vererbung
Grundlagen der VererbungZugriffsebenen bei der VererbungAufrufreihenfolge von Ctor & DtorÜberschreiben von MethodenVirtuelle Funktionen & VTableMehrfachvererbungVirtuelle VererbungRückblick – Mitarbeiterhierarchie10STL-Übersicht
STL-Übersicht & PhilosophieSTL-ContainerIteratorenSTL-AlgorithmenFunktoren & Lambda-AusdrückeRückblick – Worthäufigkeit2Speicherverwaltung
Stack- vs. Heap-SpeicherZeiger und ReferenzenDynamischer Speicher (new/delete)Intelligente Zeiger in C++RAII in C++Rückblick – Dynamischer Array-Manager5Kapselung
Zugriffsbezeichner in C++Zugriffsbezeichner im DetailInformationsverbergungStruct vs. KlasseVerschachtelte und innere KlassenWiederholung – Studierendenverwaltungssystem8Polymorphie
Polymorphie zur Compilezeit vs. LaufzeitFunktionsüberladungVirtuelle Funktionen erneut betrachtetRein virtuelle FunktionenAbstrakte KlassenInterface-Design in C++Dynamic Casting & RTTIRückblick – Shape-Calculator3Konstruktoren & Destruktoren
StandardkonstruktorParametrisierter KonstruktorKopierkonstruktorMove-KonstruktorKonstruktor-InitialisierungslistenDelegierende KonstruktorenDestruktor im DetailDrei-/Fünf-/Null-RegelZusammenfassung – String-Klasse6Operatorüberladung
Einführung in die OperatorüberladungArithmetische OperatorüberladungVergleichsoperatorüberladungStream-OperatorenZuweisungsoperatorüberladungÜberladung der Operatoren [] und ()TypkonvertierungsoperatorenWiederholung – Matrix-Klasse9Templates
FunktionstemplatesKlassen-TemplatesTemplate-SpezialisierungVariadische TemplatesGrundlagen zu SFINAE und Type TraitsRückblick – Generischer ContainerÜbe selbstständig: Online-C++-Compiler