由三个类构建而成: 节点类:每个节点必须的三部分(指向前一个节点的指针、指向后一个节点的指针、当前节点存储的数据) 迭代器类:此时的迭代器为双向迭代器,比较特殊,需要对其进行封装,如 it++ 并非使迭代器单纯向后移动...,而是让其指向下一个节点 链表类:实现链表各项功能的类,为主要部分 1.1、节点类 节点类在设计时,需要确定三个成员和构造函数,用来生成类 //节点类 template struct...首先需要先构建出迭代器对象 当使用前置 ++ 时,会去调用迭代器类中的 operator++() 重载函数,将迭代器指向当前节点的下一个节点(_node = _node->_next) 使用后置 --...,可以使迭代器类中的模板参数变为对应类型 这正是 泛型编程 思想之一 3.4、其他功能 关于迭代器类中的其他功能: 解引用 operator*() 取当前节点指针 operator->() 迭代器比较...迭代器.operator->()->成员 直接优化为 迭代器->成员 ---- 4、容量相关 list 中的容量访问有:判空和大小 实现判空:判断当前的 begin() 与 end() 是否相同 统计大小
在实际开发中,双向链表是一种具有灵活插入和删除操作的数据结构,尤其适合那些需要频繁操作非连续内存数据的场景。本文将通过一个手动实现的双向链表类 list 来讲解双向链表的底层结构和实现原理。 1...._node; } }; 迭代器主要提供以下功能: operator* 和 operator->:实现解引用操作,返回当前节点的数据。...operator++ 和 operator–:支持迭代器的前进和后退。 operator!= 和 operator==:支持迭代器的比较,判断是否到达链表末尾。...迭代器操作与遍历链表 我们为链表提供了 begin() 和 end() 函数,用于获取链表的起始和结束迭代器。通过这些迭代器,用户可以遍历整个链表,访问每个元素。...总结 本文从底层实现的角度详细讲解了如何手动实现一个双向链表容器 list。我们设计了双向链表的数据结构,通过节点、迭代器、基本的插入、删除操作,最终实现了一个功能完整的链表容器。
双向迭代器(Bidirectional Iterator) 双向迭代器允许在迭代时向前和向后移动,可以在遍历过程中回退。这种迭代器常用于需要访问前一个元素的场景。...vector底层示意图: 但是由于list在底层实现是带头双向循环链表的形式,这种形式下对象的指针就无法承担起迭代器的功能,因为它在物理内存中 ++ / -- 的结果是未知的内存块,我们想要的是对迭代器...分析list的组成结构 我们在之前C语言阶段就已经一起模拟实现过带头双向循环链表,可以知道C语言中带头双向循环链表的结构是由两部分组成的,一部分是链表结点,一部分是链表本身.因此我们至少要封装两个类模板才能够组成带头双向循环链表...指针,然后再返回*this当前的值 _node = _node->_next; return tmp; } 实现前置operator--重载函数 迭代器前置--的功能是使迭代器指向上一个链表结点...list类end()函数 实现普通list类的end()函数 end()函数就是要返回链表最后一个有效结点后一个结点的迭代器,实际上就是头结点的指针,因为迭代器的底层实现是Node*,所以这里直接返回
find 函数只查找第一个匹配项,如果目标元素有多个相同值,则只返回第一个找到的迭代器。 如果需要查找容器中某个元素是否存在,可以通过比较返回值是否等于 end() 来判断。...std::list 是一种双向链表容器,支持常数时间的插入和删除操作,而 splice 函数则提供了一种高效的方法来在两个链表之间移动元素,而不需要实际的复制或重新分配内存。...使用场景:需要移除第一个元素时使用。 clear(): 功能:清空整个链表,移除所有元素。 使用场景:当需要重新初始化链表时非常有用。 2....使用场景:从另一个容器中取一段元素来重新填充当前链表。 swap(list& other): 功能:交换当前链表和另一个链表的内容。...end(): 功能:返回指向链表最后一个元素之后的迭代器。 使用场景:用于表示链表遍历结束的位置。 rbegin(): 功能:返回指向链表最后一个元素的反向迭代器。
const迭代器` `合并两种迭代器` 1.List介绍 list是可以在常数范围内在任意位置进行插入和删除的序列式容器,并且该容器可以前后双向迭代 list的底层是双向链表结构,双向链表中每个元素存储在互不相关的独立节点中...其他构造函数则根据是否带有explicit关键字来决定是否能用于隐式转换或复制初始化 迭代器 迭代器用来遍历链表,下面是迭代器的简单使用 list lt = { 10,20,30,40,50...我这里的指针,只能是Node*,Node*++不会加到下一个节点,这里的++需要我们自己重载实现,解引用也取不到当前节点的位置,这些函数都需要我们自己重载实现,所以,我们需要对迭代器进行封装 template...const迭代器 我们上面写的迭代器对于const对象是无法编译成功的,const不能调用非const成员函数 对于const类迭代器,我们需要在list类里面重新增加重载: typedef ConstListIterator...省略其他代码 ... }; list类中的其他成员函数像begin、end需要按照是否接收常量类型来适配这两种迭代器。
不过今天学习的list其实是一个带头双向链表。 言归正传,让我们看一下list的特性。 一、list的特性 这里我还是推荐去cplusplus上阅读英文原文档。...因为list的底层结构为带头结点的双向循环链表,因此在list中进行插入时是不会导致list的迭代器失效的,只有在删除时才会失效,并且失效的只是指向被删除节点的迭代器,其他迭代器不会受到影响。...= end()) { it = erase(it); } _size = 0; } 五、list的迭代器 list的迭代器我们要实现的主要就是他的++与--问题,而++就是返回当前位置的...这个类包含一个成员变量_node,它是一个指向list_node对象的指针,用于存储当前迭代器所指向的节点。这里的Ref与Ptr主要用于分辨const与非const....删 除时,当前迭代器需要重新赋值否则会失效 插入元素不会导致迭代器失效, 删除元素时,只会导致当前迭代
前言 std::list容器,顾名思义,实现了双向链表的数据结构。...⚽一、list简介 list容器,在C++标准模板库(STL)中,是一个非常重要的数据结构,它基于双向链表实现,提供了灵活的元素管理和操作功能。...// 直接使用初始化列表 ⚽三、list的迭代器 在C++中,std::list的迭代器提供了对链表元素进行遍历的能力,但由于std::list是双向链表,其迭代器是双向迭代器,不支持随机访问。...递减(--it):将迭代器向后移动到前一个元素。 解引用(\*it):获取迭代器当前指向的元素的值。 比较(it1 == it2、it1 != it2):比较两个迭代器是否相等或不相等。...myList中当前元素的拷贝(对于基本数据类型如int,这是通过值传递实现的)。
list介绍 列表是序列容器,允许在序列中的任何位置进行恒定时间插入和擦除操作,以及双向迭代。该容器用双向链表实现。...因为list的底层结构是双向带头循环链表,所以在list中进行insert操作的时候不会导致迭代器失效,只有在删除的时候才会失效,而且失效的知识指向被删除节点的迭代器,其他迭代器不会受影响。...reverse_iterator 功能:反向迭代器,允许从容器的末尾向前遍历元素。 适用性:提供双向或随机访问迭代器的容器。...list的排序 list为双向链表,std::algorithm::sort()排序要求的是随机迭代器,而list为双向迭代器,所以无法直接使用算法库的sort()进行排序。...这种写法展示了运算符重载的具体调用过程。 模拟实现list框架 整体模拟实现list的框架如图,将迭代器与节点包装成类模板进行使用:
大家好,又见面了,我是你们的朋友全栈君。 C++ 迭代器(Iterator) 1.1 定义 迭代器是一种检查容器内元素并遍历元素的数据类型。...对循环控制变量 i,要养成写++i、不写i++的习惯。 1.4 迭代器的功能分类 不同容器的迭代器,其功能强弱有所不同。容器的迭代器的功能强弱,决定了该容器是否支持 STL 中的某种算法。...输出迭代器只支持一遍算法,同一输出迭代器不能两次遍历一个序列 正向 组合输入迭代器和输出迭代器的功能,并保留在容器中的位置 双向 组合正向迭代器和逆向迭代器的功能,支持多遍算法 随机访问 组合双向迭代器的功能与直接访问容器中任何元素的功能...链表式容器(如list) (1)删除当前的iterator,仅仅会使当前的iterator失效,只要在erase 时,递增当前 iterator erase(iter++)或者 利用 erase 返回的有效迭代器...这是因为list之类的容器,使用了链表来实现,插入、删除一个结点不会对其他结点造成影响。
⭐list模拟实现 list的底层是双向链表结构,包含有一个哨兵节点。...模拟实现list,要实现下列三个类: ①list节点类 ②迭代器的类 ③list主要功能的类(size(),empty()...)...模拟实现list的类的基本功能(增删等操作)要建立在迭代器类和节点类均已实现好的情况下才得以完成。...,双向链表可以向前移动,所以需要重载,如果是forward_list就不需要重载-- 迭代器需要进行是否相等的比较,因此还需要重载operator==()与operator!..._node; } 这个比较的就是两个迭代器中指向的节点的地址是否相等,从而可以判断迭代器是否指向了end() 。
LinkedHashMap的实现: 对于LinkedHashMap而言,它继承与HashMap、底层使用哈希表与双向链表来保存所有元素。...K, V> 1) 成员变量: LinkedHashMap采用的hash算法和HashMap相同,但是它重新定义了数组中保存的元素Entry,该Entry除了保存当前对象的引用外,还保存了其上一个元素...元素继承HashMap的Entry,提供了双向链表的功能。...在上述HashMap的构造器中,最后会调用init()方法,进行相关的初始化,这个方法在HashMap的实现中并无意义,只是提供给子类实现相关的初始化调用。...*这里从写了父类HashMap中的该方法,是因为考虑到,LinkedHashMap拥有的双链表,在这里Override是为了提高迭代的效率。
一、list的数据结构和类实现需求 ✨1.1 数据结构 在 list 的实现中,底层是通过双向链表结构来存储数据。双向链表中的每个节点不仅包含数据,还包含指向前一个节点和后一个节点的两个指针。...每个元素(节点)包含数据和指向下一个(以及前一个,对于双向链表)节点的指针。因此,std::list的迭代器需要包含更多信息,通常是一个指向当前节点的指针。...std::list的迭代器在插入或删除节点时通常不会失效(除非删除的是迭代器当前指向的节点),因为链表操作不需要移动其他元素。...而 list 的底层是双向链表,迭代器不仅需要访问链表节点的值,还需要操作链表的前驱和后继节点(即 _prev 和 _next 指针)。...然而,在这个实现中,我们假设调用者知道他们是否在删除链表的最后一个节点,并相应地处理返回的迭代器。
子类可以重新定义基类的虚函数,这叫做复写 子类可以自主选择是否提供一份属于自己的个性化虚函数实现 说说虚函数的简单实现 带有虚函数的类,编译器会为其分配一个虚函数表,里面会记录的是虚函数的地址,当此类被继承的时候...,这样也许会让你的影响更加深刻 如果是空的vector容器,由于没有元素的空间分配,所以此时的first,last,end都是null,通过这样的三个迭代器,可以比较轻松的实现首尾表示,大小,容器判断等功能...比如对某些数据的权限设置为私有的,则不能被外界访问,不同对内部数据提供不同级别的保护,防止程序中无关的部分意外的改变或者错误的使用了对象的私有部分 继承:它可以使用现有类的所有功能,无需重新编写原来的类的情况下对这些功能进行扩展...如果cache满了,则将链表最后一个节点删除即可 get(key):如果key在hashmap存在,则将对应的节点放到链表头部,并返回对应的value值 此处实现采用双向链表+Map方式进行实现,为什么采用双向链表呢...,因为如果为单链表,我删除一个元素需要从头部查找,时间复杂度为O(N),而使用双向链表只需要改变前驱的指针指向就可,这样只需要O(1)即可。
接下来我们来讲讲如何实现一个list 我们对链表肯定也是相当的熟悉,双向链表的结构就是两个指针,一个存放数据的成员,一个指针指向的是前一个节点,另一个指针指向的是下一个节点,我们来看看底层:..._node; } 注意:这里我们还需要一个构造函数可以构造一个迭代器的函数 list_iterator(node* n) :_node(n) {} 用当前节点来构造一个迭代器 3.反向迭代器实现 基于正向迭代器实现的反向迭代器...assign函数需要重新定义一个模版,因为不妨有string或者其他的自定义类型的迭代器需要传递,如果我们传递就是当前类的迭代器,那么就只能传递当前类的迭代器,这样就一棒子打死了。...4.3指定位置的插入 注意:指定位置的删除返回的是迭代器,插入节点的迭代器,,这里我们来考虑一下会不会出现迭代器失效的情况,我们插入一个新节点,是我们重新开辟的节点,返回的也是重新开辟的节点的迭代器,所以这里不存在迭代器失效的问题...= new node; _head->_next = _head; _head->_prev = _head; } }; } 总结 在本文中,我们深入探讨了C++中std::list的使用以及如何通过模拟实现基本的链表功能
本篇是STL库专题之list,本质是一个双向带头循环链表,提供了双向迭代器,可以向前和向后遍历链表。这在一些需要双向操作的算法中非常有用,比如实现回文检查等 1.为什么要学习list?...list 是 C++ 标准模板库中的一个容器,它实现了双向链表的数据结构。双向链表由一系列节点组成,每个节点包含一个数据元素和两个指针,分别指向前一个节点和后一个节点。...这使得它在需要频繁插入和删除元素的场景下表现出色,比如实现一个任务调度器,需要不断地添加新任务、移除已完成的任务 list 也是一种很常用的容器,对于链表的处理提供了极大的便利性 list 的主要特征可总结为...: 3.list类对象的容量操作 因为是链表,所以对容量的操作并不需要太多,大部分是通过创建节点并链接实现 函数名 功能说明 empty 检测list是否为空,是返回true,否则返回false size...list 的迭代器和 vector 的基本使用方法一致,但是底层的迭代器结构不同,在 list 底层结构剖析有详细的解答 传送门: 函数名 功能说明 begin + end 迭代器:begin
放在专栏【C++知识总结】,会持续更新,期待支持 1、list数据结构 list是一个带有头节点的双向链表,list主要是由以下部分组成:list节点类、迭代器类、list本身 1.1、list节点类...同时由于list为双向的链表结构,因此我们还要对--进行重载,使其--指向当前节点的前一个节点。 如下所示,为迭代器类设计的基本结构: (补充:这里==与!...2、模拟实现 上面的节点类我们只需要提供上述的一个构造函数即可,这里我们从迭代器开始,一步步模拟实现。...++操作可以实现迭代器从当前节点指向下一个节点,--操作可以实现从当前节点指向前一个节点。...= 迭代器在进行比较时,实际上比较的是两个迭代器指向的位置是否为同一个位置,而不是比较迭代器的大小,这是错误的。而判断是否指向同一个位置,只需要判断其指向的pnode是否相同即可。
2. list的底层是双向链表结构,双向链表中每个元素存储在互不相关的独立节点中,在节点中通过指针指向其前一个元素和后一个元素。...因为list的底层结构为带头结点的双向循环链表,因此在list中进行插入时是不会导致list的迭代器失效的,只有在删除时才会失效,并且失效的只是指向被删除节点的迭代器,其他迭代器不会受到影响。...--就是正向迭代器的++,因此反向迭代器的实现可以借助正向迭代器,即:反向迭代器内部可以包含一个正向迭代器,对正向迭代器的接口进行包装即可。...节点指针)进行封装 迭 代 器 失 效 在插入元素时,要给所有的迭代器重新赋值,因为插入元素有可能会导致重新扩容,致使原来迭代器失效,删除时,当前迭代器需要重新赋值否则会失效 插入元素不会导致迭代器失效...,删除元素时,只会导致当前迭代器失效,其他迭代器不受影响 使 用 场 景 需要高效存储,支持随机访问,不关心插入删除效率 大量插入和删除操作,不关心随机访问
C++STL中list底层的结构就是采用带头双向循环链表(对list的理解需要建立在对数据结构有一定基础上,对于链表不了解的读者可以先移步学习链表。)...这里我们需要在拓展补充一下迭代器的相关概念 基于功能上是正向还是反向遍历,迭代器可以分为正向迭代器iterator与反向迭代器reverse_iterator,以及支持const对象的迭代器。...基于底层结构的不同,实现出来的迭代器又有性质上的不同,可以分为单向、双向、随机迭代器(STL底层还抽象出一个最小单位的输入迭代器,我们使用的只有上诉三个迭代器,这个最小单位可以不考虑),不同迭代器支持的迭代操作不同...因为list的迭代器,我们无法通过原生指针实现,为了能过还原对应的指针操作,我们需要在迭代器类中有一个成员变量是节点指针,同时由于迭代器的相关操作经常使用,我们这里使用struct定义类。...,因为插入元素有可能会导致重新扩容,致使原来迭代器失效,删除时,当前迭代器需要重新赋值否则会失效 插入元素不会导致迭代器失效,删除元素时,只会导致当前迭代器失效,其他迭代器不受影响 使 用 场 景 需要高效存储
hasNext() const: 检查是否有下一个元素。 next(): 返回当前元素并将迭代器移动到下一个元素。 peekNext() const: 返回当前元素但不移动迭代器。...setValue(const T &value): 将迭代器当前位置的元素设置为给定值。 这两个迭代器类提供了方便而灵活的方式来遍历和操作 QList 中的元素,根据需要选择合适的迭代器。...QLinkedList::end() 返回指向链表最后一个元素之后的迭代器。...QLinkedList 提供了与 QList 类似的操作,但由于其基于双向链表实现,特别适合于需要频繁插入和删除操作的场景。...双向迭代器: QLinkedList 提供了双向迭代器,可以方便地从前往后或从后往前遍历链表。
尾删的时候,因为end()是最后一个数据的下一个位置,因此需要end()减减一下,则需要在迭代器的类域里面实现operator--()的接口。...如果我们像实现string类和vector类(官方库中不是使用原生指针)一样,直接使用原生指针,是不可以写出我们需要的迭代器的!..._pnode; } }; 此时,就可以在list类里面写出迭代器的两个函数:begin和end。需要注意的是,begin的位置,是头节点的下一个位置,因为这是带头链表。...正确的写法: 我们可以单独实现一个const版本的迭代器的类,只需要把operator*()变成const版本,然后其它的不变即可,接着begin()和end()也实现一个const版本即可!...代 器 失 效 在插入元素时,要给所有的迭代器重新赋值,因为插入 元素有可能会导致重新扩容,致使原来迭代器失效,删 除时,当前迭代器需要重新赋值否则会失效 插入元素不会导致迭代器 删除元素时,只会导致当
领取专属 10元无门槛券
手把手带您无忧上云