本人是多年的C碼農(nóng)立美,最近才開(kāi)始玩C++匿又,所以難免會(huì)遇到C++里很平常普通的東西,在C程序員眼里已經(jīng)灰常神奇了建蹄。
舉個(gè)例子碌更,最普通的鏈表,在C里面要構(gòu)建一個(gè)鏈表躲撰,要解決的幾個(gè)問(wèn)題:
- 每個(gè)節(jié)點(diǎn)的數(shù)據(jù)結(jié)構(gòu)
- 節(jié)點(diǎn)的插入针贬、刪除問(wèn)題,以及由此產(chǎn)生的內(nèi)存問(wèn)題
- 鏈表的表頭拢蛋,表尾問(wèn)題
- 特定節(jié)點(diǎn)的查找,匹配
- 鏈表的遍歷蔫巩,排序問(wèn)題
- 等等
上面列舉的是鏈表操作的幾個(gè)基本問(wèn)題谆棱,但是在C里面要自己構(gòu)建一個(gè)好用且不出錯(cuò)的鏈表快压,并且把以上基本操作都實(shí)現(xiàn),估計(jì)也得花一番好功夫垃瞧。
C++就不一樣了蔫劣,C++提供一個(gè)STL(標(biāo)準(zhǔn)模板類)庫(kù),這個(gè)里面有個(gè)std::map模板類个从,是一個(gè)關(guān)聯(lián)式容易脉幢,簡(jiǎn)單理解為,鏈表里的每個(gè)節(jié)點(diǎn)都是一個(gè)<key, value>對(duì)嗦锐。
現(xiàn)在就來(lái)看下它是如何減輕碼農(nóng)痛苦的嫌松。
一.建一張表
看到這個(gè)問(wèn)題,C碼農(nóng)是不是馬上就要想奕污,哎呀萎羔,那我要:
- 先設(shè)計(jì)一個(gè)數(shù)據(jù)節(jié)點(diǎn),并設(shè)計(jì)成鏈表節(jié)點(diǎn)碳默;
- 然后再不斷的malloc新節(jié)點(diǎn)贾陷;
- 再依次把這些節(jié)點(diǎn)串接起來(lái),形成一張表嘱根。
把上面這幾點(diǎn)用code實(shí)現(xiàn)并調(diào)通髓废,那就是個(gè)合格的C程序員。
但是我們來(lái)看看用STL提供的模板類有多么方便该抒。
直接上代碼:
sample 1
#include<map>
#include<string>
#include<iostream>
using namespace std;
int main()
{
// 聲明一張表
map<string,int> myMap;
// 依次給這張表添加元素
myMap["a"]=1;
myMap["b"]=2;
myMap["c"]=3;
// 遍歷剛剛建的表
map<string,int>::iterator it;
for(it=myMap.begin(); it!=myMap.end(); ++it)
cout<<"key: "<<it->first <<" value: "<<it->second<<endl;
return 0;
}
這段code輸出為:
key: a value: 1
key: b value: 2
key: c value: 3
哇瓦哎,是不是有點(diǎn)神奇了,建一張表柔逼,以及遍歷這張表蒋譬,這么簡(jiǎn)單!
怎么看起來(lái)像C的數(shù)組愉适?
其實(shí)不是犯助,其實(shí)是這個(gè)模板類重載了操作符[ ], 讓你看起來(lái)覺(jué)得像數(shù)組而已维咸;
這個(gè)有點(diǎn)點(diǎn)誤導(dǎo)剂买,我覺(jué)得比較純正的還是insert方法,再看下一段code:
sample 2
#include<map>
#include<string>
#include<iostream>
using namespace std;
int main()
{
map<string,int> myMap; // 聲明一張表
// 依次給這張表添加元素
myMap.insert(pair<string, int>("a", 1));
myMap.insert(pair<string, int>("b", 2));
myMap.insert(pair<string, int>("c", 3));
// 遍歷剛剛建的表
map<string,int>::iterator it;
for(it=myMap.begin(); it!=myMap.end(); ++it)
cout<<"key: "<<it->first <<" value: "<<it->second<<endl;
return 0;
}
這次看起來(lái)有點(diǎn)正兒八經(jīng)的鏈表插入的感覺(jué)了吧:)
用上C++提供的標(biāo)準(zhǔn)模板庫(kù)癌蓖,有不有點(diǎn)從石器時(shí)代跨入青銅時(shí)代的感覺(jué)~~~
二. 刪除節(jié)點(diǎn)
既然有增加節(jié)點(diǎn)瞬哼,那么對(duì)應(yīng)地,就有刪除節(jié)點(diǎn)租副。
我們先回顧一下C怎么考慮這個(gè)問(wèn)題的:
- 在鏈表中找到特定的節(jié)點(diǎn)坐慰。
- 把這個(gè)節(jié)點(diǎn)從鏈表中斷開(kāi),把這個(gè)節(jié)點(diǎn)的相鄰節(jié)點(diǎn)鏈上用僧。
- free掉這個(gè)節(jié)點(diǎn)结胀。
裹筋吧赞咙,我們看看std:map是怎么讓人happy的。
看代碼:
sample 3
#include<map>
#include<string>
#include<iostream>
using namespace std;
int main()
{
map<string,int> myMap; // 聲明一張表
// 依次給這張表添加元素
myMap.insert(pair<string, int>("a", 1));
myMap.insert(pair<string, int>("b", 2));
myMap.insert(pair<string, int>("c", 3));
// 遍歷剛剛建的表
map<string,int>::iterator it;
for(it=myMap.begin(); it!=myMap.end(); ++it)
cout<<"key: "<<it->first <<" value: "<<it->second<<endl;
cout << endl;
// 刪掉一個(gè)節(jié)點(diǎn)
myMap.erase("b");
map<string,int>::iterator iter;
for(iter=myMap.begin(); iter!=myMap.end(); ++iter)
cout<<"key: "<<iter->first <<" value: "<<iter->second<<endl;
return 0;
}
刪除特定節(jié)點(diǎn)糟港?free廢節(jié)點(diǎn)攀操?自動(dòng)就幫你做了!
三. 清空map
清空操作為什么單獨(dú)拿出來(lái)說(shuō)一下秸抚,是因?yàn)槲业谝淮问褂靡卜噶隋e(cuò)誤速和,因?yàn)樽钊菀紫氲降姆椒ň褪牵罕闅v這個(gè)表,one by one地刪除每一個(gè)節(jié)點(diǎn)剥汤。
請(qǐng)看錯(cuò)誤代碼:
map<string,int>::iterator iter;
for(iter=myMap.begin(); iter!=myMap.end(); ++iter) {
myMap.erase(iter);
}
這其實(shí)是錯(cuò)誤的寫(xiě)法颠放,因?yàn)閑rase會(huì)釋放掉iter,然后執(zhí)行++iter秀姐,程序就回跑飛慈迈。
所以這里附上一個(gè)推薦的寫(xiě)法:
map<string,int>::iterator iter;
for(iter=myMap.begin(); iter!=myMap.end(); ) {
// erase() 返回的是下一個(gè)元素的迭代器
iter = myMap.erase(iter);
}
或者再簡(jiǎn)單一點(diǎn):
myMap.clear();
世界清凈了~ 讓我歇會(huì)兒,喝口茶省有。
四. 幾個(gè)經(jīng)常用的方法
Item | Description |
---|---|
begin() | 返回指向map頭部的迭代器 |
clear() | 刪除所有元素 |
empty() | 判斷map是否為空 |
end() | 返回指向map末尾的迭代器 |
erase() | 刪除一個(gè)元素 |
find() | 查找一個(gè)元素 |
insert() | 插入元素 |
size() | 返回map中元素的個(gè)數(shù) |
還有其他的就不一一列舉了痒留,還有就是要注意這些方法的重載版本,用的時(shí)候可以特別研究一下蠢沿。