天天看點

C++STL容器總結篇之map

一、關于map的介紹

  map是STL的一個容器,和set一樣,map也是一種關聯式容器。它提供一對一(其中第一個可以稱為關鍵字,每個關鍵字隻能在map中出現一次,第二個可能稱為該關鍵字的值)的資料處理能力,由于這個特性,有助于我們處理一對一資料。這裡說下map内部資料的組織,map内部是自建一顆紅黑樹(一種非嚴格意義上的平衡二叉樹),這顆樹具有對資料自動排序的功能,是以在map内部所有的資料都是有序的。學習map我們一定要了解什麼是一對一的資料映射?

比如:一個班級中,每個學生的學号跟他的姓名就存在着一一映射的關系,這個模型用map可能輕易描述,很明顯學号用int 描述,姓名用字元串描述采用的string,于是我們使用的map形式如下:map<int , string> student;

  關于map和set底層實作以及效率問題,在另一篇《C++STL中set容器的一點總結》已經說了一些,map和set底層實作都是采用了平衡樹來實作的。這裡說一下map和set容器的差別。

對于map中的每個節點存儲的是一對資訊,包括一個鍵和一個值,各個節點之間的鍵值不能重複。

對于set中的每個節點存儲的是一個資訊,隻有一個鍵,但是每個鍵值也是唯一的。set表示的是集合的概念。

對于map的學習,或者說是對STL中的容器的學習,要知道每種容器的實作原理,每種适合适合解決什麼問題的,才關鍵~~~~

二、map容器中的函數

2.1 構造函數

map() //預設構造函數
map(const map& m) //拷貝構造函數
map(iterator begin, iterator end ); //區間構造函數
map(iterator begin, iterator end, const traits& _compare) //帶比較謂詞的構造函數
map(iterator begin, iterator end, const traits& _compare, const allocator& all) //帶配置設定器
           

map的構造函數主要是調用“拷貝構造函數”和利用“疊代器”進行初始化兩種方式,是以就不逐個示範了。

2.2 map中的基礎函數

begin(),end(),rbegin(),rend(),empty(),clear(),size(),max_size()。
以上常用的函數,看到名字應該就知道怎麼用了吧,示例代碼如下:
           
#include<iostream>
#include<map>
using namespace std;

int main(){
	map<int, string> student;
	map<int, string>::iterator ite;
	
	student.insert(pair<int, string>(1001, "張三"));
	student.insert(pair<int, string>(1002, "李四"));
    student[1005] = "王五"; //也可以這樣插入
    
	cout << "疊代器中元素如下:" << endl;
	for(ite = student.begin(); ite != student.end(); ite++){
		cout << ite->first << "   " << ite->second << endl;
	}
	cout << endl;
	
	cout << "map 的 size 的值為:" << student.size() << endl;
	cout << "map 的 max_size 的值為:" << student.max_size() << endl;

	student.clear();
	if(student.empty()){
		cout << "map 為空!" << endl;
	}else{
		cout << "map 不為空!" << endl;
	}

	return 0;
}
           

運作結果:

C++STL容器總結篇之map

2.3 map中的查找元素

  find函數和count函數在map中都能用來查找,但因為map中的鍵值是不允許重複的,是以一個鍵值隻能出現一次,這說明count的傳回值就隻能是0或1了,那麼顯然這就能完成查找了。但是用count來完成查找并不是最優的選擇,因為原來的本意是用count來完成計數的,這在vector等序列式容器中是灰常好用的,而map中之是以有這個count函數,就是為了STL提供統一的接口,這樣說來map中的upper_bound和lower_bound,equel_range等函數組合起來也是可以完成查找功能的(想一想怎麼實作)。這裡有個疑問:count和find對于完成的效率是不是一緻的呢??

我們分别看看分别用find和count來完成查找:

#include<iostream>
#include<map>
using namespace std;

int main(){
	map<int, string> student;
	map<int, string>::iterator ite;
	
	student.insert(pair<int, string>(1001, "張三"));
	student.insert(pair<int, string>(1002, "李四"));
    student[1005] = "王五"; //也可以這樣插入
    
	if(student.find(1002) != student.end()){
		cout << "find 查詢成功 !" << endl;
	}
	if(student.count(1002)){
		cout << "count 查詢成功 ! " << endl;
	}
	return 0;
}
           

運作結果:

C++STL容器總結篇之map

看到了嗎,count和find還是有差別的,那就是count隻能單純的查找元素是否存在,而find能定位要查找元素的位置。有一點需要注意的是查找的參數是鍵值哦!!

2.3 map中的資料的插入與删除

map中資料的插入,資料的插入大概有三種方式:

1. insert(pair<T1,T2,>(key1,value1))
2. insert(map<T1,T2>::value_type(key1,value1)) //這種插入方式和第一種基本相似
3. 利用數組進行插入,這個一會用程式示範吧。
           

map中資料的删除也有三種方式:

1. erase(map<T1,T2>::iterator iter)	//删除疊代器所指的節點
2. erase(key k)	//根據鍵值進行删除,删除鍵值k所指的節點 
3. erase(map<T1,T2>::iteratormap iter1,<T1,T2>::iteratoriter2)//删除iter1和iter2之間的資料
           
#include<iostream>
#include<map>
using namespace std;

int main(){
	map<int, string> student;
	map<int, string>::iterator ite;
	
	//插入示範
	student.insert(pair<int, string>(1001, "張三"));
	student.insert(pair<int, string>(1001, "張三11111"));
	student.insert(map<int, string>::value_type(1002, "李四"));
	student.insert(map<int, string>::value_type(1002, "李四111"));
    student[1003] = "王五";
    student[1003] = "王五1111";
    
	cout << "疊代器中元素如下:" << endl;
	for(ite = student.begin(); ite != student.end(); ite++){
		cout << ite->first << "   " << ite->second << endl;
	}
	cout << endl;

	//删除示範
	student[1004] = "小明";//示範删除新增兩個資料
	student[1005] = "小紅";
	
    cout << "第一種删除,疊代器删除首資料:" << endl;
    ite = student.begin();
	student.erase(ite);
	for(ite = student.begin(); ite != student.end(); ite++){
		cout << ite->first << "   " << ite->second << endl;
	}
	cout << endl;
	
	cout << "第二種删除,利用鍵值删除map中的資料:" << endl;
	student.erase(1004);
	for(ite = student.begin(); ite != student.end(); ite++){
		cout << ite->first << "   " << ite->second << endl;
	}
	cout << endl;
	
	cout << "第三種删除,利用鍵利用範圍疊代器删除map中的所有資料:" << endl;
    student.erase(student.begin(), student.end());
	for(ite = student.begin(); ite != student.end(); ite++){
		cout << ite->first << "   " << ite->second << endl;
	}
	cout << endl;
	
	return 0;
}
           
C++STL容器總結篇之map

注意:通過觀察輸出結果,利用數組進行插入對資料進行了覆寫,而其他兩種插入方式沒有進行覆寫,實際上屬于插入失敗,還要注意的是,利用數組進行插入下标實際上是鍵值。

參考部落格https://www.cnblogs.com/BeyondAnyTime/archive/2012/08/24/2654353.html

繼續閱讀