《C++primer》v5 第9章 顺序容器 读书笔记 习题答案

9.1

(a)list。可以快速插入。

(b)deque。支持尾部快速插入和头部快速删除。

(c)vector或者deque。

9.2

list<deque<int> > l;

9.3

它的范围是该容器的第一个元素和尾元素之后。区间左闭右开。

9.4

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<list>
#include<deque>
#include<vector>
using namespace std;
bool find(pair<vector<int>::iterator,vector<int>::iterator> p,int val)
{
    for(auto it=p.first;it!=p.second;++it)
    {
        if(*it==val)
            return true;
    }
    return false;
}
int main()
{
    vector<int> vec{1,3,19,2,0,5};
    cout<<find(make_pair(vec.begin(),vec.end()),19);
    return 0;
}

9.5

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<list>
#include<deque>
#include<vector>
using namespace std;
vector<int>::iterator find(pair<vector<int>::iterator,vector<int>::iterator> p,int val)
{
    for(auto it=p.first;it!=p.second;++it)
    {
        if(*it==val)
            return it;
    }
    return p.second;
}
int main()
{
    vector<int> vec{1,3,19,2,0,5};
    auto it=find(make_pair(vec.begin(),vec.end()),19);
    if(it==vec.end()) cout<<"No find!"<<endl;
    else cout<<"find "<<*it<<endl;
    return 0;
}

9.6

list的迭代器没有重载<,因此会编译错误。应该将<换为!=。

9.7

整型?

9.8

string?value_type?

9.9

begin对于普通对象将返回只一个指向普通对象的迭代器,对于常量对象将返回一个指向常量对象的迭代器。

cbegin将返回一个指向常量对象的迭代器。

9.10

it1、it2:vector<int>::iterator

it3、it4:vector<int>::const_iterator

9.11

    vector<int> a;
    vector<int> b{5,4,3,2,1};
    vector<int> c={1,2,3,4,5,6};
    vector<int> d(b);
    vector<int> e=c;
    vector<int> f(c.begin(),c.end());

9.12

创建一个容器为另一个容器的拷贝,两个容器的类型及其元素类型必须匹配。

当传递迭代器参数来拷贝一个范围时,不要求容器类型必须是相同的,而且新容器和原容器中的元素类型也可以不同,只要能将要拷贝的元素转换为要初始化的容器的元素类型即可。

9.13

通过传递迭代器来创建容器。

    list<int> l {3,4,6,7};
    vector<double> vec(l.begin(),l.end());

    vector<int> vec2{1,2,3,4};
    vector<double> vec3(vec2.begin(),vec2.end());

9.14

using namespace std;
int main()
{
    list<char*> l{"abcde","xyz","qq"};
    vector<string> vec(l.begin(),l.end());
    for(auto i:vec)
        cout<<i<<endl;
    return 0;
}

9.15

int main()
{
    vector<int> a{1,2,3},b{1,2,3};
    if(a==b) cout<<"Yes!"<<endl;
    else cout<<"No!"<<endl;
    return 0;
}

9.16

using namespace std;
int compare(const list<int> &lhs,const vector<int> &rhs)
{
    auto it=lhs.begin();
    auto jt=rhs.begin();
    while(it!=lhs.end()&&jt!=rhs.end())
    {
        if(*it<*jt) return -1;
        else if(*it>*jt) return 1;
        it++;
        jt++;
    }
    if(it==lhs.end()&&jt==rhs.end())
        return 0;
    else if(it==lhs.end())
        return -1;
    else if(jt==rhs.end())
        return 1;
}
int main()
{
    list<int>a {1,3};
    vector<int> b {1,2,3};
    cout<<compare(a,b)<<endl;
    return 0;
}

9.17

必须重载了关于c1和c2的<运算符。

9.18

int main()
{
    string s;
    deque<string> dq;
    while(cin>>s)
        dq.push_back(s);
    for(auto i:dq)
        cout<<i<<endl;
    return 0;
}

9.19

int main()
{
    string s;
    list<string> l;
    while(cin>>s)
        l.push_back(s);
    for(auto i:l)
        cout<<i<<endl;
    return 0;
}

9.20

int main()
{
    list<int> l{123,1,2,3,5,12,4,6};
    deque<int> a,b;
    for(list<int>::iterator it=l.begin();it!=l.end();++it)
    {
        if(*it%2==0)
            b.push_back(*it);
        else
            a.push_back(*it);
    }
    return 0;
}

9.21

int main()
{
    vector<int> vec;
    vector<int>::iterator it=vec.begin();
    int a;
    while(cin>>a)
        it=vec.insert(it,a);
    for(auto i:vec)
        cout<<i<<endl;
    return 0;
}

理解的关键在于insert返回一个指向插入位置的迭代器。开始的时候需要插入到vec.begin()前面的位置,插入之后就返回这个位置的迭代器。下次插入的时候传入这个迭代器,会在它前面插入,再返回插入的位置。如此,即与push_front()相同。

9.22

insert操作使迭代器失效。

9.23

应该都是c[0]

int main()
{
    vector<int> c{8};
    if(!c.empty())
    {
        auto val=*c.begin(),val2=c.front();
        auto last=c.end();
        auto val3=*(--last);
        auto val4=c.back();
        cout<<val<<" "<<val2<<" "<<val3<<" "<<val4<<endl;
    }
    return 0;
}

9.24

int main()
{
    vector<int> c;
    c.at(0);//抛出异常
    c[0];
    c.front();
    *c.begin();
    return 0;
}

只有使用at会抛出异常

9.25

如果相等则删除视为无效

9.26

int main()
{
    int ia[]= {0,1,1,2,3,5,8,13,21,55,89};
    list<int> l(begin(ia),end(ia));
    auto it=l.begin();
    while(it!=l.end())
        if(*it%2)
            it=l.erase(it);
        else
            ++it;
    for(auto it:l)
        cout<<it<<endl;
    cout<<"========="<<endl;
    vector<int> vec(begin(ia),end(ia));
    auto jt=vec.begin();
    while(jt!=vec.end())
        if(*jt%2==0)
            jt=vec.erase(jt);
        else
            ++jt;
    for(auto it:vec)
        cout<<it<<endl;
    return 0;
}

9.27

forward_list是单向列表因此有与其他容器不同的操作,尤其在删除方面。

它的删除是erase_after是删除给定迭代器后面的一个迭代器,返回删除位置后的一个迭代器。

before_begin()返回一个begin()前面的迭代器。

#include<forward_list>
using namespace std;
int main()
{
    int ia[]= {0,1,1,2,3,5,8,13,21,55,89};
    forward_list<int> l(begin(ia),end(ia));
    auto pre=l.before_begin();
    auto cur=l.begin();
    while(cur!=l.end())
    {
        if(*cur%2)
            cur=l.erase_after(pre);
        else
        {
            pre=cur;
            ++cur;
        }
    }
    for(auto i:l)
        cout<<i<<endl;
    return 0;
}

9.28

#include<forward_list>
using namespace std;
void solve(forward_list<string> &l,const string &a,const string &b)
{
    auto pre=l.before_begin();
    auto cur=l.begin();
    while(cur!=l.end())
    {
        if(*cur==a)
        {
            l.insert_after(cur,b);
            return ;
        }
        else
        {
            pre=cur;
            ++cur;
        }
    }
    l.insert_after(pre,b);
}
int main()
{
    string a="xxx",b="qq";
    forward_list<string> l{"sdfs","xx","abc"};
    solve(l,a,b);
    for(auto i:l)
        cout<<i<<endl;
    return 0;
}

9.29

vec.resize(100)会将vec增大到100,多出75个位置将置0。

vec.resize(10)将把vec缩小至10。

9.30

如果是类类型,则必须提供一个默认构造函数。

9.31

list或forward_list的迭代器不支持+运算。

#include<list>
using namespace std;
int main()
{
    list<int> l {1,2,3,5,8,9,12};
    auto it=l.begin();
    while(it!=l.end())
    {
        if(*it%2==0)
        {
            it=l.erase(it);
        }
        else
        {
            it=l.insert(it,*it);
            it++;
            it++;
        }
    }
    for(auto i:l)
        cout<<i<<endl;
    return 0;
}

insert_after\erase_after返回一个插入位置的迭代器或删除位置后的一个位置的迭代器。

#include<forward_list>
#include<list>
using namespace std;
int main()
{
    forward_list<int> l {1,2,3,5,8,9,12};
    auto pre=l.before_begin();
    auto cur=l.begin();
    while(cur!=l.end())
    {
        if(*cur%2==0)
        {
            cur=l.erase_after(pre);
        }
        else
        {
            cur=l.insert_after(cur,*cur);
            pre=cur;
            ++cur;
        }
    }
    for(auto i:l)
        cout<<i<<endl;
    return 0;
}

9.32

不合法。

后面iter++是无意义的。该insert最终返回一个在iter位置前的迭代器。

9.33

如果不将insert的结果赋给begin将导致迭代器失效!

9.34

感觉此代码有错。对于奇数情况将导致死循环。

将奇数翻倍。

using namespace std;
int main()
{
    vector<int> l {1,2,3,5,8,9,12};
    auto begin=l.begin();
    while(begin!=l.end())
    {
        if(*begin%2)
        {
             begin=l.insert(begin,*begin);
             ++begin;
        }
        ++begin;
    }
    for(auto i:l)
        cout<<i<<endl;
    return 0;
}

9.35

capacity是当前vector可容纳的最大元素数量

size是当前vector已经容纳的元素数量

9.36

不可能

9.37

list不支持随机访问因此内存不是连续储存的?

9.38

如果新加入元素后元素数量大于最大容量,将把最大容量扩大1倍。

9.39

向svec中添加元素。最后把svec大小变为原来的3/2。

9.40

9.41

int main()
{
    vector<char> vec{‘a‘,‘b‘,‘c‘,‘d‘};
    string s(vec.begin(),vec.end());
    cout<<s<<endl;
    return 0;
}

9.42

int main()
{
    vector<char> vec;
    char a;
    while(cin>>a)
        vec.push_back(a);
    string s(vec.begin(),vec.end());
    cout<<s<<endl;
    return 0;
}

9.43、9.44、9.45、9.46    

insert似乎是无返回值类型的。

这几个题暂略。。

时间: 2024-10-04 15:50:12

《C++primer》v5 第9章 顺序容器 读书笔记 习题答案的相关文章

《C++primer》v5 第11章 关联容器 读书笔记 习题答案

11.1 map是关联容器,vector是顺序容器 11.2 略 11.3 int main() { map<string,int> word; string s; while(cin>>s) word[s]++; for(auto i:word) cout<<i.first<<" "<<i.second<<endl; return 0; } 11.4 void convers(string &s) { s

《C++primer》v5 第2章 C++基础 读书笔记 习题答案

2.1 int,long long ,short 可表示范围和占用内存空间不同.具体与计算机有关. 无符号类型只能表示0和正数,带符号类型可以表示负数,0,正数. float是单精度,一般占用4个字节,double是双精度,一般占用8个字节,它们可表示的数据范围也不相同. 2.2 利率用double,本金和付款用int 2.3 unsigned u=10,u2=42; cout<<u2-u<<endl; cout<<u-u2<<endl; int i=10,

《C++primer》v5 第12章 动态内存 读书笔记 习题答案

这一章暂时没写完,先留着以后再写. 在C++程序中,程序员可以给手动开辟内存,但是这块内存需要手动释放,不便管理,因此新标准提供智能指针类型来管理动态对象.它负责自动释放所指向的对象. shared_prt允许多个指针指向同一个对象 unique_ptr独占所指向的对象 weak_ptr是一个弱引用,指向shared_ptr所管理的对象 一些操作: p=q;//递减p的引用计数,递增q的引用计数 shared_ptr<T> p(q);//p是q的拷贝,递增q的引用计数 通过make_share

《C++primer》v5 第10章 泛型算法 读书笔记 习题答案

10.1 using namespace std; int main() { vector<int> vec; int a; cin>>a; int v; while(cin>>v) vec.push_back(v); cout<<a<<" : "<<count(vec.begin(),vec.end(),a)<<endl; return 0; } 10.2 using namespace std; i

《C++primer》v5 第8章 IO库 读书笔记 习题答案

8.1.8.2 这一章不咋会啊.. istream &read(istream &is) { int a; auto old_state=is.rdstate(); is.clear(); is>>a; is.setstate(old_state); return is; } int main() { read(cin); return 0; } 8.3 读到eof或错误类型的时候 8.4 #include<fstream> using namespace std;

《C++primer》v5 第1章 开始 读书笔记 习题答案

从今天开始在博客里写C++primer的文字.主要以后面的习题作业为主,会有必要的知识点补充. 本人也是菜鸟,可能有不对之处,还望指出. 前期内容可能会比较水. 1.1略 1.2略 1.3 cin和cout分别是istream和ostream的对象. #include<iostream> using namespace std; int main() { cout<<"Hello,world"<<endl; return 0; } 1.4 #incl

《C++primer》v5 第5章 语句 读书笔记 习题答案

5.1 空语句只有一个";".如果什么也不想做可以使用空语句. 5.2 用花括号{}括起来的叫块,也叫复合语句.有多条语句作用在同一个作用域时,需要用花括号括起来. 5.3 降低了. 5.4 (a)每次迭代时候会初始化iter,但是iter缺少初值,所以这段代码根本不会通过编译.另外这里的括号需要一个bool类型的,而定义迭代器根本不会返回一个bool类型.假如上面那些问题都可以通过,每次迭代都会初始化这个iter,会导致死循环. (b)我试了一下编译未通过是因为没找到适合的find函

《C++primer》v5 第3章 字符串、向量和数组 读书笔记 习题答案

3.1略 3.2 string str; //读行 while(getline(cin,str)) cout<<str<<endl; //读单个词 while(cin>>str) cout<<str<<endl; 3.3 输入运算符读到空白符结束 getline读到换行符结束,并丢弃换行符 3.4 比较大小. 比较大小是比较的第一个不相同的字符的大小. int main() { string a,b; cin>>a>>b;

《C++primer》v5 第4章 表达式 读书笔记 习题答案

4.1 105 4.2 *vec.begin()=*(vec.begin())//先调用点运算符,再解引用 *vec.begin()+1=(*vec.begin())+1//先解引用,再加一 4.3略? 4.4 (12/3*4)+(5*15)+(24%4/2)=91 4.5 (a)-86(b)-16 (c)0 (d)0 4.6 n%2 4.7 溢出:计算结果超出该数据类型所能表示的范围 2147483647+1 1U-2 ... 4.8 比较低.. 4.9 首先判断cp是否为空指针,若非空指针则