list

1.双向循环链表list的原理:

    list是双向循环链表,每个元素都知道前面一个元素和后面一个元素。在STL中,list和vector一样是俩个常用的容器。和vector不一样的是:list不支持对元素的任意存取。list中提供的成员函数与vector类似,不过list提供对首元素的操作push_front,pop_front,这个vector不具备的。和vector另一点不同的是,list的迭代器不会存在失效的情况,它不像vector会保留备份空间,在超过容量额度时会重新全部分配内存,导致迭代器失效;list没有备份空间的概念,出入一个元素就申请一个元素的空间,所以它的迭代器不会失效。

例如:

int data[6]={3,5,7,9,2,4};
    list<int>l(data,data+6);
    l.push_back(6);

list初始化时,申请的空间大小为6,存放了data中的6个元素,当向l中插入第七个元素“6”时,list申请新的节点单元,插入list链表中。

如图:

 

        list每次增加一个元素,不存在重新申请内存的情况,它的成本是恒定的。而vector没当增加关键元素的时候,都需要重新申请新的更大的内存空间,会调用元素的自身的复制构造函数,存在构造成本。在销毁旧内存的时候,会调用析构函数,存在析构成本。所以存储复杂类型和大量元素的情况下,list比vector更有优势。
        list是一个双向链表,双向链表既可以向前又可以向后链接其他元素。

       list将元素按顺序储存在链表中,与向量(vector)相比,它允许快速的插入和删除,但是随机访问却比较慢。

 

2.list的初始化:

 

list<int>li();              //申请一个空列表;
list<int>li(n);            //声明一个有n个元素的列表,每个元素都有其默认构造函数T()构造出来的;
list<int>li(n,val);       //声明一个由n个元素的列表,每个元素都是由其复制构造函数T(val)而来
list<int>li(first,last); //声明一个列表,其元素的初始值来源由区间所指定的序列中的元素
    

 

 

3.list的函数:

a:

crbegin/crend
cbegin/cend

这个4个是c++11新增的四个函数,在set那篇博客有详细的解释。

 

b:begin()和end()

通过调用list容器的成员函数begin()得到一个指向容器起始位置的iterator,可以调用list容器的 end() 函数来得到list末端下一位置,相当于:int a[n]中的第n+1个位置,实际上是不存在的,不能访问,经常作为循环结束判断结束条件使用。

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int a[]={1,2,3,4};
    list<int>l(a,a+4);
    for(list<int>::iterator it=l.begin();it!=l.end();++it){
        cout<<*it<<" ";
    }
    cout<<endl;


    for(auto &it:l){
        cout<<it<<endl;
    }


    return 0;
}

 

 

 

c:push_back() 和push_front()

使用list的成员函数push_back和push_front插入一个元素到list中。其中push_back()从list的末端插入,而 push_front()实现的从list的头部插入。

d:front()和back()

 通过front()可以获得list容器中的头部元素,通过back()可以获得list容器的最后一个元素。但是有一点要注意,就是list中元素是空的时候,这时候调用front()和back()会发生什么呢?实际上会发生不能正常读取数据的情况,但是这并不报错,那我们编程序时就要注意了,个人觉得在使用之前最好先调用empty()函数判断list是否为空。

e:pop_back和pop_front()

通过删除最后一个元素,通过pop_front()删除第一个元素;序列必须不为空,如果当list为空的时候调用pop_back()和pop_front()会使程序崩掉。

f: empty()

利用empty() 判断list是否为空。

g:clear()

清空list中的所有元素。

#include<bits/stdc++.h>
using namespace std;
int main()
{
    list<int>p(2,0);
    p.push_back(2);
    p.push_front(1);
    int len=p.size();
    cout<<"p的长度="<<len<<endl;
    for(auto &it:p){
        cout<<it<<" ";
    }
    cout<<endl;


    cout<<"头部元素="<<p.front()<<endl;
    cout<<"尾部元素="<<p.back()<<endl;


    p.pop_back();
    p.pop_front();
    for(auto &it:p){
        cout<<it<<" ";
    }
    cout<<endl;


    if(!p.empty()) cout<<"容器p不为空"<<endl;
    p.clear();
    if(p.empty()) cout<<"容器p为空"<<endl;





    return 0;
}

 

 

h:resize()

 如果调用resize(n)将list的长度改为只容纳n个元素,超出的元素将被删除,如果需要扩展那么调用默认构造函数T()将元素加到list末端。如果调用resize(n,val),则扩展元素要调用构造函数T(val)函数进行元素构造,其余部分相同。

#include<bits/stdc++.h>
using namespace std;
int main()
{
    list<int>p;
    for(int i=1;i<10;i++) p.push_back(i);

    p.resize(5);
    p.resize(8,100);
    p.resize(12);
    for(auto &it:p) cout<<it<<" ";
    return 0;
}

1 2 3 4 5 100 100 100 0 0 0 0

 

 

i:assign()

具体和vector中的操作类似,也是有两种情况,第一种是:l1.assign(n,val)将 l1中元素变为n个T(val)。第二种情况是:l1.assign(l2.begin(),l2.end())将l2中的从l2.begin()到l2.end()之间的数值赋值给l1。

#include<bits/stdc++.h>
using namespace std;
int main()
{
    list<int>first;
    list<int>second;
    first.assign(7,100);
    for(auto &it:first) cout<<it<<" ";
    cout<<endl;


    second.assign(first.begin(),first.end());
    for(auto &it:second) cout<<it<<" ";
    cout<<endl;

    int a[]={1,2,3};
    first.assign(a,a+3);
    for(auto &it:first) cout<<it<<" ";
    cout<<endl;

    return 0;
}

 

 

 

 j:reverse():

   通过reverse()完成list的逆置。

k:swap()

交换两个链表(两个重载),一个是l1.swap(l2); 另外一个是swap(l1,l2),都可能完成连个链表的交换。

#include<bits/stdc++.h>
using namespace std;
int main()
{
    list<int>first;
    list<int>second;
    first.assign(7,100);
    second.assign(2,200);
    first.swap(second);
    for(auto &it:first) cout<<it<<" ";
    cout<<endl;

    for(auto &it:second) cout<<it<<" ";
    cout<<endl;

    return 0;
}

 

 

l: merge()

合并两个链表并使之默认升序(也可改),l1.merge(l2); 调用结束后l2变为空,l1中元素包含原来l1 和 l2中的元素,并且排好序,升序。

 

 

 

 

m: insert()  在指定位置插入一个或多个元素(三个重载):

l1.insert(l1.begin(),100); 在l1的开始位置插入100。

l1.insert(l1.begin(),2,200); 在l1的开始位置插入2个100。

l1.insert(l1.begin(),l2.begin(),l2.end());在l1的开始位置插入l2的从开始到结束的所有位置的元素。

#include <iostream>
#include <list>
#include<bits/stdc++.h>
using namespace std;

int main()
{
    list<int>p(2,100);
    p.insert(p.begin(),200);
    p.insert(p.begin(),3,50);
    list<int>l(3,666);
    p.insert(p.begin(),l.begin(),l.end());
    for(auto &it:p) cout<<it<<" ";
    return 0;
}

 

 

n:erase() 删除一个元素或一个区域的元素(两个重载)

l1.erase(l1.begin()); 将l1的第一个元素删除。

l1.erase(l1.begin(),l1.end()); 将l1的从begin()到end()之间的元素删除。

 

 

remove from list
#include <iostream>
#include <list>

int main ()
{
  int myints[]= {17,89,7,14};
  std::list<int> mylist (myints,myints+4);

  mylist.remove(89);

  std::cout << "mylist contains:";
  for (std::list<int>::iterator it=mylist.begin(); it!=mylist.end(); ++it)
    std::cout << ' ' << *it;
  std::cout << '\n';

  return 0;
}
Edit & Run

 这个删除的是值不是迭代器指向的指针

mylist contains: 17 7 14
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值