C++STL之vector和list

一.vector---数组

1.vector的初始化

        相对于string,vector的设计更加简洁和精干,以下是3种常见的初始化方式:

int main()
{
    //1.用n个a元素初始化
    //vector<类型名> 变量名(n,a);
    vector<int> v1(10, 1);
    //2.用迭代器区间初始化
    //vector<类型名> 变量名(开始迭代器,结束迭代器);
    vector<int>::iterator it1 = v1.begin();
    vector<int>::iterator it2 = v1.end();
    vector<int> v2(it1,it2);
    //当然,某些类型就是用原生指针充当迭代器,因此也可以用指针来初始化
    int a[5] = { 1,2,3,4,5 };
    vector<int> v3(a, a + 5);

    //3.直接用拷贝构造来初始化
    vector<int> v4 = v3;


    cout << "v1:";
    for (auto i : v1)
    {
        cout << i << " ";
    }
    cout << endl;

    cout << "v2:";
    for (auto i : v2)
    {
        cout << i << " ";
    }
    cout << endl;

    cout << "v3:";
    for (auto i : v3)
    {
        cout << i << " ";
    }
    cout << endl;

    cout << "v4:";
    for (auto i : v4)
    {
        cout << i << " ";
    }
    cout << endl;


    return 0;
}

2.vector的增删查改

int main()
{
    vector<int> v1(10, 1);

    //1.可以使用下标来查看vector的各个元素
    //使用v1.size()获取v1的元素个数,同样,使用v1.capacity()获取其容量大小
    for (int i = 0; i < v1.size(); i++)
    {
        cout << v1[i] << " ";
    }
    cout << endl;

    //使用front和back获取数组首尾元素
    v1.front() = 2;
    v1.back() = 3;
    cout <<"v1首元素:" << v1.front()<<endl;
    cout << "v1尾元素:" << v1.back()<<endl;
    for (int i = 0; i < v1.size(); i++)
    {
        cout << v1[i] << " ";
    }
    cout << endl;

    //使用 变量名.push_back(要添加的元素) 向数组尾部添加元素
    v1.push_back(4);
    cout <<"v1尾部:" << v1[v1.size() - 1] << endl;

    //使用 变量名.insert(迭代器,要添加的元素) 向指定迭代器位置添加元素

    v1.insert(v1.begin()+2,10);
    cout << "向指定位置插入元素后:";
    for (int i = 0; i < v1.size(); i++)
    {
        cout << v1[i] << " ";
    }
    cout << endl;

    //使用 变量名.pop_back() 删除尾部元素
    v1.pop_back();
    cout << "删除尾部元素后:";
    for (int i = 0; i < v1.size(); i++)
    {
        cout << v1[i] << " ";
    }
    cout << endl;

    //使用 变量名.erase(迭代器) 删除指定迭代器位置的元素
    v1.erase(v1.begin()+2);
    cout << "向指定位置插入元素后:";
    for (int i = 0; i < v1.size(); i++)
    {
        cout << v1[i] << " ";
    }
    cout << endl;

    //使用 变量名.clear() 清空数组
    v1.clear();

    cout << "清空后:";
    for (int i = 0; i < v1.size(); i++)
    {
        cout << v1[i] << " ";
    }
    cout << endl;

    return 0;
}

二.list---链表

1.vector与list迭代器的区别与两个容器的优劣

        vector迭代器使用的是随机迭代器,允许进行++, -- , + , - , += , -= ,= 操作,且因为是随机迭代器,vector对象本身支持[]下标访问,而list使用的是单向迭代器,仅允许++,-- ,=操作,list对象本身不支持[]下标访问。

        就插入和删除而言,由于list并不像vector存在频繁挪动数据和整体性扩容,因此效率要高于vector,而就对容器内元素的访问而言,list无法直接用下标进行访问,效率要低于vector。

2.list的初始化

template<class T>
void printItems(T items)
{
    for (auto i : items)
    {
        cout << i << " ";
    }
    cout << endl;
}

int main()
{
    //1.使用n个a元素初始化
    //list<类型名> 变量名(n,a)
    list<int> l1(10,1);

    //2.使用迭代器初始化
    list<int> l2(l1.begin(), l1.end());
    //不一定要是list的迭代器哟~
    vector<int> v1(10, 1);
    list<int> l3(v1.begin(), v1.end());
    //当然,你也可以直接用原始数组
    int a[5] = { 1,2,3,4,5 };
    list<int> l4(a, a + 5);
    
    //3.直接拷贝构造
    list<int> l5 = l4;

    cout << "l1:";
    printItems(l1);

    cout << "l2:";
    printItems(l2);

    cout << "l3:";
    printItems(l3);

    cout << "l4:";
    printItems(l4);

    cout << "l5:";
    printItems(l5);

}

3.list的增删查改

template<class T>
void printItems(T items)
{
    for (auto i : items)
    {
        cout << i << " ";
    }
    cout << endl;
}

int main()
{
    list<int> l1(10, 1);
    cout << "l1:";
    printItems(l1);


    //使用front(),back()获取链表首尾元素
    l1.front() = 2;
    l1.back() = 3;
    cout << "改变首尾元素后:";
    printItems(l1);

    //由于无法使用下表访问元素,要访问中间位置的元素,我们直接对迭代器进行操作
    list<int>::iterator it = l1.begin();

    for (int i = 0; i < 2; i++)
    {
        it++;
    }

    *it = 4;
    cout << "改变中间元素后:";
    printItems(l1);

    //使用 变量名.push_front(元素) 和 变量名.push_back(元素) 向链表首尾添加元素
    l1.push_front(6);
    l1.push_back(7);
    cout << "向首尾插入元素后:";
    printItems(l1);

    //使用 变量名.insert(迭代器,要添加的元素) 向指定迭代器位置添加元素
    l1.insert(++l1.begin(),8);
    cout << "向指定位置插入元素后:";
    printItems(l1);

    //使用 变量名.pop_back() 和 变量名.pop_back() 删除首尾元素
    l1.pop_front();
    l1.pop_back();
    cout << "删除首尾元素后:";
    printItems(l1);

    //使用 变量名.erase(迭代器) 删除指定迭代器位置的元素
    l1.erase(++l1.begin());
    cout << "删除指定位置元素后:";
    printItems(l1);

    //使用 变量名.clear() 清空链表
    l1.clear();
    cout << "清空后:";
    printItems(l1);



    return 0;
}

三.迭代器失效问题

        在使用含有迭代器的容器时,我们可能一不小心就触发了迭代器的失效

int main()
{
    vector<int> v1(3, 2);
    vector<int>::iterator it = v1.begin();
    cout << *it << endl;

    v1.push_back(3);
    cout << *it << endl;


    return 0;
}

        如图,*it在第二次并未像我们预想的一样将2打印出来,原因就在于it这个迭代器失效了,正如其字面意思,迭代器失效,就是迭代器失去了原来的效果,无法被继续使用了

        迭代器失效有两种原因,第一种是迭代器所指向的原有空间所含内容被删除或转移,形成了野指针,我们所举的例子就属于这种,最开始初始化时我们为其分配了3个元素的空间,但后面又追加了一个元素,原有空间不够,数组扩容,原有内容被转移,it迭代器自然也就失效了

        还有一种原因,就是原有迭代器含义变了

int main()
{
    vector<int> v1(6, 2);
    vector<int>::iterator it = v1.begin();
    cout << *it << endl;

    while (it != v1.end())
    {
        v1.erase(it);
        it++;
    }

    cout << v1.size() << endl;
    

    return 0;
}

        我们想用while循环来清空v1,但在删除it的内容后,it指向该内容的下一个,而it仍要++,跳过了该内容的下一个,无法完成任务

        想要避免这种情况,需要将it删除后的结果重新赋值给it以代替++,删除后其本身就已经指向下一个了

        修改后如下:

int main()
{
    vector<int> v1(6, 2);
    vector<int>::iterator it = v1.begin();
    cout << *it << endl;

    while (it != v1.end())
    {
        it = v1.erase(it);
    }

    cout << v1.size() << endl;
    

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值