最近學習了紅黑樹,雖然紅黑樹學的不是很扎實,但是還是在此之上做出了拓展,然后就學到了兩個新的容器。set和map,這兩個在c++標準模板庫STL中被稱為關聯式容器,它們就像是一個數組,把一個元素(key)映射到另一個元素(value)上,當然對于set來說value值就是key值;而map則是所有元素都是pair類型,同時擁有key和value,并且唯一。下面就對此作出一些解釋。
我們看到key_type和value_type都是由T表示的,說明這兩個并沒有什么區別。
set作為常用的容器,其在底層是通過紅黑樹進行實現的,我們可以在源碼中查看。當然,在使用set這個容器的時候,我們經常會用到它的兩個功能:排序和過濾。
排序就是在使用set的時候它會自動幫你排序(通過上面的圖片我們發現這是默認為less,也就是升序的),而過濾就是它里面不會出現重復的key值,下面用例子演示一下。
代碼如下:
#define _CRT_SECURE_NO_WARNINGS 1#include<iostream>using namespace std;#include<set>void Testset(){ set<int> s; s.insert(1); s.insert(11); s.insert(9); s.insert(6); s.insert(5); s.insert(1); set<int>::iterator it1 = s.begin(); while (it1 != s.end()) { cout << *it1 << " "; it1++; } cout << endl;}int main(){ Testset(); return 0;}
通過這個結果我們可以發現,按理說我們是按照1,11,9,6,5,1的順序進行插入,但是結果卻是按照大小順序進行升序排序的,并且最后插入的1還不見了,說明插入失敗了。這就印證我之前說的排序和過濾的功能。當然,有的時候我們不會想要去使用升序進行排序,我們需要降序,其實這也是可以的,只需要做一點改動就好,那就是將默認的升序(less<T>)改成降序(greater<T>)。
map
接著我們介紹一下map這個容器,通過查詢文檔我們可以發現在map中key和value是不一樣的,但是其余的部分基本都是一致的。


通過這個我們也會發現這是K/V形式,所以我們使用pair結構體傳入key'的位置。
pair的類型其實就是:
template<class K, class V>struct pair{ K first; V second;};下面也簡單介紹一下map的insert使用方法:
void Testmap(){ map<string, int> m; m.insert(make_pair("蘋果", 10)); m.insert(make_pair("香蕉", 12)); m.insert(make_pair("橘子", 13)); m.insert(make_pair("西瓜", 3)); m.insert(make_pair("芒果", 15)); m.insert(make_pair("葡萄", 5)); m.insert(make_pair("鴨梨", 16)); map<string, int>::iterator it2 = m.begin(); while (it2 != m.end()) { cout << it2->second << " "; ++it2; } cout << endl;}
通過結果我們可以看到這是按照key值進行排序的,而且我在打印的時候是打印的value值,所以結果就是它們這些水果分別出現的次數了。當然,對于map來說,上面的提到的僅僅是一部分用法,set可以讓數據有序,那么map也是可以的。但是map比較好的地方就是它是K/V模式的,我們可以在此基礎上統計同一個出現的次數,具體一點的我們以題為例。看如下代碼:
void CountNums(map<string, int>& FruitCount, string fruit[], int n){ for (size_t i = 0; i < n; i++) { //1. /* map<string, int>::iterator it = FruitCount.find(fruit[i]); if (it == FruitCount.end()) { FruitCount.insert(make_pair(fruit[i], 1)); } else { (it->second)++; } */ //2. std::pair<map<string, int>::iterator, bool> ret = FruitCount.insert(make_pair(fruit[i], 1)); if (!ret.second) { ret.first->second++; } //3. //FruitCount[fruit[i]]++; }}void SortFruit(vector<map<string, int>::iterator>& v, map<string, int>& fruitcount){ map<string, int>::iterator it = fruitcount.begin(); while (it != fruitcount.end()) { v.push_back(it); it++; } sort(v.begin(), v.end(), Greater());}下面則是測試函數:void Test(){ string fruit[] = { "蘋果", "梨", "芒果", "西瓜", "香蕉", "橘子", "蘋果", "梨", "芒果", "西瓜", "蘋果", "梨", "芒果", "蘋果", "梨", "蘋果", }; int n = sizeof(fruit) / sizeof(fruit[0]); map<string, int> FruitCount; vector<map<string, int>::iterator> v; CountNums(FruitCount, fruit, n); SortFruit(v, FruitCount); vector<map<string, int>::iterator>::iterator it = v.begin(); while (it != v.end()) { cout << (*it)->second << " "; ++it; } cout << endl; }結果顯示如下:
我們可以看到這些數據都是已經被統計好了的。
新聞熱點
疑難解答