List容器

1、List

(1)定义

List是一种序列式容器。List容器完成的功能实际上和数据结构中的双向链表是极其相似的,List中的数据元素是通过链表指针串连成逻辑意义上的线性表,也就是List也具有链表的主要优点,即:在链表的任一位置进行元素的插入、删除操作都是快速的。

(2)底层实现

List的实现大概是这样的,类似双向链表,:list的每个节点有三个域:前驱元素指针域、数据域和后继元素指针域。

前驱元素指针域保存了前驱元素的首地址;数据域则是本节点的数据;后继元素指针域则保存了后继元素的首地址。其实,List和循环链表也有相似的地方,即:头节点的前驱元素指针域保存的是链表中尾元素的首地址,List的尾节点的后继元素指针域则保存了头节点的首地址,这样,List实际上就构成了一个双向循环链。

由于List元素节点并不要求在一段连续的内存中,显然在List中是不支持快速随机存取的,因此对于迭代器,只能通过“++”或“--”操作将迭代器移动到后继/前驱节点元素处。而不能对迭代器进行+n或-n的操作,这点是与vector等不同的地方。

(3)使用

使用list容器之前必须加上<list>头文件:#include<list>;

List属于std命名域的内容,因此需要通过命名限定:using std::list;也可以直接使用全局的命名空间方式:using namespace std。

(4)特点

优点:(1)内存不连续

          (2)动态操作,插入与删除效率高;

          (3)可在两端进行pop,push。

缺点:(1)不能随机访问;

          (2)相对于vector占用内存多(需要存储前驱后继元素指针域)。

2、成员函数

(1)构造函数

/*构造函数*/
list() 
//声明一个空列表;
list(n) 
//声明一个有n个元素的列表,每个元素都是由其默认构造函数T()构造出来的
list(n,val) 
//声明一个由n个元素的列表,每个元素都是由其复制构造函数T(val)得来的
list(n,val) 
//声明一个和上面一样的列表
list(first,last) 
//声明一个列表,其元素的初始值来源于由区间所指定的序列中的元素

(2)赋值操作

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

c.assign(n,num);
//将n个num拷贝赋值给链表c。
c.assign(beg,end);
//将[beg,end)区间的元素拷贝赋值给链表c。

示例:

int a[5] = {1,2,3,4,5};
    list<int> a1;
    list<int>::iterator it;
    a1.assign(2,10);
    for(it = a1.begin();it!=a1.end();it++){
        cout << *it << " ";
    }
    cout << endl;
    a1.assign(a,a+5);
    for(it = a1.begin();it!=a1.end();it++){
        cout << *it << " ";
    }
    cout << endl;

(3)插入操作

push_back();
//push_back()从list的末端插入
push_front():
//push_front()实现的从list的头部插入

insert():
//在指定位置插入一个或多个元素(三个重载)
c.insert(pos,num);
//在pos位置插入元素num。
c.insert(pos,n,num);
//在pos位置插入n个元素num。
c.insert(pos,beg,end);
//在pos位置插入区间为[beg,end)的元素。

示例:

list<int> a1{1,2,3,4,5};
    list<int>::iterator it;
    cout << "insert before:";
    for(it = a1.begin();it!=a1.end();it++){
        cout << *it << " ";
    }
    cout << endl;
    
    a1.insert(a1.begin(),0);
    cout << "insert(pos,num) after:";
    for(it = a1.begin();it!=a1.end();it++){
        cout << *it << " ";
    }
    cout << endl;
    
    a1.insert(a1.begin(),2,88);
    cout << "insert(pos,n,num) after:";
    for(it = a1.begin();it!=a1.end();it++){
        cout << *it << " ";
    }
    cout << endl;

    int arr[5] = {11,22,33,44,55};
    a1.insert(a1.begin(),arr,arr+3);
    cout << "insert(pos,beg,end) after:";
    for(it = a1.begin();it!=a1.end();it++){
        cout << *it << " ";
    }
    cout << endl;

list<int> a1{1,2,3,4,5};
    a1.push_back(10);
    list<int>::iterator it;
    cout << "push_back:";
    for(it = a1.begin();it!=a1.end();it++){
        cout << *it << " ";
    }
    cout << endl;
    
    a1.pop_back();
    cout << "pop_back:";
    for(it = a1.begin();it!=a1.end();it++){
        cout << *it << " ";
    }
    cout << endl;
    
    a1.push_front(20);
    cout << "push_front:";
    for(it = a1.begin();it!=a1.end();it++){
        cout << *it << " ";
    }
    cout << endl;
    
    a1.pop_front();
    cout << "pop_front:";
    for(it = a1.begin();it!=a1.end();it++){
        cout << *it << " ";
    }
    cout << endl;

(4)删除操作

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

clear(): 
//清空list中的所有元素。

erase():
//删除一个元素或一个区域的元素(两个重载)
l1.erase(l1.begin()); 
//将l1的第一个元素删除。
l1.erase(l1.begin(),l1.end()); 
//将l1的从begin()到end()之间的元素删除。

remove(num);
//删除链表中匹配num的元素
remove_if(comp);
//删除条件满足的元素,参数为自定义的回调函数
unique();
//删除相邻的元素

示例:

list<int> a1{1,2,3,4,5};
    list<int>::iterator it;
    cout << "clear before:";
    for(it = a1.begin();it!=a1.end();it++){
        cout << *it << "	";
    }
    cout << endl;
    a1.clear();
    cout << "clear after:";
    for(it = a1.begin();it!=a1.end();it++){
        cout << *it << "	";
    }
    cout << endl;

list<int> a1{1,2,3,4,5};
    list<int>::iterator it;
    cout << "erase before:";
    for(it = a1.begin();it!=a1.end();it++){
        cout << *it << " ";
    }
    cout << endl;
    a1.erase(a1.begin());
    cout << "erase after:";
    for(it = a1.begin();it!=a1.end();it++){
        cout << *it << " ";
    }
    cout << endl;

list<int> a1{1,2,3,4,5};
    a1.remove(3);
    list<int>::iterator it;
    cout << "remove():";
    for(it = a1.begin();it!=a1.end();it++){
        cout << *it << " ";
    }
    cout << endl;

list<int> a1{1,2,3,4,5};
    a1.remove_if([](int n){return n<3;});
    list<int>::iterator it;
    cout << "remove_if():";
    for(it = a1.begin();it!=a1.end();it++){
        cout << *it << " ";
    }
    cout << endl;

list<int> a1{1,1,3,3,5};
    a1.unique();
    list<int>::iterator it;
    cout << "unique:";
    for(it = a1.begin();it!=a1.end();it++){
        cout << *it << " ";
    }
    cout << endl;
    return 0;

(5)定位操作

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

c.rbegin();
//返回逆向链表的第一个元素,即c链表的最后一个数据。
c.rend();
//返回逆向链表的最后一个元素的下一个位置,即c链表的第一个数据再往前的位置。

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

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

示例:

list<int> a1{1,2,3,4,5};
list<int>::iterator it;
for(it = a1.begin();it!=a1.end();it++){
cout << *it << "	";
}
cout << endl;

list<int> a1{1,2,3,4,5};
list<int>::reverse_iterator it;
for(it = a1.rbegin();it!=a1.rend();it++){
cout << *it << "	";
}
cout << endl;

list<int> a1{1,2,3,4,5};
if(!a1.empty()){
cout << "the first number is:" << a1.front() << endl;
cout << "the last number is:" << a1.back() << endl;
}

list<int> a1{1,2,3,4,5};
    a1.reverse();
    list<int>::iterator it;
    cout << "reverse:";
    for(it = a1.begin();it!=a1.end();it++){
        cout << *it << " ";
    }
    cout << endl;

(6)数据大小

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

c.size();
//返回链表c中实际元素的个数。
c.max_size();
//链表c可能容纳的最大元素数量。

示例:

list<int> a1{1,2,3,4,5};
    a1.resize(8);
    list<int>::iterator it;
    cout << "resize(n):";
    for(it = a1.begin();it!=a1.end();it++){
        cout << *it << " ";
    }
    cout << endl;
    
    a1.resize(10, 10);
    cout << "resize(n,num):";
    for(it = a1.begin();it!=a1.end();it++){
        cout << *it << " ";
    }
    cout << endl;

(7)交换操作

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

示例:

list<int> a1{1,2,3,4,5},a2,a3;
    a2.swap(a1);
    list<int>::iterator it;
    cout << "a2.swap(a1):";
    for(it = a2.begin();it!=a2.end();it++){
        cout << *it << " ";
    }
    cout << endl;
    
    swap(a3,a2);
    cout << "swap(a3,a2):";
    for(it = a3.begin();it!=a3.end();it++){
        cout << *it << " ";
    }
    return 0;

(8)合并操作

merge():
//合并两个链表并使之默认升序(也可改),l1.merge(l2,greater<int>()); 
//调用结束后l2变为空,l1中元素包含原来l1 和 l2中的元素,并且排好序,升序。
//其实默认是升序,greater<int>()可以省略,另外greater<int>()是可以变的,也可以不按升序排列。
c1.merge(c2);
//合并2个有序的链表并使之有序,从新放到c1里,释放c2。
c1.merge(c2,comp);
//合并2个有序的链表并使之按照自定义规则排序之后从新放到c1中,释放c2。

c1.splice(c1.beg,c2);
// 将c2连接在c1的beg位置,释放c2
c1.splice(c1.beg,c2,c2.beg);
//将c2的beg位置的元素连接到c1的beg位置,并且在c2中施放掉beg位置的元素
c1.splice(c1.beg,c2,c2.beg,c2.end);
//c2的[beg,end)位置的元素连接到c1的beg位置并且释放c2的[beg,end)位置的元素

示例:

list<int> a1{1,2,3},a2{4,5,6};
    a1.merge(a2);
    list<int>::iterator it;
    cout << "a1.merge(a2):";
    for(it = a1.begin();it!=a1.end();it++){
        cout << *it << " ";
    }
    cout << endl;
    
    a2.merge(a1,[](int n1,int n2){return n1>n2;});
    cout << "a2.merge(a1,comp):";
    for(it = a2.begin();it!=a2.end();it++){
        cout << *it << " ";
    }
    cout << endl;

list<int> a1{1,2,3},a2{4,5,6};
    a1.splice(a1.begin(), a2);
    list<int>::iterator it;
    cout << "a1.merge(a2):";
    for(it = a1.begin();it!=a1.end();it++){
        cout << *it << " ";
    }
    cout << endl;

list<int> a1{1,2,3},a2{4,5,6};
    a1.splice(a1.begin(), a2,++a2.begin());
    list<int>::iterator it;
    cout << "a1.merge(a2):";
    for(it = a1.begin();it!=a1.end();it++){
        cout << *it << " ";
    }
    cout << endl;
    return 0;

list<int> a1{1,2,3},a2{4,5,6};
    a1.splice(a1.begin(),a2,a2.begin(),a2.end());
    list<int>::iterator it;
    cout << "a1.merge(a2):";
    for(it = a1.begin();it!=a1.end();it++){
        cout << *it << " ";
    }
    cout << endl;
    return 0;

(9)排序操作

c.sort()       将链表排序,默认升序
c.sort(comp)       自定义回调函数实现自定义排序

示例:

list<int> a1{1,3,2,5,4};
    a1.sort();
    list<int>::iterator it;
    cout << "sort():";
    for(it = a1.begin();it!=a1.end();it++){
        cout << *it << " ";
    }
    cout << endl;
    
    a1.sort([](int n1,int n2){return n1>n2;});
    cout << "sort(function point):";
    for(it = a1.begin();it!=a1.end();it++){
        cout << *it << " ";
    }
    cout << endl;

(10)重载运算符

operator==
operator!=
operator<
operator<=
operator>
operator>=

示例:

list<int> a1 {1,2,3,4,5},a2;
a2 = a1;
list<int>::iterator it;
for(it = a2.begin();it!=a2.end();it++){
    cout << *it << endl;
}

  

原文地址:https://www.cnblogs.com/yedushusheng/p/5519959.html