[2018年5月1号]C++ primer 课后练习 第十章 泛型算法 第十一章 关联容器 第十二章 动态内存

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

不取消隐式转换,可以增加程序的灵活性,但可能传入不合法的值


猜你喜欢

转载自blog.csdn.net/qq_22478401/article/details/80154074