日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

[数据结构]Map和Set

發布時間:2023/11/30 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [数据结构]Map和Set 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

說起map和set,想必我們都學過紅黑樹了吧,map和set就是紅黑樹的一個應用領域。它的底層就是由紅黑樹來實現的。下面簡單說一下map和set的使用吧。

首先,有一個栗子是這樣的,讓我們統計出每種水果出現的次數。

我們會想到怎么解決的。關于map,我們知道,當你插入同樣的key值時,它就不會將要插入的key值插入到map中。但是,我們還知道,map是有倆個參數的,一個是插入的key值,另一個value可以用來統計key值出現的次數。

關于統計水果次數的問題,我們主要有以下幾種方法:

map<string,int> countMap;string strs[] = {"蘋果","香蕉","橘子","蘋果","蘋果","香蕉"};//1.從頭到尾遍歷看是否有數組中的值,沒有則插入,有則使second++for(int i = 0; i < sizeof(strs)/sizeof(strs[0]); i++){map<string,int>::iterator it = countMap.find(strs[i]);if(it != countMap.end()){it->second++;}else{countMap.insert(make_pair(strs[i],1));}}map<string,int>::iterator it1 = countMap.begin();while(it1 != countMap.end()){cout<<it1->first<<":"<<it1->second<<endl;++it1;} //2.檢測插入的返回值pair<map<string,int>::iterator,bool>的second是否為false來確定pair<map<string,int>::iterator,bool> ret;for(int i = 0; i < sizeof(strs)/sizeof(strs[0]);i++){ret = countMap.insert(make_pair(strs[i],1));if(ret.second == false)ret.first->second++;}map<string,int>::iterator it1 = countMap.begin();while(it1 != countMap.end()){cout<<it1->first<<":"<<it1->second<<endl;++it1;} //3.直接使用map重載的[]for(int i = 0; i < sizeof(strs)/sizeof(strs[0]);i++){countMap[strs[i]]++;}map<string,int>::iterator it1 = countMap.begin();while(it1 != countMap.end()){cout<<it1->first<<":"<<it1->second<<endl;++it1;}

運行結果:

這里需要注意的幾點是:

1.首先使用插入的時候,是需要插入一個pair結構體,因為map底層的value是一個pair結構體,里邊成員又有first和second;因此需要使用make_pair來構造insert的參數。
2.在使用第三種方法的時候,我們使用到map重載的operator[],說一下operator[]的函數:
(*((this->insert(make_pair(x,T()))).first)).second
分解一下上邊的operator[]的式子:
this->insert(make_pair(x,T())):返回值為pair<iterator,bool>結構體
((this->insert(make_pair(x,T()))).first):表示pair結構體中的first,即指向一個pair結構體的迭代器,此pair結構體中有key和value,也即所謂的first和second
(*((this->insert(make_pair(x,T()))).first)).second:表示取迭代器中指向的pair的second

說到map,我們還有一個multimap,是用來插入冗余的值,比如有相同的key值的時候,對于map而言,它就不會將其插入,而對于multimap而言就會插入。典型的例子為字典,我們英譯漢的時候,同一個英語單詞代表著不同的意思,這時multimap就會將每一個key值對應的不同的value值都會插入,并且以排好序的方式顯示。

1.比如map來顯示字典的時候:

typedef map<string,string> Dict;typedef map<string,string>::iterator DictIt;Dict dict;dict.insert(make_pair("left","左邊"));dict.insert(make_pair("right","右邊"));dict.insert(make_pair("left","剩余"));DictIt it = dict.begin();while (it != dict.end()){cout<<it->first<<":"<<it->second<<endl;++it;}

結果為:

2.用multimap來實現字典的時候:

typedef multimap<string,string> Dict;typedef multimap<string,string>::iterator DictIt;Dict dict;dict.insert(make_pair("left","左邊"));dict.insert(make_pair("right","右邊"));dict.insert(make_pair("left","剩余"));DictIt it = dict.begin();while (it != dict.end()){cout<<it->first<<":"<<it->second<<endl;++it;}

運行結果:

綜上所述,
(1)map和multimap可以通過key來找value,也可通過key排序
(2)當我們查找某個key值的時候,發現有多個相同的key值,此時不知道it該指向哪個pair結構體,這里要說明的是,它將返回中序遍歷的第一個key值

驗證一下:

typedef multimap<string,string> Dict;typedef multimap<string,string>::iterator DictIt;Dict dict;dict.insert(make_pair("left","左邊"));dict.insert(make_pair("right","右邊"));dict.insert(make_pair("left","剩余"));DictIt it = dict.begin();it = dict.find("left");dict.erase(it);it = dict.begin();while (it != dict.end()){cout<<it->first<<":"<<it->second<<endl;++it;}

在這里,我們找到一個key值為left的pair,此時刪除它后再打印一下發現得出的是比它大的value值。

說完map和multimap后,與之對應的還有set和multiset。set和multiset是用來判斷這個值存在或者不存在。其次也可以用來排序。還有一個特點是過濾(去重)。

1.檢測其存在或者不存在

void TestSet() {typedef set<string> MySet;typedef set<string>::iterator MySetIt;MySet myset;string strs[] = {"蘋果","香蕉","橘子","西瓜","草莓","櫻桃"};for(int i = 0; i < sizeof(strs)/sizeof(strs[0]); i++){myset.insert(strs[i]);}MySetIt it = myset.begin();if(it == myset.find("哈密瓜"))cout<<"哈密瓜存在"<<endl;elsecout<<"哈密瓜不存在"<<endl;cout<<"存在的其他水果為:"<<endl;it = myset.begin();while(it != myset.end()){cout<<*it<<endl;++it;} }

運行結果:

2.排序和去重

typedef set<int> MySet;typedef set<int>::iterator MySetIt;MySet myset;for(int i = 10; i > 0; i--)myset.insert(i);myset.insert(5);MySetIt it = myset.begin();while(it != myset.end()){cout<<*it<<endl;++it;}

運行結果:

對于過濾來說,就是如果有相同的key值,它就會去掉相同的key,只插入一個到set中。

這里multiset的意義和multimap差不多,也是處理冗余的數據。使用方法類似。

對于map和set的底層是怎么實現的呢。它是通過寫的一個紅黑樹。主要的區別是

里邊的value_type的意義,對于map來說,value_type指的是一個pair的結構體,結構體成員為key和value,而對于set來說,value_type指的是key值。
在紅黑樹中,用了枚舉來表示顏色。而在源碼的紅黑樹中使用了bool值來代替紅黑倆種顏色
我們還知道,map和multimap,set和multiset也有區別,底層是怎么用紅黑樹的呢。它是插入的時候分別對紅黑樹的插入分為唯一插入(insert_unique)和相等插入(insert_equal)(相等插入就是對冗余數據的考慮)。
set的插入:

map中value_type: typedef pair<const Key, T> value_type;
set中value_type: typedef Key value_type;

set的插入:

typedef pair<iterator, bool> pair_iterator_bool; pair<iterator,bool> insert(const value_type& x) { pair<typename rep_type::iterator, bool> p = t.insert_unique(x); return pair<iterator, bool>(p.first, p.second);}

map的插入:

pair<iterator,bool> insert(const value_type& x) { return t.insert_unique(x); }

multimap的插入:

iterator insert(const value_type& x) { return t.insert_equal(x); }

multiset的插入:

iterator insert(const value_type& x) { return t.insert_equal(x);}

還可以進行相關的區間的插入,刪除,某個位置的插入刪除等操作。

小姿勢:

lower_bound : 用來找到比key值大的數 upper_bound : 用來找到比key值大的數

總結

以上是生活随笔為你收集整理的[数据结构]Map和Set的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。