1. 程式人生 > >C++ 關聯容器

C++ 關聯容器

順序容器的底層構造是陣列和連結串列,而關聯容器的底層是紅黑樹、雜湊表,提供高效的查詢、新增和刪除操作。關聯容器與順序容器相比的優勢:

  1. 具有高效的關鍵字查詢和訪問
  2. 支援組合(關鍵字+值)的儲存方式

一、關聯容器概述

關聯容器的型別總結如下:

  • map,儲存“關鍵字-值”
  • set,關鍵字即值,只儲存一個“值”
  • multimap,關鍵字可重複的map
  • multiset,關鍵字可重複的set
  • unordered_map,無序map
  • unordered_set,無序set
  • unordered_multimap,無序可重複map
  • unordered_multiset,無序可重複set

總結一下,主要是map和set兩種,衍生出可重複和無序的各種版本。
各自具有各自的標頭檔案,例如map的標頭檔案< map >

二、map和set

map儲存的是“關鍵字”和“值”的組合體。
map是按關鍵字排序的有序序列,並且關鍵字唯一。
set儲存的“關鍵字”。
set也是按關鍵字排序的有序序列,並且關鍵字唯一。

map主要用於儲存兩個關聯單元,比如儲存圖書名和對應的作者。
set主要用於頻繁查詢,比如在挨個處理單詞時,想把“a”,“the”等詞刪除,那麼就把這些詞放在set中,處理時把每個單詞到set中查一下,如果有,就刪掉。
其餘的版本都是它倆的擴充,可以根據實際需要選擇。

三、map和set的使用

map和set唯一的區別就是map裡放的是繫結的兩個值(關鍵字-值),而set放的單個值,在儲存方面有點類似於順序容器,但是操作比順序容器高效。

  1. 定義
//map
	//未初始化 
	map<string,int> mp1;
	//列表初始化 
	map<string,int> mp2 = {{"a",1},{"b",2}};
//set
	//未初始化
	set<string> st1;
	//列表初始化 
	set<string> st2 = {"a","b","c"};

map與set的定義只是型別上的不同,map需要指明兩個型別,set只需一個。

  1. 訪問
//map
	//遍歷訪問 
	for(auto i = mp2.cbegin(); i != mp2.cend(); i++)
	{
		cout << i->first << i->second << endl;
		//等同於 
		cout << (*i).first << (*i).second << endl;
	}
	//按關鍵字訪問 
	cout << mp2["a"];//輸出的是1
//set
	for(auto i = st2.cbegin(); i != st2.cend(); i++)
	{
		cout << *i << endl;
	}

其中遍歷訪問與順序容器類似,因為map儲存的是“關鍵字-值”的型別,所以需要用first訪問關鍵字,用second訪問值。
有意思的是按關鍵字訪問,map按關鍵字升序存放,所以支援以關鍵字為下標的訪問,返回的是關鍵字對應的值。set不支援,因為它就一個值。
set的訪問和順序容器一樣。

  1. 新增元素
//map
	//單個插入 
	mp2.insert(pair<string,int>("c",2));
	//列表插入 
	mp2.insert({{"d",1},{"e",1}});
	//迭代器插入
	mp2.inset(b,e); 
//set
	//單個插入 
	st2.insert("abc");
	//迭代器插入
	st2.insert(b,e);

map比較常用的單個插入和列表插入。其中pair是將string和int型別的兩個值繫結在一起。
set的迭代器插入很方便,可以將指向順序容器中的迭代器範圍內的元素插入,前提是型別得相同。

  1. 查詢
	//查詢 
	auto f = mp2.find("a"); 
	//計數 
	auto c = count("a");

在map中查詢和計數效果一樣,因為map關鍵字唯一。在multimap中,關鍵字相同的按順序放在一起,所以可以先計數,然後找到第一個,按數量順序訪問。
set類似,它只有一個值。

  1. 刪除
	//按關鍵字刪除
	auto e1 = mp2.erase("a"); 
	//按迭代器刪除
	auto e2 = mp2.erase(p); 

set和map都一樣,都是根據關鍵字或者迭代器刪除,map刪除的是“關鍵字-值”,set刪除的是關鍵字。

四、其他關聯容器

map/set關鍵字唯一,當關鍵字不唯一的時候,可以用mutimap或者mutiset。
map/set自動按升序排序,當順序不重要的時候,可以用unordered_map或者unordered_set。
無序容器不按順序排序,輸出的順序和有序容器可能不同。順序可能不同,但結果是相同的。