C++中map和unordered_map的用法


1. 簡介

map和unordered_map都是c++中可以充當字典(key-value)來用的數據類型,但是其基本實現是不一樣的。

2. map

對於map的底層原理,是通過紅黑樹(一種非嚴格意義上的平衡二叉樹)來實現的,因此map內部所有的數據都是有序的,map的查詢、插入、刪除操作的時間復雜度都是O(logn)。此外,map的key需要定義operator <,對於一般的數據類型已被系統實現,若是用戶自定義的數據類型,則要重新定義該操作符。

map的基本操作如下

#include<iostream>
#include<map>
#include<string>
 
using namespace std;
 
int main()
{
	// 構造函數
	map<string, int> dict;
	
	// 插入數據的三種方式
	dict.insert(pair<string,int>("apple",2));
	dict.insert(map<string, int>::value_type("orange",3));
	dict["banana"] = 6;
 
	// 判斷是否有元素
	if(dict.empty())
		cout<<"該字典無元素"<<endl;
	else
		cout<<"該字典共有"<<dict.size()<<"個元素"<<endl;
 
	// 遍歷
	map<string, int>::iterator iter;
	for(iter=dict.begin();iter!=dict.end();iter++)
		cout<<iter->first<<ends<<iter->second<<endl;
 
	// 查找
	if((iter=dict.find("banana"))!=dict.end()) //  返回一個迭代器指向鍵值為key的元素,如果沒找到就返回end()
		cout<<"已找到banana,其value為"<<iter->second<<"."<<endl;
	else
		cout<<"未找到banana."<<endl;
 
	if(dict.count("watermelon")==0) // 返回鍵值等於key的元素的個數
		cout<<"watermelon不存在"<<endl;
	else
		cout<<"watermelon存在"<<endl;
	
	pair<map<string, int>::iterator, map<string, int>::iterator> ret;
	ret = dict.equal_range("banana"); // 查找鍵值等於 key 的元素區間為[start,end),指示范圍的兩個迭代器以 pair 返回
	cout<<ret.first->first<<ends<<ret.first->second<<endl;
	cout<<ret.second->first<<ends<<ret.second->second<<endl;
 
	iter = dict.lower_bound("boluo"); // 返回一個迭代器,指向鍵值>=key的第一個元素。
	cout<<iter->first<<endl;
	iter = dict.upper_bound("boluo"); // 返回一個迭代器,指向值鍵值>key的第一個元素。
	cout<<iter->first<<endl;
	return 0;
}

  


注意如果定義了map<string,int>這個類型,需要在頭文件中包含“#include<string>”,這是因為默認的string是系統的xstring對象,但是沒有定義operator<,從而報錯。map用到自定義的類型,一定要定義operator<,具體用法如下。

struct person  
{  
    string name;  
    int age;  
  
    person(string name, int age)  
    {  
        this->name =  name;  
        this->age = age;  
    }  
  
    bool operator < (const person& p) const  
    {  
        return this->age < p.age;   
    }  
};  
  
map<person,int> m; 

  

 

3. unordered_map

unordered_map和map類似,都是存儲的key-value的值,可以通過key快速索引到value。不同的是unordered_map不會根據key的大小進行排序,存儲時是根據key的hash值判斷元素是否相同,即unordered_map內部元素是無序的。unordered_map的底層是一個防冗余的哈希表(開鏈法避免地址沖突)。unordered_map的key需要定義hash_value函數並且重載operator ==。

哈希表最大的優點,就是把數據的存儲和查找消耗的時間大大降低,時間復雜度為O(1);而代價僅僅是消耗比較多的內存。哈希表的查詢時間雖然是O(1),但是並不是unordered_map查詢時間一定比map短,因為實際情況中還要考慮到數據量,而且unordered_map的hash函數的構造速度也沒那么快,所以不能一概而論,應該具體情況具體分析。

unordered_map的基本操作

#include<string>  
#include<iostream>  
#include<unordered_map>
using namespace std;  
  
int main()
{
	unordered_map<string, int>  dict; // 聲明unordered_map對象
	
	// 插入數據的三種方式
	dict.insert(pair<string,int>("apple",2));
	dict.insert(unordered_map<string, int>::value_type("orange",3));
	dict["banana"] = 6;
	
	// 判斷是否有元素
	if(dict.empty())
		cout<<"該字典無元素"<<endl;
	else
		cout<<"該字典共有"<<dict.size()<<"個元素"<<endl;
	
	// 遍歷
	unordered_map<string, int>::iterator iter;
	for(iter=dict.begin();iter!=dict.end();iter++)
		cout<<iter->first<<ends<<iter->second<<endl;
	
	// 查找
	if(dict.count("boluo")==0)
		cout<<"can't find boluo!"<<endl;
	else
		cout<<"find boluo!"<<endl;
	
	if((iter=dict.find("banana"))!=dict.end())
		cout<<"banana="<<iter->second<<endl;
	else
		cout<<"can't find boluo!"<<endl;
	
	return 0;
}

  

nordered_map用到自定義的類型,需要對key定義hash_value函數並且重載operator ==,具體用法請參考文獻

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM