STL——set multi_set map multi_map unordered_set unordered_map heap priority_queue(3)

最近做編程題發現關聯容器忘得多,翻翻以前寫的代碼,mark一下,勉勵自己

目錄

基本概念

map  multi_map

unordered_set  unordered_map

具體成員函數API調用代碼

priority_queue 

push_heap pop_heap sort_heap  

參考:



基本概念

map  multi_map

  • map是標準的關聯式容器,一個map是一個鍵值對序列,即(key,value)對。它提供基於key的快速檢索能力。
  • map中key值是唯一的。集合中的元素按一定的順序排列。元素插入過程是按排序規則插入,所以不能指定插入位置。
  • map的具體實現採用紅黑樹變體的平衡二叉樹的數據結構。在插入操作和刪除操作上比vector快。
  • map可以直接存取key所對應的value,支持[]操作符,如map[key]=value。
  • multimap與map的區別:map支持唯一鍵值,每個鍵只能出現一次;而multimap中相同鍵可以出現多次。multimap不支持[]操作符。

unordered_set  unordered_map

無序容器   使用hash函數和==運算
桶管理:將具有相同hash值的元素保存在同一個桶中。無序容器的性能依賴於hash函數的性質和桶的大小和數量
成員函數和map set差不多,關於有序的函數沒有,多了桶管理函數

具體成員函數API調用代碼

#include<iostream>
#include<string>
#include<vector>
#include<set>
#include<map>
#include<unordered_set>
#include<unordered_map>
#include<functional>

using namespace std;


//定義關聯容器
void countre_init()
{
	vector<int>v = { 1,2,3,4,5,6,7,8,9,8,7,6,5,4,3,2,1 };
	set<int>s(v.begin(), v.end());//不允許重複
	multiset<int>multi_s(v.begin(), v.end());
	//列表初始化
	map < string, string >m = { {"zhangsan", "wangbadan"}, { "lisi","wangjiudan" }, { "zhangsan", "wangbadan" } };
	multimap < string, string >multi_m = { { "zhangsan", "wangbadan" },{ "lisi","wangjiudan" },{ "zhangsan", "wangbadan" } };

	cout << v.size() << " " << s.size() << " " << multi_s.size() << endl;
	cout << m.size() << " " << multi_m.size() << endl;
}
//使用關鍵字類型的比較函數 自定義<
bool compare(int a, int b)
{return a < b ?  false:true;}//從大到小

//仿函數::又叫函數對象,一種行爲類似函數的對象。調用者可以向函數一樣使用該對象。
//實現:用戶只需要實現一種新的類型,在類中進行重載(),參數根據用戶索要進行的操作選擇匹配
class Greater//或struct
{
public:
	bool operator()(const string str1, const string str2)
	{
		return str1.size() < str2.size() ? true : false;
	}
};
void key_function()
{
	//set map 等有序集合 實現排序的時 默認使用<比較兩個關鍵字
	//自定義的操作類型在尖括號裏緊跟元素類型
	set<int, decltype(compare)*>s(compare);//必須指明指針類型  decltype推斷函數類型
	map<int, int,decltype(compare)*>m(compare);
	for (int i = 0; i < 10; i++)
	{
		s.insert(i);
		m.insert(make_pair(i+5, i));
	}
	for (auto c : s)
		cout << c << " ";
	cout << endl;

	auto map_it = m.begin();
	while (map_it != m.end())
	{
		cout << map_it->first << " " << map_it->second << endl;
		map_it++;
	}

	//實現倒序  謂詞  greater #include<functional>
	//set<int,less<int> >  setIntA;  //該容器是按升序方式排列元素。
	//set<int, greater<int>> setIntB;   //該容器是按降序方式排列元素。
	set<string, greater<string>>s2 = { "zhangsan","lisi","wangwu","maliu","luqi","wangba" };
	for (auto c : s2)
		cout << c << " " << endl;
	//實現倒序 仿函數
	set<string, Greater>s3 = { "zhangsan","lisi","wangwu","maliu","luqi","wangba" };
	for (auto c : s3)
		cout << c << " " << endl;
	
}

void pair_make()
{
	//pair類型 用於生成特定類型的模板,兩個public成員first second  make_pair()函數 ==  !=等操作
	//key_type (關鍵字類型)  mapped_type(值類型,只適用於map)  value_type(對於set爲鍵值類型,map爲pair類型) 
	//每個pair的關鍵字key爲const不可改變,但是value可以改變  set只有key值所以不可變
	//採用作用域訪問

 	pair<string, int>author("zhangsan", 33);
	cout << author.first << author.second << endl;
	author.second = 44;//合法 author.first = "lisi"  違法
	set<int>s = { 1,2,3 };
	set<int>::iterator it = s.begin();
	cout << *it << endl;// *it = 2;//違法  只讀
	pair<string, int>t = make_pair("zhangsan", 44);//make_pair()函數
	
	vector<pair<string, int>>v;
	vector<string>v2 = { "zhangsan","lisi","wangmazi" };
	for(int i = 0;i<10;i++)
		v.push_back(make_pair(v2[i%3], i + 30));
	for (auto c : v)
		cout << c.first << " " << c.second << endl;
}

//插入insert 刪除erase
void insert_function()
{
	vector<int>v = { 1,2,3,4,5,6,7,4,6,78,2,5 };
	set<int>s;
	s.insert(v.begin(), v.end());
	s.insert(0);
	for (auto c : s)
		cout << c << " ";
	cout << endl;
	cout<<s.erase(5)<<endl;//erase(key)刪除鍵值爲key的元素,返回刪除元素的個數,set01 multi 多個
	cout << *(s.erase(s.begin())) << endl;//刪除迭代器所指的元素,返回下一個迭代器
	s.erase(++s.begin(), --s.end());//範圍刪除,+ - 不支持
	for (auto c : s)
		cout << c << " ";
	cout << endl;
	s.insert(v.begin() + 3, v.end() - 1);

	map<string, int>m;
	m.insert({ "zhangsan",22 });//最簡單,常用花括號和make_pair()
	m.insert(make_pair("lisi", 33));
	m.insert(pair<string, int>("wangwu", 44));
	m.insert(map<string, int>::value_type("maliu", 55));
	//insert返回值w爲pair(iterator,bool)iterator指向待插入元素的位置,bool表示插入是否成功,成功則true
    //對於map 和set返回pair 對於multimap和multiset插入總是成功,返回iterator
	auto ret1 = s.insert(0);
	if (ret1.second == false)
		cout << "插入0失敗" << endl;
	auto ret2 = m.insert({ "zhangsan",22 });
	if (ret2.second == false)
		ret2.first->second += 11;
	cout << ret2.first->first << " " << ret2.first->second << endl;//ret2.first指向待插入(重複)迭代器
	//對於multi返回迭代器
	multimap<string, int>m2 = { {"zhangsan",22} };
   auto it = m2.insert({ "zhangsan", 33 });
   m2.insert({ "lisi",44 });
   cout << it->first << " " << it->second << endl;
   cout << m2.erase("lisi") << endl;//返回1個

   //map的下標操作 set 和multiset multimap不存在下表操作,不存在值或者值不唯一
   //[]先檢查有沒有,沒有則創建,有則返回value_type 與迭代器不同,迭代器解引用返回pair類型
   map<string, int>m3;//一個空map
   m3["zhangsan"] = 44;//1)首先查找"zhangsan",沒找到 2) 插入關鍵字zhangsan 值默認爲0  3)將4賦值給zhangsan 
   m3.at("zhangsan") = 55;//先查找,沒有則拋出異常out_of_ranage否則返回value_type

   //訪問元素
   cout<<*(s.find(1))<<endl;//返回一個迭代器,找不到返回s.end();
   cout << s.count(2) << endl;//返回一個數,key=2的個數
   //只有有序容器中可用
   cout << *s.lower_bound(3) << endl;//返回第一個不小於3的迭代器
   cout << *s.upper_bound(3) << endl;//返回第一個大於3的迭代器
   //multiset 和 multimap中查找,相同的key保存在相鄰的位置
   cout << endl << endl << endl;
   auto it3 = m2.find("zhangsan");
   int count = m2.count("zhangsan");
   while (count)
   {
	   cout << it3->first << " " << it3->second << endl;
	   count--;
	   it3++;
   }
   //upper_bound("zhangsan")找到則返回zhangsan下一個位置(尾後),未找到則返回一個可以插入zhangsan的位置
   //不影響序列有序,可能zhangsan最大,找到end==m2.end() 也可能沒找到  同時最大end == m2.end(),所以
   //不能根據其返回值判斷是否找到,但是返回一個範圍,可以輸出

   for (auto beg = m2.lower_bound("zhangsan"), end = m2.upper_bound("zhangsan"); beg != end; beg++)
	   cout << beg->first << " " << beg->second << endl;

   //equal_ranage找到則返回pair(iterator1,iterator2);iterator1指向第一個,iterator2指向最後一個的尾後
   //如果沒有找到則同時指向一個可以插入的位置
   for(auto pos = m2.equal_range("zhangsan"); pos.first!= pos.second; pos.first++)
	  cout << pos.first->first << " " << pos.first->second << endl;
}

//無序容器   使用hash函數和==運算
// 桶管理:將具有相同hash值的元素保存在同一個桶中。無序容器的性能依賴於hash函數的性質和桶的大小和數量
//成員函數和map set差不多,關於有序的函數沒有,多了桶管理函數

void unordered_container()
{
	unordered_map<string, int>un_m = { {"ccc",3}, {"aaa",1},{"bbb",2 } };
	un_m.insert({ "ddd",4 });
	for (auto pos: un_m)
	{
		cout << pos.first << " " << pos.second << endl;
	}
	un_m.erase("ccc");
	for (auto pos : un_m)
	{
		cout << pos.first << " " << pos.second << endl;
	}
	auto it = un_m.find("aaa");
	cout << it->first << " " << it->second << endl;
	cout << un_m.count("ddd") << endl;

	//桶管理函數:允許我們查看桶的狀態,必要時進行重組
	cout<<un_m.bucket_count()<<endl;//正在使用的桶數量
	cout << un_m.max_bucket_count()<<endl;//容器最多能容納的桶的數量
	cout << un_m.bucket_size(2) << endl;//第2個桶有幾個元素
	cout << un_m.bucket("ddd") << endl;//關鍵字爲"ddd"在哪個桶裏
	cout << un_m.load_factor() << endl;//平均每個桶有幾個元素


}


int main()
{
	
	countre_init();
	key_function();
	pair_make();
	insert_function();
	unordered_container();
	//調用函數對象,創建一個函數對象,調用它
	Greater a;
	cout<<a("zhangsan", "lisi")<<endl;
	return 0;
}

 


priority_queue:

    //使用方法 priority(Type,Conteiner,Function)
    //std::priority_queue<T, std::vector<T>, greater<T>> pq;
    //不加後面兩個參數的話默認爲 container 默認爲vector function默認爲less  大頂堆 
    //小頂堆 基本類型 priority_queue<int, vector<int>, greater<int> >q3;
    //自定義型 則重載< 
    //函數greater在<functional>

 push_heap pop_heap sort_heap

    將[begin, end)範圍進行堆排序,默認使用less<int>, 即最大元素放在第一個。
    make_heap(v.begin(), v.end());

    //將begin移動到end的前部,同時將剩下的元素堆排序爲一個新的heap
    //配合vector的pop_back進行出堆操作
    pop_heap(v.begin(), v.end());  v.pop_back();

    //剛插入的(尾部)元素做堆排序
    v.push_back(100);  push_heap(v.begin(), v.end());

   //將一個堆做排序,最終成爲一個有序的系列,可以看到sort_heap時,必須先是一個堆
    //(兩個特性:1、最大元素在第一個 2、添加或者刪除元素以對數時間),因此必須先做一次make_heap.
    sort_heap(v.begin(), v.end());

push_heap pop_heap sort_heap的基本操作:

void heap_opt()
{
	//include<algorithm> "functional"
	int myints[] = { 10,20,30,5,15 };
	vector<int> v(myints, myints + 5);
	vector<int>::iterator it;

	//將[begin, end)範圍進行堆排序,默認使用less<int>, 即最大元素放在第一個。
	make_heap(v.begin(), v.end());
	cout << "初始堆堆頂 : " << v.front() << endl;

	//將begin移動到end的前部,同時將剩下的元素堆排序爲一個新的heap
	//配合vector的pop_back進行出堆操作
	pop_heap(v.begin(), v.end()); v.pop_back();
	cout << "max heap after pop : " << v.front() << endl;

	//剛插入的(尾部)元素做堆排序
	v.push_back(100); push_heap(v.begin(), v.end());
	cout << "max heap after push: " << v.front() << endl;

	//將一個堆做排序,最終成爲一個有序的系列,可以看到sort_heap時,必須先是一個堆
	//(兩個特性:1、最大元素在第一個 2、添加或者刪除元素以對數時間),因此必須先做一次make_heap.
	sort_heap(v.begin(), v.end());

	cout << "最終堆順序:";
	for (unsigned i = 0; i<v.size(); i++) cout << " " << v[i];
	cout << endl;
}

priority_queue的基本操作:

void priority_queue_opt()
{
	//使用方法 priority(Type,Conteiner,Function)
	//std::priority_queue<T, std::vector<T>, greater<T>> pq;
	//不加後面兩個參數的話默認爲 container 默認爲vector function默認爲less  大頂堆 
	//小頂堆 基本類型 priority_queue<int, vector<int>, greater<int> >q3;
	//自定義型 則重載< 
	//函數greater在<functional>
	priority_queue<int> q1;
	//默認是最大值優先隊列 q1等價於q2
	priority_queue<int, vector<int>, less<int>>q2;
	priority_queue<int, vector<int>, greater<int> >q3;

	q2.push(1);
	q2.push(3);
	q2.push(4);
	q2.push(6);
	cout << "q2.size" << q2.size() << endl;
	while (!q2.empty())
	{
		cout << q2.top() << ' ';
		q2.pop();
	}
	cout << endl;
	q3.push(6);
	q3.push(3);
	q3.push(2);
	q3.push(1);
	while (!q3.empty())
	{
		cout << q3.top() << ' ';
		q3.pop();
	}
	cout << endl;

}

利用大頂堆小頂堆進行取中位數:

class MidNum {
public:
	void Insert(int num)
	{
		if (((min.size() + max.size()) & 1) == 0)//目前總共偶數個數字
		{
			if (max.size()>0 && num<max[0])//偶數個應該放在最小堆,但是數字比大頂堆最大值小
			{
				//vector.push_back  push_back() 數字進堆
				//調整,先進大頂堆,將大頂堆最大放入最小堆保持元素差1
				max.push_back(num);
				//將front移動到end的前部,同時將剩下的元素重新構造成(堆排序)一個新的heap
				push_heap(max.begin(), max.end(), less<int>());

				num = max[0];

				//pop_heap  vector.pop_back數字出堆
				//將[first, last)範圍進行堆排序,默認使用less<int>, 即最大元素放在第一個。
				pop_heap(max.begin(), max.end(), less<int>());
				max.pop_back();
			}
			min.push_back(num);
			push_heap(min.begin(), min.end(), greater<int>());
		}
		else
		{
			if (min.size()>0 && min[0]<num)//本來要插入大頂堆,結果num小頂堆最小值小
			{
				min.push_back(num);
				push_heap(min.begin(), min.end(), greater<int>());

				num = min[0];

				pop_heap(min.begin(), min.end(), greater<int>());
				min.pop_back();
			}
			max.push_back(num);
			push_heap(max.begin(), max.end(), less<int>());
		}
	}

main測試函數

int main()
{

	srand(time(0));
	heap_opt();
	priority_queue_opt();
	MidNum m;
	for (int i = 1; i < 10; ++i)
		m.Insert(rand() % 100);
	cout << m.GetMedian();
	return 0;
}

結果:

 

參考:

primer

C++Reference

劍指offer 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章