C++初阶学习第十一弹——list的用法和模拟实现

目录

一、list的使用

二.list的模拟实现

三.总结


一、list的使用

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

常见的list的函数的使用

std::list<int> It = {1, 2, 3, 4, 5};通过迭代器访问元素:
std::list<int>::iterator it = It.begin();
while (it != It.end()) {std::cout << *it << std::endl;++it;
}在链表尾部插入元素:
It.push_back(6);在链表头部插入元素
It.push_front(0);删除元素
It.remove(3); // 删除值为3的元素
It.erase(it); // 删除迭代器指向的元素排序链表:
It.sort();反转链表:
It.reverse();

 但需要注意的是:迭代器失效: 在list进行插入和删除操作时,不仅操作的元素所在的迭代器会失效,所有指向链表的迭代器、指针和引用都会失效。因此,在进行操作后,需要重新获取有效的迭代器。(vector的使用也要注意这个问题)

二.list的模拟实现

list的迭代器和 string与 vector不太一样,,没有vector那么天生条件优越。需要单独实现一个类,来封装迭代器。

指针可以解引用,迭代器的vector类中必须重载operator*()

指针可以通过->访问其所指空间成员,迭代器类中必须重载oprator->()

指针可以++向后移动,迭代器类中必须重载operator++()与operator++(int)

迭代器需要进行是否相等的比较,因此还需要重载operator==()与operator!=()。

#pragma once
#include<iostream>
#include<assert.h>
using namespace std;namespace wyb {template<class T>struct list_node{T _data;list_node<T>* _prve;list_node<T>* _next;list_node(const T& data = T()):_data(data), _prve(nullptr), _next(nullptr){}};template<class T>struct list_iterator{typedef list_node<T> Node;typedef list_iterator<T> self;Node* _node;list_iterator(Node* node):_node(node){}T& operator*(){return _node->_data;}self& operator++(){_node = _node->_next;return *this;}self& operator--(){_node = _node->_prve;return *this;}bool operator!=(const self& s) const{return _node != s._node;}bool operator==(const self& s) const{return _node == s._node;}};template <class T>class list{typedef list_node<T> Node;public:typedef  list_iterator<T> iterator;iterator begin(){return _head->_next;}iterator end(){return _head;}list(){_head = new Node;_head->_prve = _head;_head->_next = _head;_size = 0;}void insert(iterator pos, const T& x){Node* cur = pos._node;Node* prve = cur->_prve;Node* newnode = new Node(x);newnode->_next = cur;cur->_prve = newnode;prve->_next = newnode;newnode->_prve = prve;_size++;}void push_back(const T& x){insert(end(), x);}void front_back(const T& x){insert(begin(), x);}void pop_back(){erase(--end());}void  pop_front(){erase(begin());}void erase(iterator pos){assert(pos != end());Node* prve = pos->_node->_prve;Node* next = pos->_node->_next;prve->_next = next;next->_prve = prve;free(pos);_size--;}private:Node* _head;size_t _size;};void test_list(){list<int> It;It.push_back(1);It.push_back(2);It.push_back(3);It.push_back(4);It.push_back(5);list<int>::iterator it=It.begin();while (it != It.end()){cout << *it << " ";++it;}cout << endl;}
}

1、任意位置插入删除时:list可以随意插入删除,但是vector任意位置的插入删除效率低,需要挪动元素,尤其是插入时有时候需要异地扩容,就需要开辟新空间,拷贝元素,释放旧空间,效率很低

2、访问元素时:vector支持随机访问,但是list不支持随机访问
3、迭代器的使用上:vector可以使用原生指针,但是list需要对原生指针进行封装
4、空间利用上:vector使用的是一个连续的空间,空间利用率高,而list使用的是零碎的空间,空间利用率低

三.总结

以上关于list的模拟实现有点不全,我后期我会补充一些进来。又不懂的地方可以随时联系。

创作不易希望大佬点赞关注。

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

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

相关文章

Qlik Sense QVD 文件

QVD 文件 QVD (QlikView Data) 文件是包含从 Qlik Sense 或 QlikView 中所导出数据的表格的文件。QVD 是本地 Qlik 格式&#xff0c;只能由 Qlik Sense 或 QlikView 写入和读取。当从 Qlik Sense 脚本中读取数据时&#xff0c;该文件格式可提升速度&#xff0c;同时又非常紧凑…

攻防世界 Web新手练习区

GFSJ0475 get_post 获取在线场景后&#xff0c;点开网址 依据提示在搜索框输入信息 给出第二条提示信息 打开hackbar&#xff0c;将网址Load下来&#xff0c;勾选Post data&#xff0c;在下方输入框输入b2 点击Execute 出现flag值 GFSJ0476 robots 打开御剑扫描域名&#…

MySQL —— explain 查看执行计划与 MySQL 优化

文章目录 explain 查看执行计划explain 的作用——查看执行计划explain 查看执行计划返回信息详解表的读取顺序&#xff08;id&#xff09;查询类型&#xff08;select_type&#xff09;数据库表名&#xff08;table&#xff09;联接类型&#xff08;type&#xff09;可用的索引…

前端研发高德地图,如何根据经纬度获取地点名称和两点之间的距离?

地理编码与逆地理编码 引入插件&#xff0c;此示例采用异步引入&#xff0c;更多引入方式 https://lbs.amap.com/api/javascript-api-v2/guide/abc/plugins AMap.plugin("AMap.Geocoder", function () {var geocoder new AMap.Geocoder({city: "010", /…

React(二)

文章目录 项目地址七、数据流7.1 子组件传递数据给父组件7.1.1 方式一:給父设置回调函数,传递给子7.1.2 方式二:直接将父的setState传递给子7.2 给props传递jsx7.2.1 方式一:直接传递组件给子类7.2.2 方式二:传递函数给子组件7.3 props类型验证7.4 props的多层传递7.5 cla…

SpringBootTest常见错误解决

1.启动类所在包错误 问题 由于启动类所在包与需要自动注入的类的包不在一个包下&#xff1a; 启动类所在包&#xff1a; com.exmaple.test_02 但是对于需要注入的类却不在com.exmaple.test_02下或者其子包下&#xff0c;就会导致启动类无法扫描到该类&#xff0c;从而无法对…

Redis面试篇笔记(持续更新)

一、redis主从集群 单节点redis的并发能力是由上限的&#xff0c;要进一步提高redis的并发能力可以搭建主从集群&#xff0c;实现读写分离&#xff0c;一主多从&#xff0c;主节点写数据&#xff0c;从节点读数据 部署redis主从节点的docker-compose文件命令解析 version: &q…

ISUP协议视频平台EasyCVR私有化视频平台新能源汽车充电停车管理方案的创新与实践

在环保意识提升和能源转型的大背景下&#xff0c;新能源汽车作为低碳出行的选择&#xff0c;正在全球迅速推广。但这种快速增长也引发了充电基础设施短缺和停车秩序混乱等挑战&#xff0c;特别是在城市中心和人口密集的居住区&#xff0c;这些问题更加明显。因此&#xff0c;开…

goland单元测试

一、单元测试的概念 1.1 什么是单元测试&#xff0c;有什么用&#xff1f; 单元测试是针对于函数的测试&#xff0c;用来保证该函数的逻辑正确性。 1.2 单元测试的要求&#xff1f; 1. 单元测试在正式上线之前应该全部自动执行&#xff0c;并且需要保证全部通过 2. 单元测试需…

连接数据库:通过链和代理查询鲜花信息

目录 新的数据库查询范式 实战案例背景信息 创建数据库表 用 Chain 查询数据库 用 Agent 查询数据库 一直以来&#xff0c;在计算机编程和数据库管理领域&#xff0c;所有的操作都需要通过严格、专业且结构化的语法来完成。这就是结构化查询语言&#xff08;SQL&#xff0…

【c++丨STL】stack和queue的使用及模拟实现

&#x1f31f;&#x1f31f;作者主页&#xff1a;ephemerals__ &#x1f31f;&#x1f31f;所属专栏&#xff1a;C、STL 目录 前言 一、什么是容器适配器 二、stack的使用及模拟实现 1. stack的使用 empty size top push和pop swap 2. stack的模拟实现 三、queue的…

aws上安装ssm-agent

aws-cloudwatch 连接机器 下载ssm-agent aws-ec2 安装ssm-agent aws-linux安装ssm-agent 使用 SSM 代理查找 AMI 预装 先运行&#xff1a;systemctl status amazon-ssm-agent 查看sshm-agent的状态。 然后安装提示&#xff0c;执行 systemctl start amazon-ssm-agent 启动即…

百度世界2024:智能体引领AI应用新纪元

在近日盛大举行的百度世界2024大会上&#xff0c;百度创始人李彦宏以一场题为“文心一言”的精彩演讲&#xff0c;再次将全球科技界的目光聚焦于人工智能&#xff08;AI&#xff09;的无限可能。作为一名科技自媒体&#xff0c;我深感这场演讲不仅是对百度AI技术实力的一次全面…

纯血鸿蒙NEXT-组件导航 (Navigation)

Navigation组件是路由导航的根视图容器&#xff0c;一般作为Page页面的根容器使用&#xff0c;其内部默认包含了标题栏、内容区和工具栏&#xff0c;其中内容区默认首页显示导航内容&#xff08;Navigation的子组件&#xff09;或非首页显示&#xff08;NavDestination的子组件…

C语言 | Leetcode C语言题解之第564题寻找最近的回文数

题目&#xff1a; 题解&#xff1a; #define MAX_STR_LEN 32 typedef unsigned long long ULL;void reverseStr(char * str) {int n strlen(str);for (int l 0, r n-1; l < r; l, r--) {char c str[l];str[l] str[r];str[r] c;} }ULL * getCandidates(const char * n…

docker学习笔记跟常用命令总结

Docker简介 Docker是一个用于构建运行传送应用程序的平台 镜像 将应用所需的函数库、依赖、配置等与应用一起打包得到的就是镜 镜像结构 镜像管理命令 命令说明docker pull拉取镜像docker push推送镜像docker images查看本地镜像docker rmi删除本地镜像docker image prune…

MySQL 中 InnoDB 支持的四种事务隔离级别名称,以及逐级之间的区别?

MySQL中的InnoDB存储引擎支持四种事务隔离级别&#xff0c;这些级别定义了事务在并发环境中的行为和相互之间的可见性。以下是这四种隔离级别的名称以及它们之间的区别&#xff1a; 读未提交&#xff08;Read Uncommitted&#xff09; 特点&#xff1a;这是最低的隔离级别&…

【力扣热题100】[Java版] 刷题笔记-226. 翻转二叉树

题目:226. 翻转二叉树 给你一棵二叉树的根节点 root &#xff0c;翻转这棵二叉树&#xff0c;并返回其根节点。 解题思路 二叉树翻转&#xff0c;可以通过递归进行交换。 解题过程 /*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeN…

Android kotlin之配置kapt编译器插件

配置项目目录下的gradle/libs.versions.toml文件&#xff0c;添加kapt配置项&#xff1a; 在模块目录下build.gradle.kt中增加 plugins {alias(libs.plugins.android.application)alias(libs.plugins.jetbrains.kotlin.android)// 增加该行alias(libs.plugins.jetbrains.kotl…

【Linux学习】【Ubuntu入门】1-8 ubuntu下压缩与解压缩

1.Linux系统下常用的压缩格式 常用的压缩扩展名&#xff1a;.tar、.tar.bz2、.tar.gz 2.Windows下7ZIP软件安装 Linux系统下很多文件是.bz2&#xff0c;.gz结尾的压缩文件。 3.Linux系统下gzip压缩工具 gzip工具负责压缩和解压缩.gz格式的压缩包。 gzip对单个文件进行…