10.38:
输入迭代器:可以读取序列中的元素,如 find, accumulate
输出迭代器:可以看作输入迭代器功能上的补集--只写而不读元素如copy和ostream_itertor
前向迭代器:可以读写元素,replace要求前向迭代器,forward_list拥有前向迭代器
双向迭代器:可以正向/方向读写序列中的元素,reverse,除了forward_list都拥有双向迭代器
随机访问迭代器:提供在常量时间内访问序列中任意元素的能力sort要求随机访问迭代器
10.39
list无法随机访问任意元素,仅仅支持++,--,所以是双向迭代器
vector是随机访问迭代器
10.40,copy要求输出迭代器,reverse要求双向迭代器,unique要求前向迭代器
10.41
将指定范围内的old_val值修改为new_val
将指定范围使pred为true的值改为new_val
将指定范围内的old_val拷贝到指定的dest位置
将指定范围内使pred为true的值改成new_val,copy到dest位置
10.42
使用list的成员函数效率更高
int main(){ list<string > listStr = {"1","12","1","13","12","132"}; listStr.sort(); listStr.unique(); for_each(listStr.cbegin(),listStr.cend(),[](const string& str){cout << str<< endl;}); for (;;); return 0; }
11.1
map 为 键值对
vector 为顺序容器
11.2
list:适合于频繁插入不需要随机查询的情况
vector:适合于需求随机查询,不用插入,只需尾部插入的情况
deque:需要首尾插入,并且需要随机查询的情况
map:适合明确的键值对的数值的存储
set:适合条件筛选的条件集合
11.3
void countMap(map<string, int > strCount, const string& str){ strCount[str]++; } int main(){ map<string, int > strCount; string tmp; while (cin >>tmp) { countMap(strCount, tmp); } for (;;); return 0; }11.4
void countMap(const set<string> setCondition, map<string, int > strCount, const string& str){ if(setCondition.find(str) != setCondition.end()){ strCount[str]++; } } int main(){ map<string, int > strCount; set<string> setCondition = {"example.","example,","Example" }; string tmp; while (cin >>tmp) { countMap(setCondition, strCount, tmp); } for (;;); return 0; }
11.5
需要用一个键来查询相应的值的时候用map
没有键值对关系的时候用set
11.6
list是有序的
set是无序的,set的元素为唯一
11.7
void insertFamilyName(map<string, vector<string> > familyName, const string& firstName, const string& lastName){ familyName[firstName].push_back(lastName); } int main(){ map<string, vector<string> > familyName; insertFamilyName(familyName, "y","xy"); for (;;); return 0; }
11.8
set的原则就是不允许存在相同的元素,而如果vector需要实现该功能,在插入元素时,需要遍历当前所有的元素,使得程序执行缓慢臃肿
11.9
void setWordLineMap(map<string, list<int > > wordLineMap, const string& word, const int& line) { wordLineMap[word].push_back(line); } int main(){ map<string, list<int > > wordLineMap; for (;;); return 0; }11.10
int main(){ map<vector<int >::iterator, int> itMap; vector<int > vec = {1,2,3,4,5,6,7,8,9}; for(vector<int >::iterator it = vec.begin(); it != vec.end(); it++){ itMap[it] = *it; } for(const auto &mapVal : itMap){ cout << mapVal.second << endl; } for (;;); return 0; }
可以,因为vector的迭代器可以进行比较,满足map的key的建立规则
而list不能运行,list迭代器没有重载<运算符,迭代器之间无法进行比较
11.11
bool compareIsBn(const int & i_0, const int & i_1){ return i_0 < i_1; } ; int main(){
//函数指针必须给*号加上括号,不然就是返回的bool指针 multiset<int , bool (*)(const int & i_0, const int & i_1) > set(compareIsBn); for (;;); return 0; }
11.12
int main(){ vector<int > vec = { 1,2,3,4,5,6,8,9 }; list<int > list = { 9,9,9,9,9,9,9,9 }; vector<pair<int,int>> pairVec; std::list<int >::iterator listIt = list.begin(); std::vector<int >::iterator vecIt = vec.begin(); for(; vecIt != vec.end()&& listIt!=list.end(); listIt++, vecIt++){ pairVec.push_back(pair<int, int>(*vecIt, *listIt)); } for(auto vecP : pairVec){ cout << vecP.first << " " << vecP.second << endl; } for (;;); return 0; }
11.13
pairVec.push_back({ *vecIt, *listIt }); pairVec.push_back(pair<int, int>( *vecIt, *listIt )); pairVec.push_back(make_pair(*vecIt, *listIt));
11.14
void insertFamilyName(map<string, vector<pair<string, string>> > familyName, const string& firstName, const string& lastName,const string& birthday){ familyName[firstName].push_back(pair<string,string>(lastName,birthday)); }
11.15:
mapped_type : vector<int>
key_type: contst int,
value_type: pair<int,vector<int>>
11.16
int main(){ std::map<int, int> m; m[1] = 1; std::map<int, int>::iterator mIt = m.begin(); mIt->second = 2; for (;;); return 0; }
11.17
都是将一个范围的元素插入到另一个容器中
只有第二个copy不能通过编译,因为back_inserter其实是通过push_back实现,但是multiset不支持push_back操作
11.18
int main(){ map<int,int > mMap; mMap[1] = 2; map<int,int>::const_iterator mapIt = mMap.cbegin(); cout << mapIt->first << endl; cout << mapIt->second << endl; for (;;); return 0; }
11.19
int main() { multiset<int, bool (*)(const int & i_0, const int & i_1) > mSet(compareIsBn); mSet.insert(1); multiset<int, bool(*)(const int & i_0, const int & i_1) >::iterator it = mSet.begin(); cout << *it << endl; for (;;); return 0; }
11.20
void countMap(const set<string> setCondition, map<string, int > strCount, const string& str){ if(setCondition.find(str) != setCondition.end()){ pair<map<string,int>::iterator, bool> it = strCount.insert(make_pair(str,1)); if(!it.second){ ++it.first->second; } } }
肯定原来的好啊,现在这么做,画蛇添足
11.21
插入一个word其计数器+1
1.22
插入类型, pair<string, vector<int>>
返回类型, pair<map<string, vector<int>>, bool>
11.23
void insertFamilyName(multimap<string, vector<pair<string, string>> > familyName, const string& firstName, const string& lastName, const string& birthday) { vector<pair<string, string>> vec; vec.push_back(make_pair(lastName, birthday)); familyName.insert(make_pair(firstName, vec)); }
11.24
插入一个pair<int,int>(0,1)
11.25
越界异常
11.26
单词计数就可以用下标简洁快速清晰的实现
11.27
需要直接操作元素切不想增加map元素数量时候用find
想直接知道数量切不操作元素时候用count
11.28
int main() { map<string, vector<int>> m; m["a"] ={1}; map<string, vector<int>>::iterator mIt = m.find("a"); cout << mIt->second[0] << endl; for (;;); return 0; }
11.29
upper_bound,lower_bound返回一个相等且可以插入的迭代器位置
equal_range返回一个pair,且pair两个元素相等,同样指向可以插入的迭代器位置
11.30
pair.first指向的是一个map迭代器,所以,pos.first->second是指向第一个查找到元素的迭代器的value值即second值
11.31
void eraseForMultimap(multimap<string,string> mMap, const string& theKey){ for(std::multimap<string, string>::iterator begin = mMap.lower_bound(theKey), end = mMap.upper_bound(theKey); begin != end; begin++ ){ mMap.erase(begin); } }
11.32
int main() { multimap<string, string> mMap; mMap.insert({ "a","b" }); mMap.insert({ "b","c" }); mMap.insert({ "a","d" }); mMap.insert({ "a","e" }); mMap.insert({ "a","g" }); mMap.insert({ "c","a" }); for(multimap<string, string>::iterator it = mMap.begin(); it != mMap.end();it++){ cout << it->first << ends; cout << it->second << endl; } for (;;); return 0; }
map是有序容器,插入时,即按字典序插入,所以只要按迭代器,直接输出即可
11.33
map<string, string> saveRule(ifstream & rule){ map<string, string> ruleMap; string key, value; while (rule >> key && getline(rule,value)) { string::iterator strIt = value.begin(); while (isspace(*strIt)) { value.erase(strIt); } ruleMap[key] = value; } return ruleMap; } void word_transform(ifstream & rule, ifstream& changeTarger){ map<string, string> ruleMap = saveRule(rule); string word; while (changeTarger >> word) { if(ruleMap.find(word) == ruleMap.end()){ cout << word << ends; }else{ cout << ruleMap[word] << ends; } } } int main() { ifstream rule("rule.txt"); ifstream word("word.txt"); word_transform(rule,word); for (;;); return 0; }
11.34
会插入一个pair<string,"">
11.35
结果无区别,程序的简洁和可读性下降
11.36
书本的程序会抛出异常
11.37
无序版本在没有顺序关系,或维护顺序关系代价很大的情况下的表现比有序版本好
有序版本可以按字典顺序输出内容
11.38
void countHashMap(const set<string> setCondition, unordered_map<string, int > strCount, const string& str) { if (setCondition.find(str) != setCondition.end()) { strCount[str] ++; } }
有序无序版本仅仅在输出上有区别,所以只要替换map成unordered_map即可实现题目需求
12.1
b1与b2都指向同一块动态内存,所以大小都为4
12.2
class StrBlob { public: typedef vector<string>::size_type size_type; StrBlob(); StrBlob(initializer_list<string> il); size_type size()const {return data->size();} bool empty() const {return data->empty();} void push_back(const string& t){data->push_back(t);} void pop_back() const; const string& front() const; const string& back()const; private: std::shared_ptr<vector<string>> data; void check(const size_type count, const string& msg) const; }; StrBlob::StrBlob() :data(make_shared<vector<string>>()) {} StrBlob::StrBlob(initializer_list<string> il) : data(make_shared<vector<string>>(il)) {} void StrBlob::check(const size_type count, const string& msg)const { if(count > data->size()){ throw out_of_range(msg); } } void StrBlob::pop_back()const { check(0, "pop back size short"); data->pop_back(); } const string& StrBlob::front()const { check(0, "front size short"); return data->front(); } const string& StrBlob::back()const { check(0, "back size short"); return data->back(); } int main() { StrBlob b1; { StrBlob b2 = {"1","2","3"}; b1 = b2; b1.push_back("4"); cout << b1.size() << endl; cout << b2.size() << endl; } for (;;); return 0; }
12.3
不需要,push_back和pop_back都需要对成员变量进行更改
12.4
size_type 是 无符号整数,永远大于等于0
12.5
不取消隐式转换,可以增加程序的灵活性,但可能传入不合法的值