C++PrimerV5/Ch09/ex9.26-9.36

本文通过具体示例展示了如何使用C++标准库中的容器进行元素的添加、删除及查找等操作,包括vector、list、forward_list等不同类型的容器,并探讨了在循环中更新迭代器的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

ex9.26: 定义int ia[] = {0,1,1,2,3,5,8,13,21,55,89};将数组ia 拷贝到一个vector 和一个list中,使用单迭代器版本的erase函数从list删除奇数元素,从vector删除偶数元素。

知识点考查:删除元素

c.pop_front(); //删除首元素;vector/string 不支持此成员函数
c.pop_back(); //删除尾元素;
             //forward_list不支持 递减--,back(),pop_back()
c.erase(p);
//删除迭代器所指定的元素,返回一个指向被删元素之后元素的迭代器,若p指向尾元素,则返回尾后迭代器,若p是尾后迭代器,则函数行为未定义;
c.erase(b,e);
//删除迭代器b和e所指定范围内的元素,返回一个指向最后一个被删元素之后元素的迭代器,若e本身就是尾后迭代器,则函数也返回尾后迭代器
b=c.erase(b,e);//调用后,b==e,

c.clear();//删除c中所有元素,返回void
c.erase(c.begin(),c.end());//等价于c.clear();

代码如下:

#include<iostream>
#include<vector>
#include<list>
using namespace std;

int main()
{
    int ia[] = {0,1,1,2,3,5,8,13,21,55,89};
    vector<int>vint;
    list<int>lint;
    for (int i=0;i<sizeof(ia)/sizeof(int);i++)//int型数组长度表示 sizeof(ia)/sizeof(int)
    {
        vint.push_back(ia[i]);
        lint.push_back(ia[i]);
    }
    auto it1 = vint.begin();
    auto it2 = lint.begin();

    while (it1 != vint.end())
    {
        if (!(*it1 % 2))//若为偶数
            it1=vint.erase(it1);//it1自动指向所删除元素之后的元素
        else
            ++it1;
    }
    while (it2 != lint.end())
    {
        if (*it2 % 2)//若为奇数
            it2 = lint.erase(it2);
        else
            ++it2;
    }
    for (auto i : vint)
        cout << i<< " ";
    cout << endl;

    for (auto j : lint)
        cout << j << " ";
    cout << endl;
    return 0;
}

这里写图片描述

ex9.27: 编写程序,查找并删除forward_list中的奇数元素。

知识点考查:forward_list

**//-------forward_list中的插入删除操作-----------**

lst.before_begin()//返回指向链表首元素之前不存在的元素的迭代器
lst.cbefore_begin()//返以一个const-iterator

lst.insert_after(p,t)//在迭代器p之后的位置插入元素t
lst.insert_after(p,n,t)//在迭代器p之后的位置插入n个元素t
lst.insert_after(p,b,e)//在迭代器p之后的位置插入迭代器[b e)之间元素
lst.insert_after(p,il)//在迭代器p之后的位置插入花括号列表il中的元素

emplace_after(p,args)//使用args在p指定的位置之后创建一个元素。返回一个指向这个新元素的迭代器。若p为尾后迭代器,则函数未定义。

lst.erase_after(p)//删除p指向的位置之后的元素,返回一个被删除元素之后元素的迭代器
lst.erase_after(b,e)//删除从[b,e)之间的元素,返回一个被删除元素之后元素的迭代器

/*注意:
forward_list不支持 递减--,push_back, pop_back, back 等操作
未定义 insert, emplace, erase,
而定义 insert_after, emplace_after, erase_after,
*/

代码如下:

#include<iostream>
#include<forward_list>
using namespace std;

int main()
{
    forward_list<int>flint = {0,1,2,3,4,5,6,7,8,9};
    auto prev = flint.before_begin();//首前元素
    auto curr= flint.begin();//首元素

    while (curr!=flint.end())
    {
        if (*curr % 2)//若是奇数
        {
            curr = flint.erase_after(prev);//删除prev的下一个元素,即删除当前元素,返回下一个元素
        }
        else
        {
            prev = curr;
            ++curr;
        }   
    }
    for (auto i : flint)
        cout << i << " ";
    cout << endl;
    return 0;
}

这里写图片描述

ex9.28: 编写函数,接受以恶搞forward_list和两个string共三个参数。函数应在链表中查找第一个string,并将第二个string插入到紧接着第一个string之后的位置。若第一个string未在链表中,则将第二个string插入到链表末尾。

代码如下:

#include<iostream>
#include<forward_list>
#include<string>
using namespace std;
void insert(forward_list<string>& fls2, const string &s1, const string &s2)
{
    auto curr = fls2.begin();
    auto prev = fls2.before_begin();
    for (; curr != fls2.end(); prev = curr++)
    {
        if (*curr == s1)
        {
            fls2.insert_after(curr, s2);
            return;
        }
    }
    fls2.insert_after(prev, s2);
}
int main()
{
    //forward_list<string>fls = { "a","ab","abc","abcd" };
    forward_list<string>fls = { "a","abc","abcd" };

    insert(fls,"ab","ab2");

    string str;
    for (auto str : fls)
        cout << str << " ";
    cout << endl;
    return 0;
}

这里写图片描述

ex9.29:

//考查知识点:resize()来增大或缩小容器;
/*
list<int>ilist(10,42);//10个int,每个值都是42
ilist.resize(15);//在ilist的末尾添加5个0
ilist.resize(25,-1);//在ilist末尾添加10个-1
ilist.resize(5);//从ilist末尾删除20个元素
*/
#include <iostream> 
#include <vector>  
using namespace std;

int main()
{
    vector<int> vec(25, 1);
    int i;
    for (auto i:vec)
        cout << i << " ";
    cout << endl;
    cout << endl;

    vec.resize(100);//将75个0元素添加到vector的末尾  
    for (auto i : vec)
        cout << i << " ";
    cout <<endl;
    cout << endl;

    vec.resize(10); //从vector末尾删除90个元素  
    for (auto i : vec)
        cout << i << " ";
    cout << endl;

    return 0;
}

这里写图片描述

ex9.31: 实现循环程序,删除偶数数值元素,复制奇数数值元素。

(1)vector、string、deque实现
添加或者删除vector、string、deque元素的循环元素必须考虑迭代器,引用,指针可能失效的问题;
程序必须保证每个循环步中都更新迭代器、引用或指针;
若循环中调用的是insert 或erase,那么更新迭代器很容易,因为这些操作都返回迭代器;

#include <iostream>
#include <list>
using namespace std;

int main()
{
    list<int> vi = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
    auto iter = vi.begin();//调用begin而不是cbegin,因为要改变vi
    while (iter != vi.end())
    {
        if (*iter % 2) 
        {
            iter = vi.insert(iter, *iter);//复制当前奇数元素
            iter+=2;//向前移动迭代器,跳过了当前元素已经插入到它之前的元素
        }
        else
            iter = vi.erase(iter);//删除偶数元素,返回的iter指向被删元素的下一个元素
    }
    for (auto i : vi)
        cout << i << " ";
    return 0;
}

(2) list实现
当向容器中添加或者删除元素时,对于list和forward_list,指向容器的迭代器(包括尾后迭代器和首前迭代器)、指针和引用仍有效

#include <iostream>
#include <list>
using namespace std;
int main()
{
    list<int> vi = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
    auto iter = vi.begin();
    while (iter != vi.end())
    {
        if (*iter % 2) 
        {
            iter = vi.insert(iter, *iter);
            advance(iter, 2);//类比iter+=2;但list不支持递增++运算符
        }
        else
            iter = vi.erase(iter);
    }
    for (auto i : vi)
        cout << i << " ";
    return 0;
}

(3) forward_list实现

#include <iostream>
#include <forward_list>
using namespace std;
int main()
{
    forward_list<int> vi = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
    auto iter = vi.begin(), prev = vi.before_begin();
    while (iter != vi.end())
    {
        if (*iter % 2) 
        {
            iter = vi.insert_after(prev, *iter);
            advance(iter, 2);//注意比较
            advance(prev, 2);//注意比较
        }
        else
            iter = vi.erase_after(prev);
    }
    for (auto i : vi) 
        cout << i << " ";
    return 0;
}

这里写图片描述
——————————————
ex9.32-9.36较简单,略过!
——————————————

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值