C++ Primer 第九章答案

习题9.1
(a)使用list要好一些,由于它需要插入容器,list的底层是双向链表。
         在任何位置插入数据都很方便,且支持双向访问。
(b)使用deque,deque是双端队列,支持随机访问,在首尾添加或删除原元素很快。
(c)使用lvector,不需要插入和删除,只需要排序的话,在随机访问
         方面毫无疑问的选择vector。

总结:
常用的容器三种
vector:底层是可变大小数组,特点是随机访问速度快。
list:底层是双向链表,特点是插入和删除元素速度快。
deque:底层是双端队列,特点是随机访问速度快,且在首尾添加删除元素快速。

原则
(1)容器首选vector,数组连续,空间开销小
(2)涉及随机插入删除,选择list,链表方便,但是空间上不连续,导致额外空间开销大,酌情考虑。
(3)deque,中和前两个特点,如果需要随机访问,但元素的删除和插入只在两端,使用deque。

习题9.2
list > listTest;

习题9.3
他们指向同一个容器中的元素,或者是容器最后一个元素之后的位置
begin可以通过递增来到达end。

习题9.4
#include
#include

using namespace std;

bool vecFindValue(vector::iterator beg, vector::iterator end, int i)
{
    for (auto it = beg; it != end; it++)
    {
        if (*it == i)
        {
            return true;
        }
    }
    return false;
}

int main(int argc, char** argv)
{
    vector vec = { 0,1,2,3,4 };
    bool consult = vecFindValue(vec.begin(), vec.end(), 3);
    cout << consult << endl;
        
    system("pause");
    return 0;
}
习题9.5
#include
#include

using namespace std;
vector::iterator vecFindValue(vector::iterator beg, vector::iterator end, int i)
{
    for (auto it = beg; it != end; it++)
    {
        if (*it == i)
        {
            return it;
        }
    }
    return end;
}

int main(int argc, char** argv)
{
    vector vec = { 0,1,2,3,4 };
    auto consult = vecFindValue(vec.begin(), vec.end(), 8);
    if(consult != vec.end())
        cout << *consult << endl;
    else
        cout << "Can't find the value" << endl;
        
    system("pause");
    return 0;
}

习题9.6
iterator没有比较这种操作,修改为while(iter1 != iter2)

习题9.7
vector::iterator

习题9.8
写:list::iterator
读:list::const_iterator

习题9.9
cbegin返回const_iterator,begin返回iterator

习题9.10
it1是vector::iterator,其余是vector::const_iterator

习题9.11
vector vec;    // 0
vector vec(10);    // 0
vector vec(10,1);  // 1
vector vec = {1,2,3,4,5}; // 1,2,3,4,5
vector vec(other_vec); // same as other_vec
vector vec(other_vec.begin(), other_vec.end()); // same as other_vec

习题9.12
接收另一个容器拷贝,是将其全部元素复制到本容器中来。
二使用迭代器,是将begin和end之间的元素复制进来。

习题9.13
#include
#include
#include
using namespace std;

int main(int argc, char** argv)
{
    list ilst(5, 4);
    vector ivc(5, 5);

    //! from list to vector
    vector dvc(ilst.begin(), ilst.end());
    for (auto i : ilst) cout << i;
    cout << endl;
    for (auto t : dvc) cout << t;
    cout << endl;

    //! from vector to vector
    vector dvc2(ivc.begin(), ivc.end());
    for (auto i : ivc) cout << i;
    cout << endl;
    for (auto t : dvc2) cout << t;

    system("pause");
    return 0;
}

习题9.14
#include
#include
#include
#include
using namespace std;

int main(int argc, char** argv)
{
    list ilst(5,"beutiful");

    //! from list to vector
    vector vec(ilst.begin(), ilst.end());
    for (auto i : vec) cout << i << endl;

    system("pause");
    return 0;
}

习题9.15
#include
#include
#include
#include
using namespace std;

int main(int argc, char** argv)
{
    vector vec_1(5, 1);
    vector vec_2(5, 1);
    if (vec_1 == vec_2)
    {
        cout << "vec_1 is same as vec_2" << endl;
    }
    else
    {
        cout << "not" << endl;
    }

    system("pause");
    return 0;
}

习题9.16
#include
#include
#include
#include
using namespace std;

int main(int argc, char** argv)
{
    vector vec(5, 1);
    list lis(5, 1);
    vector vec_2(lis.begin(),lis.end());
    if (vec == vec_2)
    {
        cout << "true" << endl;
    }
    else
    {
        cout << "false" << endl;
    }

    system("pause");
    return 0;
}

习题9.17
两个容器得相同类型,且支持该比较操作符。

习题9.18
#include
#include
#include
#include
#include
using namespace std;

int main(int argc, char** argv)
{
    string buf;
    deque deq;
    while (cin >> buf)
    { 
        deq.push_back(buf);
    }
    for (auto i : deq)
    {
        cout << i << endl;
    }

    system("pause");
    return 0;
}

习题9.19
#include
#include
#include
#include
#include
using namespace std;

int main(int argc, char** argv)
{
    string buf;
    list lis;
    while (cin >> buf)
    { 
        lis.push_back(buf);
    }
    for (const auto i : lis)
    {
        cout << i << endl;
    }

    system("pause");
    return 0;
}

习题9.20
#include
#include
#include
#include
#include
using namespace std;

int main(int argc, char** argv)
{
    string buf;
    list lis = {0,1,2,3,4,5,6};
    deque sinDeq;
    deque douDeq;
    for (auto i : lis)
    {
        if (i % 2)
            sinDeq.push_back(i);
        else
            douDeq.push_back(i);
    }
    for (auto i : sinDeq)
    {
        cout << i;
    }
    cout << endl;
    for (auto i : douDeq)
    {
        cout << i;
    }


    system("pause");
    return 0;
}

练习9.21
是相同的,插入一个元素到原begin的前面,然后返回新插入元素的
iterator,将它赋值给iter,它与插入后的begin相同。然后重复此操作,
可以一直在首位插入值。

练习9.22
1、循环不会终止。
2、在insert之后mid不再是最中间的位置,迭代器失效。

练习9.23
都是相同的值

练习9.24
    std::cout << v.at(0); 
    std::cout << v[0];     
    std::cout << v.front();  
    std::cout << *(v.begin()); 

练习9.25
elems相等删除他们指定的元素;
不相等,删除他们范围内的元素;
如果都是end,不删除任何元素。
第二个迭代器指向元素位置一定在第一个迭代器后面。

练习9.26
解释下两点
删除元素后,其本身的end()返回的迭代器永远不失效,不必担心。
删除元素后,后面的元素后替补该位置,因此如果删除后,继续判断
该位置的元素(此元素是后面元素补上来的)。如果不符合,再后移判断。
直接后移会出现漏判的情况。
#include
#include
#include
#include
#include
using namespace std;

int main(int argc, char** argv)
{
    int ia[] = { 0, 1, 1, 2, 3, 5, 8, 13, 21, 55, 89 };

    //! init
    vector vec(ia, end(ia));
    list lst(vec.begin(), vec.end());

    //! remove odd value
    for (auto it = lst.begin(); it != lst.end();)
        if (*it & 0x1)
            it = lst.erase(it);
        else
            ++it;

    //! remove even value
    for (auto it = vec.begin(); it != vec.end();)
        if (!(*it & 0x1))
            it = vec.erase(it);
        else
            ++it;

    //! print
    cout << "list : ";
    for (auto i : lst) cout << i << " ";
    cout << "\nvector : ";
    for (auto i : vec) cout << i << " ";
    cout << std::endl;

    system("pause");
    return 0;
}

练习9.27
#include
#include
#include
#include
#include
#include
using namespace std;

int main(int argc, char** argv)
{
    forward_list flst = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

    for (auto prev = flst.before_begin(), curr = flst.begin();
    curr != flst.end();)
        if (*curr & 0x1)
            curr = flst.erase_after(prev);
        else
            prev = curr++;

    for (auto i : flst) cout << i << " ";

    system("pause");
    return 0;
}

练习9.28
#include
#include
#include
#include
#include
#include
using namespace std;

bool sertElemAfterFind(forward_list &forList, string str1, string str2)
{
    auto i_before = forList.before_begin();
    for (auto i = forList.begin(); i != forList.end(); i++, i_before++)
    {
        if (str1 == *i)
        {
            forList.insert_after(i, str2);
            return true;
        }
    }
    forList.insert_after(i_before, str2);
    return false;
}
int main(int argc, char** argv)
{
    forward_list flst(5,"Hello");

    sertElemAfterFind(flst, "f", "ss");
    for (auto i : flst) cout << i << " ";

    system("pause");
    return 0;
}

练习9.29
添加75个0进vec;
从vec末尾删除90个元素。

练习9.30
如果元素是class,但是该类没有default构造函数,就有问题了。

练习9.31
list和forward_list没有 += 操作。
list将该操作替换成advance(iter, 2);即可

forward_list版本:
#include
#include
#include
#include
#include
#include
using namespace std;

bool sertElemAfterFind(forward_list &forList, string str1, string str2)
{
    auto i_before = forList.before_begin();
    for (auto i = forList.begin(); i != forList.end(); i++, i_before++)
    {
        if (str1 == *i)
        {
            forList.insert_after(i, str2);
            return true;
        }
    }
    forList.insert_after(i_before, str2);
    return false;
}
int main(int argc, char** argv)
{
    forward_list vi = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
    auto iter = vi.begin();
    auto iter_bef = vi.before_begin();
    while (iter != vi.end()) {
        if (*iter % 2) {
            iter = vi.insert_after(iter, *iter);
            advance(iter, 1);
            advance(iter_bef, 2);
        }
        else
            iter = vi.erase_after(iter_bef);
            
    }

    for (auto i : vi) cout << i << " ";

    system("pause");
    return 0;
}

练习9.32
不合法,给iter自增,会导致越界。

练习9.33
崩溃,在插入或删除操作之后,导致iter失效。

练习9.34
遇到奇数,不断插入奇数。

练习9.35
capacity是vector当前最大能够容纳多少个元素,size是vector
当前容纳的元素个数。

练习9.36
不可能

练习9.37
arry是固定大小数组,list是双向链表不需要变长,使用再分配内存即可

练习9.38

练习9.39
cin的输入中,当元素到达capacity值,capacity会自动变大。
而reseize是增大了size,当然size到一定地步,capacity会再次自动变大。

练习9.40

练习9.41
 vector vec{'p', 'e', 'z', 'y'};
 string str(vec.begin(), vec.end());

练习9.42
s.reseize(100);

练习9.43
#include
#include
#include
#include
#include
#include
using namespace std;


void Replace(string& s, const string& oldVal, const string& newVal)
{
    for (auto beg = s.begin(); std::distance(beg, s.end()) >=
        std::distance(oldVal.begin(), oldVal.end());) {
        if (string{ beg, beg + oldVal.size() } == oldVal) {
            beg = s.erase(beg, beg + oldVal.size());
            beg = s.insert(beg, newVal.cbegin(), newVal.cend());
            std::advance(beg, newVal.size());
        }
        else
            ++beg;
    }
}
int main(int argc, char** argv)
{
    string str{ "To drive straight thru is a foolish, tho courageous act." };
    Replace(str, "thru", "through");
    Replace(str, "tho", "though");
    std::cout << str << std::endl;

    system("pause");
    return 0;
}

练习9.44
void Replace(string& s, string const& oldVal, string const& newVal)
{
    for (string::size_type i = 0; i != s.size(); ++i)
        if (s.substr(i, oldVal.size()) == oldVal) {
            s.replace(i, oldVal.size(), newVal);
            i += newVal.size() - 1;
        }
}

练习9.45
#include
#include
#include
#include
#include
#include
using namespace std;

std::string pre_suffix(const std::string name, const std::string pre,const std::string su)
{
    auto ret = name;
    ret.insert(ret.begin(),pre.begin(),pre.end());
    ret.append(su);
    return ret;
}
int main(int argc, char** argv)
{
    std::string name("alan");
    std::cout << pre_suffix(name, "Mr.", ",Jr.") << std::endl;

    system("pause");
    return 0;
}

练习9.46
#include
#include
#include
#include
#include
#include
using namespace std;


std::string pre_suffix(const std::string& name, const std::string& pre,
    const std::string& su)
{
    std::string ret(name);
    ret.insert(0, pre);
    ret.insert(ret.size(), su);

    return ret;
}
int main(int argc, char** argv)
{
    std::string name("alan");
    std::cout << pre_suffix(name, "Mr.", ",Jr.") << std::endl;

    system("pause");
    return 0;
}

 

你可能感兴趣的:(C++)