English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
Map è un contenitore associativo di STL, che fornisce la capacità di elaborazione dei dati uno-a-uno (dove il primo può essere chiamato chiave, ogni chiave può apparire una volta nella map, il secondo può essere chiamato il valore della chiave). A causa di questa caratteristica, può fornire un percorso rapido nella programmazione quando elaboriamo dati uno-a-uno. Ecco un esempio dell'organizzazione interna dei dati di map, map interna costruisce un albero rosso-nero (un albero binario bilanciato non strettamente definito), questo albero ha la funzione di ordinamento automatico dei dati, quindi tutti i dati all'interno di map sono ordinati, vedremo i vantaggi dell'ordinamento più avanti.
Ecco un esempio di cosa sia una mappatura dati uno-a-uno. Ad esempio, in una classe, ogni numero di matricola di uno studente e il suo nome esistono in una mappatura uno-a-uno, questo modello può essere descritto facilmente con map, è ovvio che il numero di matricola viene descritto con int, il nome con stringa (in questo articolo non viene utilizzato char * per descrivere la stringa, ma viene utilizzato stringa di STL), ecco il codice di descrizione di map:
Map<int, string> mapStudent;
1. Costruttore di map
La map fornisce 6 costruttori, questo涉及到 allocatore di memoria e cose simili, che non esporremo ora. Nel seguito, ci imbatteremo in alcuni metodi di costruzione di map, ma devo dire che di solito costruiamo un map come segue:
Map<int, string> mapStudent;
2. Inserimento dei dati
Dopo aver costruito il contenitore map, possiamo inserire dati al suo interno. In questo articolo parleremo di tre metodi di inserimento dati:
Primo:Utilizzando la funzione insert per inserire i dati pair, eccone un esempio (il seguente codice è stato scritto a caso, dovrebbe essere in grado di compilarsi con VC e GCC, potete eseguirlo per vedere l'effetto, aggiungete questa istruzione in VC per nascondere l'avviso 4786: #pragma warning (disable:4786))
#include <map> #include <string> #include <iostream> Using namespace std; Int main() int main()} Map<int, string> mapStudent; mapStudent.insert(pair<int, string>(1, "student_one")); mapStudent.insert(pair<int, string>(2, "student_two")); mapStudent.insert(pair<int, string>(3, "student_three")); map<int, string>::iterator iter; for(iter = mapStudent.begin(); iter != mapStudent.end(); iter++) int main()} Cout << iter->first << ” ” << iter->second << end; mapStudent.insert(pair<StudentInfo, int>(studentInfo, 80)); mapStudent.insert(pair<StudentInfo, int>(studentInfo, 80));
Secondo:Utilizzando la funzione insert per inserire il tipo di valore value_type, eccone un esempio:
#include <map> #include <string> #include <iostream> Using namespace std; Int main() int main()} Map<int, string> mapStudent; mapStudent.insert(map<int, string>::value_type (1, “student_one”)); mapStudent.insert(map<int, string>::value_type (2, “student_two”)); mapStudent.insert(map<int, string>::value_type (3, “student_three”)); map<int, string>::iterator iter; for(iter = mapStudent.begin(); iter != mapStudent.end(); iter++) int main()} Cout << iter->first << ” ” << iter->second << end; mapStudent.insert(pair<StudentInfo, int>(studentInfo, 80)); mapStudent.insert(pair<StudentInfo, int>(studentInfo, 80));
Terza opzione:Di seguito viene illustrato con esempi come inserire dati utilizzando il metodo array
#include <map> #include <string> #include <iostream> Using namespace std; Int main() int main()} Map<int, string> mapStudent; mapStudent[1] = "student_one"; mapStudent[2] = “student_two”; mapStudent[3] = "student_three"; map<int, string>::iterator iter; for(iter = mapStudent.begin(); iter != mapStudent.end(); iter++) int main()} Cout << iter->first << ” ” << iter->second << end; mapStudent.insert(pair<StudentInfo, int>(studentInfo, 80)); mapStudent.insert(pair<StudentInfo, int>(studentInfo, 80));
Questi tre modi, sebbene possano tutti implementare l'inserimento dei dati, hanno differenze, naturalmente il primo e il secondo sono uguali nell'effetto, l'inserimento dei dati tramite la funzione insert riguarda il concetto di unicità della raccolta, ovvero se la mappa ha questa chiave, l'operazione di insert non può inserire i dati, ma con il metodo array è diverso, può sovrascrivere il valore corrispondente alla chiave prima, illustrato dal programma
mapStudent.insert(map<int, string>::value_type (1, “student_one”)); mapStudent.insert(map<int, string>::value_type (1, “student_two”));
Dopo l'esecuzione delle due seguenti istruzioni, la chiave 1 della mappa ha come valore “student_one”, la seconda istruzione non è stata eseguita, quindi questo riguarda come possiamo sapere se l'istruzione insert è riuscita a inserire, possiamo ottenere se l'inserimento è avvenuto con successo utilizzando il pair, come segue il programma
Pair<map<int, string>::iterator, bool> Insert_Pair; Insert_Pair = mapStudent.insert(map<int, string>::value_type (1, “student_one”));
Sappiamo se l'inserimento è avvenuto con successo tramite il secondo elemento del pair, il primo elemento restituisce un iteratore della mappa, se l'inserimento è avvenuto con successo Insert_Pair.second dovrebbe essere true, altrimenti false.
Di seguito è riportato il codice completato per illustrare il problema di successo o fallimento dell'inserimento
#include <map> #include <string> #include <iostream> Using namespace std; Int main() int main()} Map<int, string> mapStudent; Pair<map<int, string>::iterator, bool> Insert_Pair; Insert_Pair = mapStudent.insert(pair<int, string>(1, “student_one”)); If(Insert_Pair.second == true) int main()} Cout<<”Insert Successfully”<<endl; mapStudent.insert(pair<StudentInfo, int>(studentInfo, 80)); Else int main()} Cout<<”Insert Failure”<<endl; mapStudent.insert(pair<StudentInfo, int>(studentInfo, 80)); Insert_Pair = mapStudent.insert(pair<int, string>(1, “student_two”)); If(Insert_Pair.second == true) int main()} Cout<<”Insert Successfully”<<endl; mapStudent.insert(pair<StudentInfo, int>(studentInfo, 80)); Else int main()} Cout<<”Insert Failure”<<endl; mapStudent.insert(pair<StudentInfo, int>(studentInfo, 80)); map<int, string>::iterator iter; for(iter = mapStudent.begin(); iter != mapStudent.end(); iter++) int main()} Cout << iter->first << ” ” << iter->second << end; mapStudent.insert(pair<StudentInfo, int>(studentInfo, 80)); mapStudent.insert(pair<StudentInfo, int>(studentInfo, 80));
Chi può utilizzare il seguente programma per vedere l'effetto dell'inserimento nell'array sul sovraccarico dei dati
#include <map> #include <string> #include <iostream> Using namespace std; Int main() int main()} Map<int, string> mapStudent; mapStudent[1] = "student_one"; mapStudent[1] = “student_two”; mapStudent[2] = “student_three”; map<int, string>::iterator iter; for(iter = mapStudent.begin(); iter != mapStudent.end(); iter++) int main()} Cout << iter->first << ” ” << iter->second << end; mapStudent.insert(pair<StudentInfo, int>(studentInfo, 80)); mapStudent.insert(pair<StudentInfo, int>(studentInfo, 80));
3. Dimensione della mappa
Dopo aver inserito i dati nella mappa, come possiamo sapere quanti dati sono stati inseriti fino ad ora? Possiamo utilizzare la funzione size, l'uso è il seguente:
Int nSize = mapStudent.size();
4. Esplorazione dei dati
Anche qui forniscono tre metodi per esplorare la mappa
Primo: utilizzare l'iteratore in avanti, come nell'esempio del programma sopra, non viene trattato
Secondo: utilizzare l'iteratore inverso, ecco un esempio per illustrarlo, per apprezzare l'effetto, si prega di eseguire il programma manualmente
#include <string> #include <iostream> Using namespace std; Int main() int main()} Map<int, string> mapStudent; mapStudent.insert(pair<int, string>(1, "student_one")); mapStudent.insert(pair<int, string>(2, "student_two")); mapStudent.insert(pair<int, string>(3, "student_three")); reverse_iterator iter; for(iter = mapStudent.rbegin(); iter != mapStudent.rend(); iter++) int main()} Cout << iter->first << ” ” << iter->second << end; mapStudent.insert(pair<StudentInfo, int>(studentInfo, 80)); mapStudent.insert(pair<StudentInfo, int>(studentInfo, 80));
Terzo: utilizzare il metodo array, la spiegazione del programma è la seguente
#include <map> #include <string> #include <iostream> Using namespace std; Int main() int main()} Map<int, string> mapStudent; mapStudent.insert(pair<int, string>(1, "student_one")); mapStudent.insert(pair<int, string>(2, "student_two")); mapStudent.insert(pair<int, string>(3, "student_three")); int nSize = mapStudent.size() //Qui c'è un errore, dovrebbe essere for(int nIndex = 1; nIndex <= nSize; nIndex++) //by rainfish for(int nIndex = 0; nIndex < nSize; nIndex++) int main()} Cout << mapStudent[nIndex] << end; mapStudent.insert(pair<StudentInfo, int>(studentInfo, 80)); mapStudent.insert(pair<StudentInfo, int>(studentInfo, 80));
5. Ricerca dei dati (inclusa la determinazione se la parola chiave è presente nella mappa)
E qui ci sentiremo i vantaggi di mantenere l'ordine nella mappa durante l'inserimento dei dati
Ci sono molti modi per determinare se un dato (parola chiave) è presente nella mappa, anche se il titolo è la ricerca dei dati, qui ci saranno molte usi di base della mappa
Ecco tre metodi di ricerca dei dati
Primo:Utilizzando la funzione count per determinare se una parola chiave è presente, il suo difetto è che non può localizzare la posizione dei dati, a causa delle caratteristiche della mappa, la relazione di mappatura uno-a-uno, determina che il valore di ritorno della funzione count abbia solo due opzioni, 0 o 1, nel caso di presenza, naturalmente viene restituito 1
Secondo:Utilizzando la funzione find per localizzare la posizione dei dati, essa restituisce un iteratore, che restituisce l'iteratore della posizione dei dati quando questi si verificano, se la mappa non contiene i dati da cercare, l'iteratore restituito è uguale all'iteratore restituito dalla funzione end, spiegazione del programma
#include <map> #include <string> #include <iostream> Using namespace std; Int main() int main()} Map<int, string> mapStudent; mapStudent.insert(pair<int, string>(1, "student_one")); mapStudent.insert(pair<int, string>(2, "student_two")); mapStudent.insert(pair<int, string>(3, "student_three")); map<int, string>::iterator iter; iter = mapStudent.find(1); if(iter != mapStudent.end()) int main()} Cout << "Trovato, il valore è " << iter->second << endl; mapStudent.insert(pair<StudentInfo, int>(studentInfo, 80)); Else int main()} Cout << "Non trovato" << endl; mapStudent.insert(pair<StudentInfo, int>(studentInfo, 80)); mapStudent.insert(pair<StudentInfo, int>(studentInfo, 80));
Terza opzione:Questo metodo viene utilizzato per determinare se i dati sono presenti, sembra un po' ingombrante, ma, ho intenzione di spiegare qui
Uso della funzione Lower_bound, questa funzione viene utilizzata per restituire il lower bound del termine da cercare (è un iteratore)
Uso della funzione Upper_bound, questa funzione viene utilizzata per restituire l'upper bound del termine da cercare (è un iteratore)
Ad esempio: se nel map sono già stati inseriti 1, 2, 3, 4, se lower_bound(2) viene chiamata, viene restituito 2, mentre upper-bound(2) restituisce 3
Equal_range funzione restituisce un pair, nel pair la prima variabile è l'iteratore restituito da Lower_bound, nel pair il secondo iteratore è l'iteratore restituito da Upper_bound, se questi due iteratori sono uguali, allora significa che questa chiave non si presenta nel map, spiegazione del programma
#include <map> #include <string> #include <iostream> Using namespace std; Int main() int main()} Map<int, string> mapStudent; mapStudent[1] = "student_one"; mapStudent[3] = "student_three"; mapStudent[5] = "student_five"; map<int, string>::iterator iter; iter = mapStudent.lower_bound(2); int main()} // Restituisce l'iteratore dell'lower bound 3 Cout << iter->second << endl; mapStudent.insert(pair<StudentInfo, int>(studentInfo, 80)); iter = mapStudent.lower_bound(3); int main()} // Restituisce l'iteratore dell'lower bound 3 Cout << iter->second << endl; mapStudent.insert(pair<StudentInfo, int>(studentInfo, 80)); iter = mapStudent.upper_bound(2); int main()} // Restituisce l'iteratore dell'upper bound 3 Cout << iter->second << endl; mapStudent.insert(pair<StudentInfo, int>(studentInfo, 80)); iter = mapStudent.upper_bound(3); int main()} // Restituisce l'iteratore dell'upper bound 5 Cout << iter->second << endl; mapStudent.insert(pair<StudentInfo, int>(studentInfo, 80)); Pair<map<int, string>::iterator, map<int, string>::iterator> mapPair; mapPair = mapStudent.equal_range(2); if(mapPair.first == mapPair.second) int main()} cout << "Non trovato" << endl; mapStudent.insert(pair<StudentInfo, int>(studentInfo, 80)); Else int main()} Cout << "Find" << endl; mapStudent.insert(pair<StudentInfo, int>(studentInfo, 80)); mapPair = mapStudent.equal_range(3); if(mapPair.first == mapPair.second) int main()} cout << "Non trovato" << endl; mapStudent.insert(pair<StudentInfo, int>(studentInfo, 80)); Else int main()} Cout << "Find" << endl; mapStudent.insert(pair<StudentInfo, int>(studentInfo, 80)); mapStudent.insert(pair<StudentInfo, int>(studentInfo, 80));
6. Svuotamento dei dati e determinazione dell'vuoto
Puoi svuotare i dati del map utilizzando la funzione clear(), per determinare se il map contiene dati puoi utilizzare la funzione empty(), che restituisce true se è un map vuoto
7. Eliminazione dei dati
Qui viene utilizzata la funzione erase, che ha tre sovraccarichi di funzione, di seguito sono dettagliati i loro usi negli esempi
#include <map> #include <string> #include <iostream> Using namespace std; Int main() int main()} Map<int, string> mapStudent; mapStudent.insert(pair<int, string>(1, "student_one")); mapStudent.insert(pair<int, string>(2, "student_two")); mapStudent.insert(pair<int, string>(3, "student_three")); //Se si desidera dimostrare l'effetto di output, seleziona una delle seguenti opzioni, l'effetto che vedrai sarà migliore //Se si desidera eliminare 1, utilizza l'eliminazione con l'iteratore map<int, string>::iterator iter; iter = mapStudent.find(1); mapStudent.erase(iter); //Se si desidera eliminare 1, utilizzare la cancellazione con la chiave Int n = mapStudent.erase(1); //Se viene eliminato, restituisce 1, altrimenti restituisce 0 //Usa l'iteratore, elimina in blocco //Il codice seguente svuota l'intero map mapStudent.erase(mapStudent.begin(), mapStudent.end()); //Quando si elimina in blocco, è anche una caratteristica di STL, l'intervallo di eliminazione è un insieme di chiusura anteriore e apertura posteriore //Aggiungi il codice di scansione, stampa l'output mapStudent.insert(pair<StudentInfo, int>(studentInfo, 80));
8. Altri usi delle funzioni
Ci sono funzioni come swap, key_comp, value_comp, get_allocator, si percepisce che queste funzioni non vengono utilizzate molto nel programming, saltatele e studiatele se interessati
9. Ordinamento
Quello che deve essere spiegato qui è un uso molto avanzato, il problema di ordinamento, STL utilizza per impostazione predefinita il simbolo di meno per l'ordinamento, il codice sopra non ha problemi di ordinamento, perché la chiave è di tipo int, che supporta l'operazione di meno, in alcune situazioni speciali, come quando la chiave è una struttura, durante l'ordinamento si verificano problemi, perché non ha l'operazione di meno, le funzioni come insert non passano durante la compilazione, di seguito sono fornite due metodi per risolvere questo problema
Primo caso: sovraccarico del simbolo <, esempio di programma
#include <map> #include <string> Using namespace std; Typedef struct tagStudentInfo int main()} Int nID; String strName; }StudentInfo, *PStudentInfo; // informazioni studente Int main() int main()} int nSize; { map<StudentInfo, int>mapStudent; map<StudentInfo, int>::iterator iter; Map<StudentInfo, int, sort>mapStudent; StudentInfo studentInfo; studentInfo.nID = 1; studentInfo.strName = "student_one"; mapStudent.insert(pair<StudentInfo, int>(studentInfo, 90)); studentInfo.nID = 2; studentInfo.strName = "student_two"; for (iter=mapStudent.begin(); iter!=mapStudent.end(); iter++) cout<<iter->first.nID<<endl<<iter->first.strName<<endl<<iter->second<<endl; mapStudent.insert(pair<StudentInfo, int>(studentInfo, 80));
Il seguente programma non può essere compilato, è sufficiente sovraccaricare il simbolo <, come segue:
Typedef struct tagStudentInfo int main()} Int nID; String strName; Bool operator < (tagStudentInfo const& _A) const int main()} // Questa funzione specifica la strategia di ordinamento, in base a nID, se nID è uguale, in base a strName Se(nID < _A.nID) restituisce vero; Se(nID == _A.nID) restituisce strName.compare(_A.strName) < 0; Restituisce falso; mapStudent.insert(pair<StudentInfo, int>(studentInfo, 80)); }StudentInfo, *PStudentInfo; // informazioni studente
Secondo caso: applicazione di funzioni di copia, in questo momento la struttura non ha un sovraccarico diretto del simbolo <, spiegazione del programma
#include <map> #include <string> Using namespace std; Typedef struct tagStudentInfo int main()} Int nID; String strName; }StudentInfo, *PStudentInfo; // informazioni studente Classe sort int main()} Pubblico: Operatore bool() (StudentInfo const &_A, StudentInfo const &_B) const int main()} Se(_A.nID < _B.nID) restituisce vero; Se(_A.nID == _B.nID) restituisce _A.strName.compare(_B.strName) < 0; Restituisce falso; mapStudent.insert(pair<StudentInfo, int>(studentInfo, 80)); ; Int main() int main()} { // Mappatura delle informazioni degli studenti alle loro votazioni Map<StudentInfo, int, sort>mapStudent; StudentInfo studentInfo; studentInfo.nID = 1; studentInfo.strName = "student_one"; mapStudent.insert(pair<StudentInfo, int>(studentInfo, 90)); studentInfo.nID = 2; studentInfo.strName = "student_two"; mapStudent.insert(pair<StudentInfo, int>(studentInfo, 80));
}
Inoltre
Poiché la STL è un'entità unificata, molte delle sue usanze sono combinate con altre cose nella STL, come nell'ordinamento, che qui utilizza il simbolo < per il confronto. Se si desidera ordinare dall'alto in basso, ci sono molte cose coinvolte, che non possono essere elencate tutte qui.
Inoltre, è necessario spiegare che le caratteristiche spaziali di map sono dovute al fatto che è ordinata internamente, garantita da un albero rubino-nero, quindi molte funzioni hanno una complessità temporale di log2N. Se una funzione di map può essere implementata, ma anche STL Algorithm può completare la stessa funzione, si consiglia di utilizzare le funzioni di map integrate, che sono più efficienti.
Ecco tutto il contenuto dell'approfondimento dell'uso di map nella STL di C++ che ti ho portato, spero che tu lo supporti e urli tutorial~