STL中的關聯式容器解析
" 其實真正能擊垮你的,
往往不是那些突如其來的滅頂之災,
而是壓在你心底
那些看似不值一提,日積月累的心事,
在某一瞬間,使你徹底崩潰,成為壓垮你的最後一根稻草。"
這幾天,突然一下子想明白了
隨波逐流不是我的風格,我需要堅持一些東西,需要做一些不一樣的東西,即使是在無限的誘惑裡~
很難,真的很難,
加油!
正題:記錄STL中的map 和set用法!
map
map和set一樣是關聯式容器,它們的底層容器都是紅黑樹,區別就在於map的值不作為鍵,鍵和值是分開的。它的特性如下:
- map以RBTree作為底層容器
- 所有元素都是鍵+值存在
- 不允許鍵重複
- 所有元素是通過鍵進行自動排序的
- map的鍵是不能修改的,但是其鍵對應的值是可以修改的
map<key, value> m;
set
set是一種關聯式容器,其特性如下:
- set以RBTree作為底層容器
- 所得元素的只有key沒有value,value就是key
- 不允許出現鍵值重複
- 所有的元素都會被自動排序
- 不能通過迭代器來改變set的值,因為set的值就是鍵
set<int> s;
∴:map和set的共同點在於:都是有序的無重複的key值,而且底層都是基於R-B Tree。
說明:pair是一個結構體型別,裡面的兩個成員變數的型別可以通過模板給定;換句話說,pair是一種K-V資料型別,可以定義此型別的變數
例:map<string,int> m;
pair<string,int> v(string("zhangheng",2));
m.insert(v);
//構造一個int型別的set
set<int> s;
//插入幾個元素
s.insert(1);
s.insert(2);
s.insert(6);
//測試insert()的返回值
pair<set<int>::iterator, bool> ret;
ret = s.insert(4);//set中還沒有4這個元素,插入成功,返回插入節點的迭代器和TRUE
ret = s.insert(4);//set中已經存在了4,插入失敗,返回的是元素4的迭代器和FALSE
常用的容器操作:插入、刪除、儲存、遍歷、查詢、排序
C++中的STL之所以牛B,是因為STL封裝了許多複雜的資料結構和演算法,以及大量常用的資料結構操作。vector封裝了資料,list封裝了連結串列,map和set封裝了二叉樹。
接下來,分別舉例來研究map和set的用法:
●map的操作
map<string, int> m;
m["messi"] = 1;
m["jams"] = 2;
m["jack"] = 3;
//插入操作
pair<string, int> value("json", 4);
m.insert(value);
//輸出集合中的元素(遍歷map中的元素)
for(map<string, int>::iterator iter = m.begin(); iter != m.end(); iter ++){
cout<<"key : "<<iter->first<<endl;
cout<<"value : "<<iter->second<<endl;
}
// 修改資料的兩種方式:
// 方式1:
m[2] = "Ma";
// 方式2:
m->second = "Yuan";
print(mapStu1);
//刪除操作
//1,刪除指定的鍵值
m.erase("jams");
//2,刪除迭代器指向的元素
m.erase(m.begin());
it = m.find(2);
m.erase(it);
//3,刪除指定區間的元素
m.erase(m.begin(), m.end())
//查詢元素
//給定一個鍵值,如果查詢成功函式返回指向這個元素的迭代器,否則返回end()
map<string, int>::iterator iter = myMap.find("messi");
if(iter != myMap.end()){
cout<<"key : "<<iter->first<<endl;
cout<<"value : "<<iter->second<<endl;
}
●set的操作
例:把只包含質因子2、3和5的數稱作醜數(Ugly Number)。 比如6、8都是醜數,但14不是,因為它包含質因子7。把1當做是第一個醜數。求按從小到大的順序的第N個醜數。
/*
題目:把只包含質因子2、3和5的數稱作醜數(Ugly Number)。
例如6、8都是醜數,但14不是,因為它包含質因子7。把1當做是第一個醜數。求按從小到大的順序的第N個醜數。
所以:從1開始的10個醜數分別為1,2,3,4,5,6,8,9,10,12。
你可能疑惑:8的因子有1、2、4、8;那怎麼能是醜數呢?是因為只是要求一個數的質數因子只能是2,3,5
時間:2018年x月x日 08:08:08
思路:一:暴力(遍歷)
1)設定一個計數器用來統計出現的醜數的個數
2)從1開始遍歷每個整數,推斷是否是醜數,假設是醜數則計數器加1。否則遍歷下一個整數。
注意,怎麼判斷一個數是不是醜數,迴圈除以2直到不能整除,接著迴圈除以3再到不能整除,再迴圈除以5,若還是不能整除,則不是醜數。
例:醜數12 12/2 = 6;6/2 = 3;3/2 不能整除;3/3 = 1; 結束,12是醜數;非醜數26 26/2 = 13;13/2 不能整除;13/3 不能整除;13/5 不能整除;結束,26不是整數
3)當計數器的值=N時,停止遍歷。輸出醜數。
二:想辦法從上一個醜數判斷出下一個醜數,而不須要從1開始遍歷再判斷。
即:所有的醜數都是由前面醜數乘上2,或3,或5得到的。
1)先求出醜數i之前的所有醜數與2,3,5的乘積,找出大於i的最小值作為新產生的醜數。
*/
#include <bits/stdc++.h>
using namespace std;
/*
//法一:暴力
class Solution {
public:
void GetUglyNumber_Solution(int index) {
//找到第index個醜數
int i,count =0;
if (index < 1)
{
cout << "error input " << endl;
exit(0);
}
for (i=1;i< INT_MAX && count< index;i++)
{
if ( IsUgly(i) )
{
count++ ;
//cout << i << " " ;
}
}
cout << i-1 << endl;
}
//遍歷法找醜數
bool IsUgly(int num)//判斷是否是
{
while (num %2 == 0)
{
num /= 2;
}
while (num %3 == 0)
{
num /= 3;
}
while (num %5 == 0)
{
num /= 5;
}
if (num == 1)
return true;
else
return false;//not an ugly number
}
};
*/
//法二:建議此種方法,所有的醜數都是有現有醜數乘以2,3,5得到的
class Solution {
public:
int GetUglyNumber_Solution(int index) {
if (index <= 0)
{
return 0;
}
vector<int> v(index);
v[0]=1;
vector<int>::iterator it2=v.begin();
vector<int>::iterator it3=v.begin();
vector<int>::iterator it5=v.begin();
int count=1;
while(count<index)
{
int m=min(*it2 * 2,min(*it3 * 3,*it5 * 5));
v[count]=m;
//下邊就是更新2,3,5的指標
if (*it2 * 2 <= m)//小於等於當前最大的醜數,則要更新
{ //因為在這個指標之前的數乘以2都比當前的最大丑數小,
it2++;
}
if (*it3 * 3 <= m)
{
it3++;
}
if (*it5 * 5 <= m)
{
it5++;
}
count++;
}
int ugly = v[count - 1];
return ugly;
}
};
/*
//法三:此種方法花費時間太長,MAX只能設定較小的數才可以,適用於求Number較小的情況。不建議使用,但是它用set的思想值得學習。
class Solution {
public:
void GetUglyNumber_Solution(int Index)
{
const int MAX = 100000;//const int MAX = INT_MAX/5;
int i,j;
set<int> s;
set<int>::iterator it;
s.insert(1);
for (i=1 ; i<MAX ; i++)
{
if (s.find(i) != s.end() )
{
s.insert(2*i) ;
s.insert(3*i) ;
s.insert(5*i) ;
}
}
for (it = s.begin(),j=0;it!= s.end()&&j<Index-1;it++,j++)
cout << *it << " ";
cout<< endl<< *it << endl;
}
};
*/
int main()
{
int Number;
cout << "Input a number : " ;
cin >> Number ;
Solution so;
int result=so.GetUglyNumber_Solution(Number);
cout<<result<<endl;
return 0;
}
好嘞!