Middle
Πότε πρέπει να χρησιμοποιείτε std::set και πότε std::unordered_set σε C++;
sobes.tech AI
Απάντηση από AI
Το std::set και το std::unordered_set χρησιμοποιούνται για την αποθήκευση μοναδικών στοιχείων. Η επιλογή μεταξύ τους εξαρτάται από τις προτεραιότητες: ταξινόμηση ή απόδοση πρόσβασης/εισαγωγής/διαγραφής.
Το std::set βασίζεται σε ένα ισορροπημένο δυαδικό δέντρο αναζήτησης (συνήθως ένα κόκκινο-μαύρο δέντρο).
Χαρακτηριστικά του std::set:
- Τα στοιχεία αποθηκεύονται σε ταξινομημένη σειρά.
- Η εισαγωγή, διαγραφή και αναζήτηση στοιχείων διαρκεί κατά μέσο όρο O(log N), όπου N είναι ο αριθμός των στοιχείων.
- Κατάλληλο όταν η ταξινομημένη σειρά των στοιχείων είναι σημαντική ή όταν απαιτείται η λήψη στοιχείων σε συγκεκριμένο εύρος.
Το std::unordered_set βασίζεται σε έναν πίνακα κατακερματισμού.
Χαρακτηριστικά του std::unordered_set:
- Τα στοιχεία δεν αποθηκεύονται σε ταξινομημένη σειρά.
- Η εισαγωγή, διαγραφή και αναζήτηση στοιχείων διαρκεί κατά μέσο όρο O(1), αλλά στην χειρότερη περίπτωση (με πολλές συγκρούσεις στη συνάρτηση κατακερματισμού) μπορεί να φτάσει το O(N).
- Απαιτεί ο τύπος του στοιχείου να έχει μια ορισμένη συνάρτηση κατακερματισμού (
std::hash) και τελεστή σύγκρισης ισότητας (operator==). - Κατάλληλο όταν απαιτείται η μέγιστη ταχύτητα εισαγωγής, διαγραφής και αναζήτησης, και η σειρά των στοιχείων δεν έχει σημασία.
Πίνακας σύνοψης:
| Κριτήριο | std::set |
std::unordered_set |
|---|---|---|
| Εσωτερική δομή | Ισορροπημένο δέντρο | Πίνακας κατακερματισμού |
| Σειρά στοιχείων | Ταξινομημένη | Μη ταξινομημένη |
| Χρόνος αναζήτησης/εισαγωγής/διαγραφής (μέσος όρος) | O(log N) | O(1) |
| Χρόνος αναζήτησης/εισαγωγής/διαγραφής (χειρότερη περίπτωση) | O(log N) | O(N) |
| Απαιτήσεις τύπου | Τελεστής < |
std::hash, operator== |
Παράδειγμα χρήσης του std::set:
#include <iostream>
#include <set>
int main() {
std::set<int> ταξινομημένο_set;
ταξινομημένο_set.insert(5);
ταξινομημένο_set.insert(2);
ταξινομημένο_set.insert(8);
// Τα στοιχεία εμφανίζονται με ταξινομημένη σειρά: 2 5 8
for (int τιμή : ταξινομημένο_set) {
std::cout << τιμή << " ";
}
std::cout << std::endl;
return 0;
}
Παράδειγμα χρήσης του std::unordered_set:
#include <iostream>
#include <unordered_set>
int main() {
std::unordered_set<int> μη_ταξινομημένο_set;
μη_ταξινομημένο_set.insert(5);
μη_ταξινομημένο_set.insert(2);
μη_ταξινομημένο_set.insert(8);
// Η σειρά εμφάνισης μπορεί να διαφέρει
for (int τιμή : μη_ταξινομημένο_set) {
std::cout << τιμή << " ";
}
std::cout << std::endl;
return 0;
}