C++容器:list(双向链表)

一丶list介绍

C++中的list容器底层确实是以双向链表的形式实现的

  list容器是C++标准模板库(STL)中的一部分,它提供了对列表数据结构的实现。

  • 双向链表结构list容器的每个元素都是通过指针链接在一起的,每个元素都包含指向前一个和后一个元素的指针。这种双向链表的结构使得在list容器中插入和删除元素时无需移动其他元素,因此这些操作的时间复杂度为O(1)。
  • 内存分配:由于list容器基于双向链表,其元素可以分散存储在内存中,不需要像数组或vector那样连续分配内存空间。这使得list在内存使用上更加灵活,特别适合于需要频繁插入和删除操作的场景。
  • 迭代器稳定性list容器的迭代器在插入和删除操作中保持稳定性,即使在进行这些操作时,指向其他元素的迭代器也不会失效。

二丶list的使用

       C++中list容器提供了多种用于操作列表的函数,使得对元素的插入、删除和访问变得灵活而高效。以下是一些常用的list容器函数:

  • push_back():在列表的尾部插入一个新元素。
  • push_front():在列表的头部插入一个新元素。
  • pop_back():删除列表尾部的元素。
  • pop_front():删除列表头部的元素。
  • size():返回列表中元素的个数。
  • empty():判断列表是否为空,如果为空则返回true,否则返回false。
  • clear():清除列表中的所有元素。
  • erase():删除列表中的一个或多个元素。
  • remove():移除列表中所有等于特定值的元素。
  • sort():对列表中的元素进行排序。
  • reverse():反转列表中元素的顺序。
#include<iostream>
#include<list>
using namespace std;
template<class T>
void PrintList(const list<T>& l)  //打印函数
{
	auto it = l.begin();
	while (it != l.end())
	{
		cout << *it << " ";
		it++;
	}
	cout << endl;
}
void ListTest()
{
	list<int> l;    //空
	l.push_back(1);   //尾插
	l.push_back(2);
	l.push_back(3);
	PrintList(l);


	list<int> _l(l);  //构造函数重载
	PrintList(_l);
	_l.clear();


	l.push_front(4);  //头插
	l.push_front(5);
	l.push_front(6);
	PrintList(l);


	l.sort();   //排序
	PrintList(l);


	l.pop_back();  //尾删
	l.pop_back();
	PrintList(l);


	l.pop_front();  //头删
	l.pop_front();
	PrintList(l);
}
int main()
{
	ListTest();
	return 0;
}

 

        这些用法其实很简单,主要还是要学会灵活使用。这里要注意一下sort函数,默认是升序函数

底层使用的一般是快速排序算法,然后sort重载了另一个函数,这里的Compare 是用来控制升序或者降序的,称为仿函数

std::list::sort

(1)	
  void sort();

(2)	
template <class Compare>
  void sort (Compare comp);

      如下,MyCompare 只重载了运算符(),然后我们自己写了一个sort,调用的是std::sort,std::sort(迭代器1,迭代器2,仿函数),不传仿函数就调用另一个重载函数将迭代器范围内升序排序

struct MyCompare {
    bool operator()(int a, int b) {
        return a > b; // 降序排列
    }
};

template <class ForwardIt, class Compare>
void sort(ForwardIt first, ForwardIt last, Compare comp) {
    // ... 其他代码 ...

    while (first != last) {
        // ... 其他代码 ...

        // 使用comp比较函数对象比较两个元素
        if (comp(*i, *j)) {
            // ... 其他代码 ...
        } else {
            // ... 其他代码 ...
        }

        // ... 其他代码 ...
    }

    // ... 其他代码 ...
}

三丶与vector比较

  1. 内存分配:

    • vector:在内存中连续存储元素,当需要添加或删除元素时,可能会导致整个容器的内存重新分配。
    • list:在内存中非连续存储元素,每个元素都是一个单独的节点,包含数据和指向前后节点的指针。因此,添加或删除元素时,只需要修改相邻节点的指针,不会影响其他元素的内存位置。
  2. 访问方式:

    • vector:支持随机访问,可以直接通过索引访问任何元素,访问速度快。
    • list:不支持随机访问,只能通过迭代器进行顺序访问。
  3. 插入和删除操作:

    • vector:在尾部插入和删除元素的效率高,因为不需要移动其他元素;而在中间或头部插入和删除元素效率较低,因为需要移动其他元素。
    • list:在任何位置插入和删除元素的效率都较高,因为只需要修改相邻节点的指针。
  4. 容量和大小:

    • vector:有固定的容量,可以容纳的元素数量有限。当超过容量时,会自动扩容,可能会引起内存重新分配和元素移动。
    • list:没有固定容量的概念,只要内存允许,可以不断地添加新元素。
  5. 性能:

    • vector:在内存中连续存储,有利于缓存的利用,因此访问速度较快。但在插入和删除操作时可能需要移动大量元素,效率较低。
    • list:在内存中非连续存储,不利于缓存的利用,访问速度较慢。但在插入和删除操作时只需要修改指针,效率较高。

    总之,vectorlist各有优缺点,具体使用哪个容器取决于具体的应用场景和需求。如果需要频繁访问元素,可以选择vector;如果需要频繁插入和删除元素,可以选择list

  • 10
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值