C++——list

1、list的介绍及使用

1.1list的介绍

我用一张图简单的介绍一下,有需要详细了解的可以到该网址查询:cplusplus.com/reference/list/list/?kw=list

1.2list的使用

list中的接口比较多,此处类似,只需要掌握如何正确的使用,然后再去深入研究背后的原理,已
达到可扩展的能力。以下为list中一些常见的重要接口

1.2.1list的构造

构造函数( (constructor))cplusplus.com/reference/list/list/list/

借口说明

list (size_type n, const value_type& val =
value_type())
构造的list中包含n个值为val的元素
list()
构造空的list
list (const list& x)
拷贝构造函数
list (InputIterator first, InputIterator last)
用[first, last)区间中的元素构造list

1.2.2list iterator的使用

此处,大家可暂时将迭代器理解成一个指针,该指针指向list中的某个节点
函数声明
接口说明
begin+end
返回第一个元素的迭代器+返回最后一个元素下一个位置的迭代器
rbegin+rend
返回第一个元素的reverse_iterator,即end位置返回最后一个元素下一个位置的reverse_iterator,即begin位置

注意
1. begin与end为正向迭代器,对迭代器执行++操作,迭代器向后移动
2. rbegin(end)与rend(begin)为反向迭代器,对迭代器执行++操作,迭代器向前移动
1.2.3 list capacity

函数声明

接口说明
empty
检测list是否为空,是返回true,否则返回false
size
返回list中有效节点的个数

1.2.4 list element access
函数声明接口说明
front
返回list的第一个节点中值的引用
back
返回list的最后一个节点中值的引用

1.2.5 list modifiers
函数声明

接口说明

push_front
在list首元素前插入值为val的元素
pop_front删除list中第一个元素
push_back在list尾部插入值为val的元素
pop_back删除list中最后一个元素
insert在list position 位置中插入值为val的元素
erase删除list position位置的元素
swap交换两个list中的元素
clear清空list中的有效元素

除以上这些外,list还有其它操作,需要的时候皆可在开头我放的地址中查询。

1.2.6 list的迭代器失效
前面说过,此处大家可将迭代器暂时理解成类似于指针,迭代器失效即迭代器所指向的节点的无
效,即该节点被删除了。因为list的底层结构为带头结点的双向循环链表,因此在list中进行插入
时是不会导致list的迭代器失效的,只有在删除时才会失效,并且失效的只是指向被删除节点的迭
代器,其他迭代器不会受到影响
2、list的模拟实现
2.1 模拟实现list
要模拟实现list,必须要熟悉list的底层结构以及其接口的含义,通过上面的学习,这些内容已基本
掌握,现在我们来模拟实现list。

2.2 list的反向迭代器
通过前面例子知道,反向迭代器的++就是正向迭代器的--,反向迭代器的--就是正向迭代器的++,
因此反向迭代器的实现可以借助正向迭代器,即:反向迭代器内部可以包含一个正向迭代器,对
正向迭代器的接口进行包装即可。

3. list与vector的对比
vector与list都是STL中非常重要的序列式容器,由于两个容器的底层结构不同,导致其特性以及
应用场景不同,其主要不同如下:
vectorlist
底层结构
动态顺序表,一段连续空间
带头结点的双向循环链表
随机访问
支持随机访问,访问某个元素效率O(1)
不支持随机访问,访问某个元 素效率O(N)
插入和删除
任意位置插入和删除效率低,需要搬移元素,时间复杂度为O(N),插入时有可能需要增容,增容:开辟新空间,拷贝元素,释放旧空间,导致效率更低
任意位置插入和删除效率高,
不需要搬移元素,时间复杂度
为O(1)
空间利用率
底层为连续空间,不容易造成内存碎片,空间利用
率高,缓存利用率高
底层节点动态开辟,小节点容
易造成内存碎片,空间利用率
低,缓存利用率低
迭代器
原生态指针
对原生态指针(节点指针)进行
封装
迭代器失效
在插入元素时,要给所有的迭代器重新赋值,因为
插入元素有可能会导致重新扩容,致使原来迭代器
失效,删除时,当前迭代器需要重新赋值否则会失
插入元素不会导致迭代器失
效,删除元素时,只会导致当
前迭代器失效,其他迭代器不
受影响
使用场景
需要高效存储,支持随机访问,不关心插入删除效
大量插入和删除操作,不关心
随机访问

另外提供一段代码:

#define _CRT_SEURE_NO_WARNINGS 1

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

void test_list1()
{
    list<int> lt1;
    list<int> lt2(10, 1);
    vector<int> v1 = { 1, 2, 3, 4, 5, 6 };
    list<int> lt3(v1.begin(), v1.end());
    list<int> lt4 = { 1,2,3,4,5,6,1,1,1,1 };

    int a[] = { 1,20,3,40 };
    list<int> lt5(a, a + 4);
    sort(a, a + 4);

    //1、封装,通用的相似的遍历容器的方式,并且封装屏蔽了容器结构的差异和底层实现的细节
    //2、复用,实现算法时用迭代器函数模板方式实现,跟底层容器结构解耦

    list<int>::iterator it4 = lt4.begin();
    while (it4 != lt4.end())
    {
        cout << *it4 << " ";
        ++it4;
    }
    cout << endl;

    for (auto e : lt4)
    {
        cout << e << " ";
    }
    cout << endl;

    sort(a, a + 4);
    sort(v1.begin(),v1.end());
    sort(lt3.begin(), lt3.end());

    reverse(lt3.begin(), lt3.end());
    reverse(v1.begin(), v1.end());
}

void test_list2()
{
    list<int> lt2(10, 1);
    lt2.push_back(10);
    lt2.push_front(10);
    for (auto e : lt2)
    {
        cout << e << " ";
    }
    cout << endl;

    lt2.resize(20, 2);
    for (auto e : lt2)
    {
        cout << e << " ";
    }
    cout << endl;
    lt2.resize(5);
    for (auto e : lt2)
    {
        cout << e << " ";
    }
    cout << endl;
}

void test_op1()
{
    srand(time(0));
    const int N = 1000000;

    list<int> lt1;
    vector<int> v;

    for (int i = 0; i < N; ++i)
    {
        auto e = rand() + i;
        lt1.push_back(e);
        v.push_back(e);
    }

    int begin1 = clock();
    //排序
    sort(v.begin(), v.begin());
    int end1 = clock();

    int begin2 = clock();
    lt1.sort();
    int end2 = clock();

    printf("vector sort:%d\n", end1 - begin1);
    printf("list sort:%d\n", end2 = begin2);
}

int main()
{
    test_op1();
    //test_list2();
}
 

最后,希望本篇博客对大家有所帮助,代码有错误可在评论区指出,谢谢大家啦!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值