STL——List常用接口模拟实现及其使用

认识list

list的介绍

    1. list是可以在常数范围内在任意位置进行插入和删除的序列式容器,并且该容器可以前后双向迭代。
    1. list的底层是双向链表结构,双向链表中每个元素存储在互不相关的独立节点中,在节点中通过指针指向其前一个元素和后一个元素。
    1. list与forward_list非常相似:最主要的不同在于forward_list是单链表,只能朝前迭代,已让其更简单高效。
    1. 与其他的序列式容器相比(array,vector,deque),list通常在任意位置进行插入、移除元素的执行效率更好。
    1. 与其他序列式容器相比,list和forward_list最大的缺陷是不支持任意位置的随机访问,比如:要访问list的第6个元素,必须从已知的位置(比如头部或者尾部)迭代到该位置,在这段位置上迭代需要线性的时间开销;list还需要一些额外的空间,以保存每个节点的相关联信息(对于存储类型较小元素的大list来说这可能是一个重要的因素)

list和vector的对比

vectorlist



动态顺序表,一段连续空间带头结点的双向循环链表


访
支持随机访问,访问某个元素效率O(1)不支持随机访问,访问某个元素效率O(N)




任意位置插入和删除效率低,需要搬移元素,时间复杂度为O(N),插入时有可能需要增容,增容:开辟新空间,拷贝元素,释放旧空间,导致效率更低任意位置插入和删除效率高,不需要搬移元素,时间复杂度为O(1)




底层为连续空间,不容易造成内存碎片,空间利用率高,缓存利用率高底层节点动态开辟,小节点容易造成内存碎片,空间利用率低,缓存利用率低


原生态指针对原生态指针(节点指针)进行封装




在插入元素时,要给所有的迭代器重新赋值,因为插入元素有可能会导致重新扩容,致使原来迭代器失效,删除时,当前迭代器需要重新赋值否则会失效插入元素不会导致迭代器失效,删除元素时,只会导致当前迭代器失效,其他迭代器不受影响
使


需要高效存储,支持随机访问,不关心插入删除效率大量插入和删除操作,不关心随机访问

基本框架

单个节点构建

	template<class T>class list_node {public:list_node<T>* _next;//后继指针list_node<T> *_prev;//前驱指针T _data;//节点的值list_node(const T& data = T()):_data(data), _next(nullptr),_prev(nullptr){}};

List结构构建

class List {typedef list_node<T> Node;public:List(){_pHead = new Node();_pHead->_next = _pHead;_pHead->_prev = _pHead;}
};

push_back尾插

实现
void push_back(const T& data) {Node* newnode = new Node(data);Node* pTail = _pHead->_prev;//最后一个节点pTail->_next = newnode;newnode->_prev = pTail;//连接最后一个节点和新节点newnode->_next = _pHead;_pHead->_prev = newnode;//处理最后一个节点和第一个节点		}
使用
mylist::List<int> A;A.push_back(1);A.push_back(2);A.push_back(3);A.push_back(4);A.print();//这个是方便调试观察结果写出来的函数

在这里插入图片描述

迭代器的实现

在之前的容器string和vector的实现中,迭代器都是以指针的形式实现,但是在List模拟实现中又不是指针,因为List是一个链表,空间并不连续,指针的+或-并不能移动到数据的下一个位置。

迭代器的构造

	template <class T>class list_iterator {typedef list_node<T> Node;public:Node* _nodelist_iterator(Node* x): _node(x){}};

operator++

//前置++   (++it)iterator<T>& operator++() {_node = _node->_next;return *this;}
//后置++  (it++)iterator<T> operator++(int) {list_iterator<T> tmp(*this);_node = _node->_next;return tmp;}

operator*

//解引用T& operator*() {return _node->_data;}

operator !=

bool operator !=(const iterator& it) {return _node != it._node;}

在这里插入图片描述

const迭代器实现

如果这里要实现const迭代器,将之前的的代码复用再写一个const_list_iterator,然后在List再写一个const 的begin()和end()就可以了,但是这里有更优的写法,可以解决这些不必要的代码冗余

	class List {public:typedef list_node<T> Node;typedef list_iterator<T, T&, T*> iterator;typedef list_iterator<T, const T&, const T*> const_iterator;const_iterator begin() const {return const_iterator(_pHead->_next);}const_iterator end() const {return cosnt_iterator(_pHead);}.......
}
struct list_iterator {typedef list_node<T> Node;typedef list_iterator<T, Ref, Ptr> self;Ref& operator*() {return _node->_data;}
}

迭代器对List初始化

template<class Iterator>List(Iterator first, Iterator last) {_pHead = new Node();_pHead->_next = _pHead;_pHead->_prev = _pHead;while (first != last) {push_back(*first);first++;}}

增删查改

在 pos 位置前插入 - insert

	void insert(iterator pos, const T& x) {Node* cur = pos._node;     // 找到pos位置的结点Node* cur_prev = cur->_prev;     // 当前pos位置的前一个结点Node* new_node = new Node(x);  // 创建新节点cur_prev->_next = new_node;new_node->_prev = cur_prev;new_node->_next = cur;cur->_prev = new_node;}

push_front 头插

void push_front(const T& x) {insert(begin(), x); }

在这里插入图片描述

删除 pos 位置的结点 erase

iterator erase(iterator pos) {assert(pos != end());   // 防止头结点被删除Node* cur = pos._node;   // posNode* cur_prev = cur->_prev;   // pos的前驱Node* cur_next = cur->_next;   // pos的后继// 删除posdelete cur;cur_prev->_next = cur_next;cur_next->_prev = cur_prev;return iterator(cur_next);}

pop_back 尾删

void pop_back() {erase(_pHead->_prev);  // 删除最后一个元素
}

在这里插入图片描述

pop_front 头删

void pop_front() {erase(begin());  // 删除头结点的下一个结点->begin所指的位置}

在这里插入图片描述

clear 删除链表所有数据

void clear() {iterator cur = begin();while (cur != end()) {iterator del = cur++;delete del._node; }//处理哨兵节点_pHead->_next = _pHead;_pHead->_prev = _pHead;}

在这里插入图片描述

析构函数和拷贝构造

默认的拷贝构造是浅拷贝,在这里是行不通的,万一调用析构函数,同一个空间就被释放两次了所以要对拷贝构造设计一下让其成为深拷贝的形式

析构

~List() {clear();delete _pHead;_pHead = nullptr;
}

拷贝构造


list(const list<T>& L) {_pHead = new Node();_pHead->_next = _pHead;_pHead->_prev = _pHead;List<T> tmp(L.begin(), L.end());swap(_pHead, tmp._pHead);  
}

在这里插入图片描述

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

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

相关文章

【IDEA】在IntelliJ IDEA中导入Eclipse项目:详细指南

IntelliJ IDEA和Eclipse是两款常用的集成开发环境&#xff08;IDE&#xff09;&#xff0c;在软件开发中经常会遇到需要在它们之间迁移项目的情况。本文将重点介绍如何在IntelliJ IDEA中导入Eclipse项目&#xff0c;以帮助开发者顺利地迁移他们的项目&#xff0c;并在IntelliJ …

大型语言模型高效推理综述

论文地址&#xff1a;2404.14294.pdf (arxiv.org) 大型语言模型&#xff08;LLMs&#xff09;由于在各种任务中的卓越表现而受到广泛关注。然而&#xff0c;LLM推理的大量计算和内存需求给资源受限的部署场景带来了挑战。该领域的努力已经朝着开发旨在提高LLM推理效率的技术方…

RustGUI学习(iced)之小部件(二):如何使用滑动条部件

前言 本专栏是学习Rust的GUI库iced的合集&#xff0c;将介绍iced涉及的各个小部件分别介绍&#xff0c;最后会汇总为一个总的程序。 iced是RustGUI中比较强大的一个&#xff0c;目前处于发展中&#xff08;即版本可能会改变&#xff09;&#xff0c;本专栏基于版本0.12.1. 概述…

Redis中的慢查询日志(一)

慢查询日志 概述 Redis的慢查询日志功能用于记录执行时间超过给定时长的命令请求&#xff0c;用户可以通过这个功能产生的日志来 监视和优化查询速度。服务器配置有两个和慢查询日志相关的选项: 1.slowlog-log-slower-than选项指定执行时间超过多少微妙(1秒1000 000微妙)的命…

【精】DevOps实战学习CI/CD落地方案#CI篇#

目录 先有个大概了解 基本概念 CI/CD Devops 阿里云效 devops产品 K8s jenkins docker git maven 知行合一&#xff0c;上手操作 实操记录 安装VMware 安装并配置虚拟机 安装并配置docker docker安装 修改镜像源&#xff08;关键且易出错&#xff09; CentOS…

低代码信创开发核心技术(四)动态元数据系统设计

一、概述 在当今快速发展的信息技术领域&#xff0c;动态元数据系统扮演着至关重要的角色。它不仅能够提供数据的描述信息&#xff0c;还能动态地适应业务需求的变化&#xff0c;从而提高系统的灵活性和可扩展性。构建一个动态元数据系统意味着我们可以在不重启系统的情况下&a…

Facebook的未知力量:数字世界的新引擎

在数字化的时代&#xff0c;社交媒体已经成为了我们日常生活中不可或缺的一部分&#xff0c;而Facebook作为其中的巨头&#xff0c;其影响力远远超出了我们的想象。但是&#xff0c;Facebook背后隐藏的力量和影响远不止于此&#xff0c;它正逐渐成为数字世界的新引擎&#xff0…

书生·浦语 大模型(学习笔记-5)XTuner 微调 LLM:1.8B、多模态、Agent

目录 一&#xff1a;两种微调 二、数据的一生 三、微调方案 四、XTuner 五、InternLM2 1.8B模型&#xff08;相关知识&#xff09; 一&#xff1a;两种微调 增量与训练和指令微调的区别 二、数据的一生 原始数据转换为标准格式数据 添加对话模板&#xff0c;直接调用即可…

操作系统课程--考纲要求

第一/二次课&#xff1a; 绪论 【学习内容与目标】 1、操作系统目标及定义 掌握操作系统的设置目标&#xff0c;理解并掌握操作系统的定义&#xff0c;了解操作系统的地位以及从资源管理者角度和用户角度了解操作系统的组成。 2、 操作系统的特征与功能 掌握操作系统的特征&…

github Copilot的使用总结

1. 代码建议和补全 GitHub Copilot 的基本使用涉及编写代码时的实时代码建议和补全。一旦你已经安装并配置好 GitHub Copilot 插件&#xff0c;你可以在支持的编辑器&#xff08;如 Visual Studio Code&#xff09;中开始使用 Copilot。以下是一些基本的使用步骤&#xff1a; …

RK3588S和ARM阵列服务器在虚拟化云平台的应用

RK3588是瑞芯微2021年底推出的首款高端8nm旗舰芯片&#xff0c;而RK3588S 则是针对消费端市场在RK3588基础上缩减了部分外围接口&#xff0c;CPU、GPU和NPU等主要参数得到了保留&#xff0c;主要应用范围为高端ARM平板、ARM笔电产品&#xff0c;会议平板类、ARM服务器、智能机器…

信息系统项目管理师——第7章项目立项管理

本章考选择题2-3分&#xff0c;案例和论文均有可能作为领域考试。 项目建议与立项申请♥♥♥♥♥ 立项申请的概念 立项申请又称为项目建议书&#xff0c;是项目建设单位向上级主管部门提交项目申请时所必须的文 件&#xff0c;是该项目建设筹建单位根据国民经济的发展、国家…

JavaWeb过滤器

Javaweb过滤器是一种用于在Servlet处理请求之前或之后对请求进行预处理或后处理的组件。过滤器可以用于拦截请求、修改请求参数、过滤响应内容等操作。其主要作用包括&#xff1a; 拦截请求&#xff1a;过滤器可以拦截客户端请求&#xff0c;对请求进行验证、过滤或修改&#x…

Java基础之JVM对象内存分配机制简介

一 对象内存分配 1.1 运行时数据区域 1.2 常见java应用启动JVM参数&#xff1a; -Xss&#xff1a;每个线程的栈大小(单位kb)-Xms&#xff1a;堆的初始大小&#xff0c;默认物理内存的1/64,示例&#xff1a;-Xms:4g -Xms:10m-Xmx&#xff1a;堆的最大可用大小&#xff0c;默认物…

水库大坝安全白蚁监测系统解决方案

一、系统背景 白蚁作为河岸生态系统中的重要病害&#xff0c;不仅会导致水库大坝外部环境发生改变&#xff0c;甚至会引发水库大坝破坏&#xff0c;进而导致自身结构失去稳定性&#xff0c;严重影响水库大坝的正常运行。因此&#xff0c;治理水库大坝白蚁是确保水库大坝工程顺利…

HTTP与HTTPS 对比,区别详解(2024-04-25)

一、简介 HTTP&#xff08;超文本传输协议&#xff0c;Hypertext Transfer Protocol&#xff09;是一种用于从网络传输超文本到本地浏览器的传输协议。它定义了客户端与服务器之间请求和响应的格式。HTTP 工作在 TCP/IP 模型之上&#xff0c;通常使用端口 80。 HTTPS&#xf…

【Hadoop】- MapReduce YARN 初体验[9]

目录 提交MapReduce程序至YARN运行 1、提交wordcount示例程序 1.1、先准备words.txt文件上传到hdfs&#xff0c;文件内容如下&#xff1a; 1.2、在hdfs中创建两个文件夹&#xff0c;分别为/input、/output 1.3、将创建好的words.txt文件上传到hdfs中/input 1.4、提交MapR…

区块链技术与应用学习笔记(8-9节)——北大肖臻课程

目录 8.挖矿 对于全节点和轻节点思考问题&#xff1f; ①全节点在比特币的主要作用&#xff1f; ②挖矿时当监听到别人已经挖出区块并且延申了最长合法链此时应该立刻放弃当前区块在 本地重新组装一个指向最后这个新合法区块的候选区块&#xff0c;重新开始挖矿。节点这么做…

「React Native」为什么要选择 React Native 作为的跨端方案

文章目录 前言一、常见因素二、举个栗子2.1 项目背景2.2 为什么选择 React Native2.3 项目实施2.4 成果总结 前言 没有完美的跨端技术&#xff0c;只有适合的场景。脱离适用场景去谈跨端技术没有什么意义。 一、常见因素 共享代码库&#xff1a; React Native 允许开发者编写…

OmniPlan Pro for Mac v4.8.0中文激活版 项目流程管理工具

OmniPlan Pro for Mac是一款功能强大的项目管理软件&#xff0c;它以其直观的用户界面和丰富的功能&#xff0c;帮助用户轻松管理各种复杂的项目。 OmniPlan Pro for Mac v4.8.0中文激活版 通过OmniPlan Pro&#xff0c;用户可以轻松创建任务&#xff0c;设置任务的开始和结束时…