STL list

STL list

list 容器,又称双向链表容器,即该容器的底层是以双向链表的形式实现的。这意味着,list 容器中的元素可以分散存储在内存空间里,而不是必须存储在一整块连续的内存空间中。

存储结构示意图

在这里插入图片描述

基于这样的存储结构,list 容器具有一些其它容器(array、vector 和 deque)所不具备的优势,即它可以在序列已知的任何位置快速插入或删除元素(时间复杂度为O(1))。并且在 list 容器中移动元素,也比其它容器的效率高。

缺点是,它不能像 array 和 vector 那样,通过位置直接访问元素。举个例子,如果要访问 list 容器中的第 6 个元素,它不支持容器对象名[6]这种语法格式,正确的做法是从容器中第一个元素或最后一个元素开始遍历容器,直到找到该位置。

创建 list 容器

//方法一
std::list<int> values;

//方法二
std::list<int> values(10);

//方法三
std::list<int> values(10, 5);

//方法四
std::list<int> value1(10);
std::list<int> value2(value1);

//方法五
int a[] = { 1,2,3,4,5 };
std::list<int> values(a, a+5);//拷贝普通数组,创建list容器
//拷贝其它类型的容器,创建 list 容器
std::array<int, 5>arr{ 11,12,13,14,15 };
std::list<int>values(arr.begin()+2, arr.end());//拷贝arr容器中的{13,14,15}

list 容器可用的成员函数

成员函数功能
begin()返回指向容器中第一个元素的双向迭代器。
end()返回指向容器中最后一个元素所在位置的下一个位置的双向迭代器。
rbegin()返回指向最后一个元素的反向双向迭代器。
rend()返回指向第一个元素所在位置前一个位置的反向双向迭代器。
cbegin()和 begin() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改元素。
cend()和 end() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改元素。
crbegin()和 rbegin() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改元素。
crend()和 rend() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改元素。
empty()判断容器中是否有元素,若无元素,则返回 true;反之,返回 false。
size()返回当前容器实际包含的元素个数。
max_size()返回容器所能包含元素个数的最大值。这通常是一个很大的值,一般是 232-1,所以我们很少会用到这个函数。
front()返回第一个元素的引用。
back()返回最后一个元素的引用。
assign()用新元素替换容器中原有内容。
emplace_front()在容器头部生成一个元素。该函数和 push_front() 的功能相同,但效率更高。
push_front()在容器头部插入一个元素。
pop_front()删除容器头部的一个元素。
emplace_back()在容器尾部直接生成一个元素。该函数和 push_back() 的功能相同,但效率更高。
push_back()在容器尾部插入一个元素。
pop_back()删除容器尾部的一个元素。
emplace()在容器中的指定位置插入元素。该函数和 insert() 功能相同,但效率更高。
insert()在容器中的指定位置插入元素。
erase()删除容器中一个或某区域内的元素。
swap()交换两个容器中的元素,必须保证这两个容器中存储的元素类型是相同的。
resize()调整容器的大小。
clear()删除容器存储的所有元素。
splice()将一个 list 容器中的元素插入到另一个容器的指定位置。
remove(val)删除容器中所有等于 val 的元素。
remove_if()删除容器中满足条件的元素。
unique()删除容器中相邻的重复元素,只保留一个。
merge()合并两个事先已排好序的 list 容器,并且合并之后的 list 容器依然是有序的。
sort()通过更改容器中元素的位置,将它们进行排序。
reverse()反转容器中元素的顺序。

代码示范:

#include <iostream>
#include <list>
using namespace std;
int main(){
	//创建空的list容器
	std::list<double> l;
	//添加元素
	l.push_back(3.1);
	l.push_back(2.2);
	l.push_back(2.9);
	//输出元素个数
	printf("元素个数:%d\n",l.size());
	//排序
	l.sort();
	//遍历输出
	for(std::list<double>::iterator it=l.begin();it!=l.end();it++){
		//这里变量类型用auto当然也是可以的 
		cout<<*it<<" ";
	} 
	return 0;
} 

运行结果:

在这里插入图片描述

list 容器中添加或插入新的元素

相关成员函数如下:

  • push_front():向 list 容器首个元素前添加新元素;
  • push_back():向 list 容器最后一个元素后添加新元素;
  • emplace_front():在容器首个元素前直接生成新的元素;
  • emplace_back():在容器最后一个元素后直接生成新的元素;
  • emplace():在容器的指定位置直接生成新的元素;
  • insert():在指定位置插入新元素;
  • splice():将其他 list 容器存储的多个元素添加到当前 list 容器的指定位置处。

除了 insert() 和 splice() 方法有多种语法格式外,其它成员方法都仅有 1 种语法格式。

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

int main()
{
    std::list<int> values{1,2,3};
    values.push_front(0);//{0,1,2,3}
    values.push_back(4); //{0,1,2,3,4}

    values.emplace_front(-1);//{-1,0,1,2,3,4}
    values.emplace_back(5);  //{-1,0,1,2,3,4,5}
   
    //emplace(pos,value),其中 pos 表示指明位置的迭代器,value为要插入的元素值
    values.emplace(values.end(), 6);//{-1,0,1,2,3,4,5,6}
    for (auto p = values.begin(); p != values.end(); ++p) {
        cout << *p << " ";
    }
    return 0;
}

insert()函数用法

#include <iostream>
#include <list>
#include <array>
using namespace std;
int main()
{
    std::list<int> values{ 1,2 };
    //第一种格式用法
    values.insert(values.begin() , 3);//{3,1,2}

    //第二种格式用法
    values.insert(values.end(), 2, 5);//{3,1,2,5,5}

    //第三种格式用法
    std::array<int, 3>test{ 7,8,9 };
    values.insert(values.end(), test.begin(), test.end());//{3,1,2,5,5,7,8,9}

    //第四种格式用法
    values.insert(values.end(), { 10,11 });//{3,1,2,5,5,7,8,9,10,11}

    for (auto p = values.begin(); p != values.end(); ++p)
    {
        cout << *p << " ";
    }
    return 0;
}

splice()函数用法

语法格式功能
void splice (iterator position, list& x);position 为迭代器,用于指明插入位置;x 为另一个 list 容器。 此格式的 splice() 方法的功能是,将 x 容器中存储的所有元素全部移动当前 list 容器中 position 指明的位置处。
void splice (iterator position, list& x, iterator i);position 为迭代器,用于指明插入位置;x 为另一个 list 容器;i 也是一个迭代器,用于指向 x 容器中某个元素。 此格式的 splice() 方法的功能是将 x 容器中 i 指向的元素移动到当前容器中 position 指明的位置处。
void splice (iterator position, list& x, iterator first, iterator last);position 为迭代器,用于指明插入位置;x 为另一个 list 容器;first 和 last 都是迭代器,[fist,last) 用于指定 x 容器中的某个区域。 此格式的 splice() 方法的功能是将 x 容器 [first, last) 范围内所有的元素移动到当前容器 position 指明的位置处。
#include <iostream>
#include <list>
using namespace std;
int main()
{
    //创建并初始化 2 个 list 容器
    list<int> mylist1{ 1,2,3,4 }, mylist2{10,20,30};
    list<int>::iterator it = ++mylist1.begin(); //指向 mylist1 容器中的元素 2
   
    //调用第一种语法格式
    mylist1.splice(it, mylist2); // mylist1: 1 10 20 30 2 3 4
                                 // mylist2:
                                 // it 迭代器仍然指向元素 2,只不过容器变为了 mylist1

    //调用第二种语法格式,将 it 指向的元素 2 移动到 mylist2.begin() 位置处
    mylist2.splice(mylist2.begin(), mylist1, it);   // mylist1: 1 10 20 30 3 4
                                                    // mylist2: 2
                                                    // it 仍然指向元素 2
   
    //调用第三种语法格式,将 [mylist1.begin(),mylist1.end())范围内的元素移动到 mylist.begin() 位置处                  
    mylist2.splice(mylist2.begin(), mylist1, mylist1.begin(), mylist1.end());//mylist1:
                                                                             //mylist2:1 10 20 30 3 4 2
   
    cout << "mylist1 包含 " << mylist1.size() << "个元素" << endl;
    cout << "mylist2 包含 " << mylist2.size() << "个元素" << endl;
    //输出 mylist2 容器中存储的数据
    cout << "mylist2:";
    for (auto iter = mylist2.begin(); iter != mylist2.end(); ++iter) {
        cout << *iter << " ";
    }
    return 0;
}

list 容器删除元素方法

成员函数功能
pop_front()删除位于 list 容器头部的一个元素。
pop_back()删除位于 list 容器尾部的一个元素。
erase()该成员函数既可以删除 list 容器中指定位置处的元素,也可以删除容器中某个区域内的多个元素。
iterator erase (iterator position);
iterator erase (iterator first, iterator last);(包括 first 指向的元素,但不包括 last 指向的元素)
clear()删除 list 容器存储的所有元素。
remove(val)删除容器中所有等于 val 的元素。
unique()删除容器中相邻的重复元素,只保留一份。
void unique()
void unique(BinaryPredicate)//传入一个二元谓词函数
remove_if()删除容器中满足条件的元素。
//删除 mylist 容器中能够使 lamba 表达式成立的所有元素。
mylist.remove_if([](int value) {return (value < 10); });

除此之外,还有forward_list容器,其底层实现和 list 容器一样,采用的也是链表结构,只不过 forward_list 使用的是单链表,而 list 使用的是双向链表。

forward_list 容器具有和 list 容器相同的特性,即擅长在序列的任何位置进行插入元素或删除元素的操作,但对于访问存储的元素,没有其它容器(如 array、vector)的效率高。

由于单链表没有双向链表那样灵活,因此相比 list 容器,forward_list 容器的功能受到了很多限制。比如,由于单链表只能从前向后遍历,而不支持反向遍历,因此 forward_list 容器只提供前向迭代器,而不是双向迭代器。这意味着,forward_list 容器不具有 rbegin()、rend() 之类的成员函数。

但是forward_list 容器底层使用单链表,存储相同个数的同类型元素,单链表耗用的内存空间更少,空间利用率更高,并且对于实现某些操作单链表的执行效率也更高。

使用方法与list容器类似(创建等)

forward_list 容器可用的成员函数

成员函数功能
before_begin()返回一个前向迭代器,其指向容器中第一个元素之前的位置。
begin()返回一个前向迭代器,其指向容器中第一个元素的位置。
end()返回一个前向迭代器,其指向容器中最后一个元素之后的位置。
cbefore_begin()和 before_begin() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改元素。
cbegin()和 begin() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改元素。
cend()和 end() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改元素。
empty()判断容器中是否有元素,若无元素,则返回 true;反之,返回 false。
max_size()返回容器所能包含元素个数的最大值。这通常是一个很大的值,一般是 232-1,所以我们很少会用到这个函数。
front()返回第一个元素的引用。
assign()用新元素替换容器中原有内容。
push_front()在容器头部插入一个元素。
emplace_front()在容器头部生成一个元素。该函数和 push_front() 的功能相同,但效率更高。
pop_front()删除容器头部的一个元素。
emplace_after()在指定位置之后插入一个新元素,并返回一个指向新元素的迭代器。和 insert_after() 的功能相同,但效率更高。
insert_after()在指定位置之后插入一个新元素,并返回一个指向新元素的迭代器。
erase_after()删除容器中某个指定位置或区域内的所有元素。
swap()交换两个容器中的元素,必须保证这两个容器中存储的元素类型是相同的。
resize()调整容器的大小。
clear()删除容器存储的所有元素。
splice_after()将某个 forward_list 容器中指定位置或区域内的元素插入到另一个容器的指定位置之后。
remove(val)删除容器中所有等于 val 的元素。
remove_if()删除容器中满足条件的元素。
unique()删除容器中相邻的重复元素,只保留一个。
merge()合并两个事先已排好序的 forward_list 容器,并且合并之后的 forward_list 容器依然是有序的。
sort()通过更改容器中元素的位置,将它们进行排序。
reverse()反转容器中元素的顺序。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值