C++ STL之list的使用及模拟实现

文章目录

  • 1. 介绍
  • 2. list类的使用
    • 2.1 list类对象的构造函数
    • 2.2 list类对象的容量操作
    • 2.3 list类对象的修改操作
    • 2.4 list类对象的访问及遍历操作
  • 3. list类的模拟实现


1. 介绍

英文解释:

在这里插入图片描述

也就是说:

  1. list是可以在常数范围内在任意位置进行插入和删除的序列式容器,并且该容器可以前后双向迭代。

  2. list的底层是双向链表结构,双向链表中每个元素存储在互不相关的独立节点中,在节点中通过指针指向其前一个元素和后一个元素。

  3. list与forward_list非常相似:最主要的不同在于forward_list是单链表,只能朝前迭代,已让其更简单高效。

  4. 与其他的序列式容器相比(array,vector,deque),list通常在任意位置进行插入、移除元素的执行效率更好。

  5. 与其他序列式容器相比,list和forward_list最大的缺陷是不支持任意位置的随机访问,比如:要访问list的第6个元素,必须从已知的位置(比如头部或者尾部)迭代到该位置,在这段位置上迭代需要线性的时间开销;list还需要一些额外的空间,以保存每个节点的相关联信息(对于存储类型较小元素的大list来说这可能是一个重要的因素)。

图示:

在这里插入图片描述

想要具体了解其底层数据结构可以参照:线性表之双向链表

2. list类的使用

template < class T, class Alloc = allocator<T> > class list;

list 是类模板。使用其定义变量时,首先需要实例化。

例如:

实例化类型解释
list整型容器,每个元素的类型为 int。
list<char*>char* 指针容器,每个元素的类型为 char*。
list<vector>list 类模板嵌套实例化的容器,元素类型为 vector。

2.1 list类对象的构造函数

(constructor)构造函数代码功能说明
explicit list (const allocator_type& alloc = allocator_type());(默认构造函数)构造一个空的容器,没有任何元素。
explicit list (size_type n, const value_type& val = value_type(), const allocator_type& alloc = allocator_type());(填充构造函数)构造一个具有 n 个元素的容器。每个元素都是 val 的副本。
template <class InputIterator>
list (InputIterator first, InputIterator last, const allocator_type& alloc = allocator_type());
(范围构造函数)构造一个与范围[first, last)中的元素数量相同的容器,每个元素都是从该范围中的相应元素构造而来,顺序相同。
list (const list& x);(拷贝构造函数)构造一个与 x 中的每个元素副本相同顺序的容器。

实例:

// constructing lists
#include <iostream>
#include <list>int main()
{// 按照上述描述的顺序使用的构造函数std::list<int> first;                                // empty list of intsstd::list<int> second(4, 100);                       // four ints with value 100std::list<int> third(second.begin(), second.end());  // iterating through secondstd::list<int> fourth(third);                       // a copy of third// the iterator constructor can also be used to construct from arrays:int myints[] = { 16,2,77,29 };std::list<int> fifth(myints, myints + sizeof(myints) / sizeof(int));std::cout << "The contents of fifth are: ";for (std::list<int>::iterator it = fifth.begin(); it != fifth.end(); it++)std::cout << *it << ' ';std::cout << '\n';return 0;
}

输出结果:

在这里插入图片描述

2.2 list类对象的容量操作

函数名称代码功能说明
emptybool empty() const;返回 list 容器是否为空(即其大小是否为0)。
sizesize_type size() const;返回 list 容器中元素的个数。
max_sizesize_type max_size() const;返回 list 容器中可以容纳的最大元素的数量。

2.3 list类对象的修改操作

函数名称代码功能说明
assigntemplate <class InputIterator>
void assign (InputIterator first, InputIterator last);
void assign (size_type n, const value_type& val);
对 list 容器进行赋值,替换其当前内容,并相应地修改其大小。
push_frontvoid push_front (const value_type& val);在 list 容器开头插入一个新元素 val。
pop_frontvoid pop_front();删除 list 容器中第一个元素。
push_backvoid push_back (const value_type& val);在 list 容器最后插入一个新元素 val。
pop_backvoid pop_back();删除 list 容器中最后一个元素。
insertiterator insert (iterator position, const value_type& val);
void insert (iterator position, size_type n, const value_type& val);
template <class InputIterator>
void insert (iterator position, InputIterator first, InputIterator last);
在指定位置 position 之前插入新元素 val、n 个 val或者迭代器区间[first, last)范围的元素。
eraseiterator erase (iterator position);
iterator erase (iterator first, iterator last);
删除 position 位置的元素或者迭代器区间[first, last)范围的元素。
swapvoid swap (list& x);与另一个相同类型的 list 容器 x 交换内容。存在一个同名的非成员函数 swap,重载该算法的意义是优化交换时间。
resizevoid resize (size_type n, value_type val = value_type());改变容器的大小,使其包含 n 个元素。如果 n 小于当前容器的大小,则内容将被缩减为其前 n 个元素,并移除超出范围的元素。如果 n 大于当前容器的大小,则通过在末尾插入所需数量的元素来扩展内容,使其大小达到 n。如果指定了 val,则新元素将被初始化为 val 的副本;否则,它们将进行值初始化。
clearvoid clear();从 list 容器中移除所有元素,使容器的大小变为0。

2.4 list类对象的访问及遍历操作

函数名称代码功能说明
frontreference front();
const_reference front() const;
返回 list 容器中第一个元素的引用。
backreference back();
const_reference back() const;
返回 list 容器中最后一个元素的引用。

遍历操作

#include <iostream>
#include <list>int main()
{std::list<int> lt(10, 100);// 1. 迭代器遍历for (std::list<int>::iterator it = lt.begin(); it != lt.end(); ++it)std::cout << *it << " ";std::cout << '\n';// 2. 范围for遍历for (auto e : lt)std::cout << e << " ";std::cout << '\n';return 0;
}

运行结果:

在这里插入图片描述

解释

  1. 迭代器遍历:
  • 首先,通过lt.begin()获取列表的起始迭代器,lt.end()获取列表的结束迭代器。
  • 使用std::list<int>::iterator it定义一个迭代器变量,并将其初始化为列表的起始迭代器。
  • 使用迭代器变量it进行循环迭代,从列表的起始位置迭代到结束位置(不包括结束位置)。
  • 在循环中,通过*it访问当前迭代器指向的元素,并输出到标准输出流std::cout中。
  1. 范围for循环遍历:
  • 使用auto关键字和范围for循环语法,遍历列表lt中的每个元素。
  • 在每次迭代中,将当前元素赋值给变量e
  • 在循环体内,输出变量e的值到标准输出流std::cout中。

3. list类的模拟实现

#pragma once
#include<iostream>
using namespace std;namespace my_list
{   // List的节点类template<class T>struct ListNode{ListNode(const T& val = T()):_pPre(nullptr),_pNext(nullptr),_val(val){}ListNode<T>* _pPre;ListNode<T>* _pNext;T _val;};//List的迭代器类template<class T, class Ref, class Ptr>class List_iterator{typedef ListNode<T>* PNode;typedef List_iterator<T, Ref, Ptr> Self;public:List_iterator(PNode pNode = nullptr){_pNode = pNode;}List_iterator(const Self& l){_pNode = l._pNode;}Ref operator*(){return _pNode->_val;}Ptr operator->(){return &_pNode->_val;}Self& operator++(){_pNode = _pNode->_pNext;return *this;}Self operator++(int){Self tmp(*this);_pNode = _pNode->_pNext;return tmp;}Self& operator--(){_pNode = _pNode->_pPre;return *this;}Self operator--(int){Self tmp(*this);_pNode = _pNode->_pPre;return tmp;}bool operator!=(const Self& l){return _pNode != l._pNode;}bool operator==(const Self& l){return _pNode == l._pNode;}PNode GetNode(){return _pNode;}private:PNode _pNode;};// 反向迭代器——对正向迭代器的接口进行包装template<class Iterator, class Ref, class Ptr>struct Reverse_iterator{Iterator _it;typedef Reverse_iterator<Iterator, Ref, Ptr> Self;Reverse_iterator() {}Reverse_iterator(Iterator it): _it(it){}Ref operator*(){Iterator tmp(_it);--tmp;return *tmp;}Ptr operator->(){return &(operator*());}Self& operator++(){--_it;return *this;}Self operator++(int){Self tmp(*this);--_it;return tmp;}Self& operator--() {++_it;return *this;}Self operator--(int){Self tmp(*this);++_it;return tmp;}bool operator!=(const Self& s){return _it != s._it;}bool operator==(const Self& s){return _it == s._it;}};//list类template<class T>class list{typedef ListNode<T> Node;typedef Node* PNode;public:typedef List_iterator<T, T&, T*> iterator;typedef List_iterator<T, const T&, const T&> const_iterator;typedef Reverse_iterator<iterator, T&, T*> reverse_iterator;typedef Reverse_iterator<const_iterator, const T&, const T*> const_reverse_iterator;public:///// List Iteratoriterator begin(){return _pHead->_pNext;}iterator end(){return _pHead;}const_iterator begin() const{return const_iterator(_pHead->_pNext);}const_iterator end() const{return const_iterator(_pHead);}reverse_iterator rbegin(){return reverse_iterator(end());}reverse_iterator rend(){return reverse_iterator(begin());}const_reverse_iterator rbegin() const{return const_reverse_iterator(end());}const_reverse_iterator rend() const{return const_reverse_iterator(begin());}///// List 构造/赋值list(){CreateHead();}list(int n, const T& value = T()){CreateHead();while (n--){push_back(value);}_size = n;}list(int n, T& value = T()){CreateHead();while (n--){push_back(value);}_size = n;}template <class Iterator>list(Iterator first, Iterator last){CreateHead();while (first != last){push_back(*first);first++;_size++;}}list(const list<T>& l){CreateHead();for (auto it : l){push_back(it);_size++;}}void swap(list<T>& l){std::swap(this->_pHead, l._pHead);std::swap(this->_size, l._size);}list<T>& operator=(list<T> l){swap(l);return *this;}~list(){clear();delete _pHead;_pHead = nullptr;}///// List Capacitysize_t size()const{return _size;}bool empty()const{return _size == 0;}// List AccessT& front(){assert(!empty());return _pHead->_pNext->_val;}const T& front()const{assert(!empty());return _pHead->_pNext->_val;}T& back(){assert(!empty());return _pHead->_pPre->_val;}const T& back()const{assert(!empty());return _pHead->_pPre->_val;}// List Modifyvoid push_back(const T& val){insert(end(), val);}void pop_back(){erase(--end());}void push_front(const T& val){insert(begin(), val);}void pop_front(){erase(begin());}// 在pos位置前插入值为val的节点iterator insert(iterator pos, const T& val){PNode tmp = new Node(val);PNode cur = pos.GetNode();PNode pre = cur->_pPre;tmp->_pNext = cur;tmp->_pPre = pre;pre->_pNext = tmp;cur->_pPre = tmp;_size++;return tmp;}// 删除pos位置的节点,返回该节点的下一个位置iterator erase(iterator pos){PNode cur = pos.GetNode();PNode next = cur->_pNext;PNode pre = cur->_pPre;delete cur;pre->_pNext = next;next->_pPre = pre;_size--;return next;}void clear(){iterator it = begin();while (it != end()){it = erase(it);}}private:// 创建头结点void CreateHead(){_pHead = new Node;_pHead->_pNext = _pHead->_pPre = _pHead;}PNode _pHead;size_t _size = 0;};
};

注意

这里实现的反向迭代器类模板同样也可以适配到vector类和string类中。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/244802.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

单点登陆(SSO)基于CAS实现前后端分离的SSO系统开发「IDP发起」

关于其他前端常见登录实现单点登录方案&#xff0c;请见「前端常见登录实现方案 单点登录方案 」 前沿 单点登录&#xff08;SSO&#xff09;&#xff0c;英文全称为 Single Sign On。 SSO 是指在多个应用系统中&#xff0c;用户只需要登录一次&#xff0c;就可以访问所有相互…

macbookpro可以玩什么游戏

最近几年苹果在游戏领域的动作越来越频繁&#xff0c;在当地时间6月6日举行的的WWDC 2023上还请来了小岛秀夫和他的《死亡搁浅导演剪辑版》到现场为苹果电脑站台。事实上&#xff0c;在不久的将来&#xff0c;我们还真有机会看到越来越多Windows上的大作运行在搭载苹果M系列芯片…

旅游项目day14

其他模块数据初始化 搜索实现 请求一样&#xff0c;但是参数不一样&#xff0c;根据type划分。 后台需要提供一个搜索接口。 请求分发器&#xff1a; 全部搜索 目的地搜索 精确搜索、无高亮展示 攻略搜索 全文搜索、高亮显示、分页 游记搜搜 用户搜索 丝袜哥

小程序使用echarts图表-雷达图

本文介绍下小程序中如何使用echarts 如果是通过npm安装&#xff0c;这样是全部安装的&#xff0c;体积有点大 我这边是使用echarts中的一个组件来实现的&#xff0c;下边是具体流程&#xff0c;实际效果是没有外边的红色边框的&#xff0c;加红色边框的效果是这篇说明 1.echa…

什么是网络?

你是一台电脑&#xff0c;你的名字叫 A 很久很久之前&#xff0c;你不与任何其他电脑相连接&#xff0c;孤苦伶仃。 直到有一天&#xff0c;你希望与另一台电脑 B 建立通信&#xff0c;于是你们各开了一个网口&#xff0c;用一根网线连接了起来。 用一根网线连接起来怎么就能&…

【QT+QGIS跨平台编译】之七:【libjpeg+Qt跨平台编译】(一套代码、一套框架,跨平台编译)

文章目录 一、libjpeg介绍二、文件下载三、文件分析四、pro文件五、编译实践一、libjpeg介绍 libjpeg是一个广泛使用的jpeg图像压缩和解压的函数库,采用 C 语言开发。 2013年1月,Independent JPEG Group发布了版本9,对新引入的无损编码模式进行了改进。2022年1月,发布了版…

html5实现好看的年会邀请函源码模板

文章目录 1.设计来源1.1 邀请函主界面1.2 诚挚邀请界面1.3 关于我们界面1.4 董事长致词界面1.5 公司合作方界面1.6 活动流程界面1.7 加盟支持界面1.8 加盟流程界面1.9 加盟申请界面1.10 活动信息界面 2.效果和源码2.1 动态效果2.2 源码目录结构 源码下载 作者&#xff1a;xcLei…

《PCI Express体系结构导读》随记 —— 第I篇 第3章 PCI总线的数据交换(1)

前言中曾提到&#xff1a;本章详细阐述了PCI总线的数据传送方式&#xff0c;与Cache相关的内容和预读机制是本章的重点。 PCI Agent设备之间、以及HOST处理器和PCI Agent设备之间可以使用存储器读写和I/O读写等总线事务进行数据传送。在大多数情况下&#xff0c;PCI桥不直接与P…

uniapp组件库Modal 模态框 的使用方法

目录 #平台差异说明 #基本使用 #传入富文本内容 #异步关闭 #点击遮罩关闭 #控制模态框宽度 #自定义样式 #缩放效果 #API #Props #Event #Method #Slots 弹出模态框&#xff0c;常用于消息提示、消息确认、在当前页面内完成特定的交互操作。 #平台差异说明 AppH5微…

Transformer and Pretrain Language Models3-1

content transformer attention mechanism transformer structure​​​​​​​ pretrained language models language modeling pre-trained langue models(PLMs&#xff09; fine-tuning approaches PLMs after BERT applications of masked LM frontiers of PLMs …

高校寝室卫生检查系统UML建模——活动图

学生查看历史的通知公告学生投诉寝室卫生检查 学生查看其他寝室的卫生情况 发起报修请求

Django笔记(六):DRF框架

首 前后端分离是互联网应用开发的标准使用方式&#xff0c;让前后端通过接口实现解耦&#xff0c;能够更好的进行开发和维护。 RESTful接口常见规范 在接口设计中&#xff0c;大家遵循一定的规范可以减少很多不必要的麻烦&#xff0c;例如url应有一定辨识度&#xff0c;可以…

单元测试、模块测试、web接口测试

单元测试与模块测试 什么是“单元测试”、“模块测试”&#xff1f; 然而在功能的实现代码中并没有“单元”&#xff0c;也没有“模块”&#xff1b;只有函数、类和方法。先来分别看看它们 的定义&#xff1a; 单元测试&#xff08;Unit testing&#xff09;&#xff0c;是指…

Dify学习笔记-应用发布(四)

1、发布为公开 Web 站点 使用 Dify 创建 AI 应用的一个好处在于&#xff0c;你可以在几分钟内就发布一个可供用户使用的 Web 应用&#xff0c;该应用将根据你的 Prompt 编排工作。 如果你使用的是自部署的开源版&#xff0c;该应用将运行在你的服务器上 如果你使用的是云服务&…

Netty Reactor 模式解析

目录 Reactor 模式 具体流程 配置 初始化 NioEventLoop ServerBootstrapAcceptor 分发 Reactor 模式 在刚学 Netty 的时候&#xff0c;我们肯定都很熟悉下面这张图&#xff0c;它就是单Reactor多线程模型。 在写Netty 服务端代码的时候&#xff0c;下面…

【算法练习】leetcode算法题合集之栈和队列篇

普通栈 LeetCode20 有效的括号 LeetCode20 有效的括号 定义一个辅助map&#xff0c;判断字符串的字符是否在]})中。一旦是右括号就要弹出元素&#xff0c;判断匹配。 class Solution {public boolean isValid(String s) {if (s.length() % 2 1) {return false;}Map<Chara…

探索 XMLHttpRequest:网页与服务器的异步通信之道(上)

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

多场景建模:阿里多场景多任务元学习方法M2M

multi-scenario multi-task meta learning approach (M2M) 背景 广告领域大部分是针对用户建模的&#xff0c;像点击率预估&#xff0c;很少有针对广告主需求建模&#xff08;广告消耗预估、活跃率/流失率预估、广告曝光量预估&#xff09;&#xff0c;广告的类型较多&#x…

k8s从初识到上天系列第一篇:初识kubernetes

&#x1f609;&#x1f609; 欢迎加入我们的学习交流群呀&#xff01; ✅✅1&#xff1a;这是孙哥suns给大家的福利&#xff01; ✨✨2&#xff1a;我们免费分享Netty、Dubbo、k8s、Mybatis、Spring、SpringSecurity、Docker、Grpc、各种MQ、Rpc、SpringCloud等等很多应用和源码…

CSS之高度塌陷和外边距塌陷

目录 1.高度塌陷&#xff08;原因&#xff0c;如何解决&#xff09; 【概念介绍】 【解决办法】 【概念介绍-BFC】 【拓展-BFC的触发条件】 2.外边距塌陷 &#xff08;原因&#xff0c;如何解决&#xff09; 【概念介绍】 【两种情况】 1.相邻块元素 2.嵌套块元素 【…