C++list

1.迭代器的功能以及性质

功能有iterator,reverse_iterator,const_iterator,const_reverse_iterator

性质有单向,双向和随机,单向的迭代器只能++操作,双向只能++/--俩种,随机则可以执行++/--/+/-的操作

底层结构可以决定使用那些算法,下图的关系可知output的操作是包括随机,最后一个可以包容前面的,InputIterator表示哪一个都可以接受,单向,双向及随机都可以作为参数。

2.list的构造

list构造函数是调用了一个函数,名字上可以理解是空的初始化,内容是调用函数获得一个节点,把下一个指向自己,前一个也指向自己,就是一个哨兵位。

 3.push_back实现

这里head是哨兵位,则begin就是head的下一个,end就是head的前一个(或者可以把有哨兵位的链表环型的),要插入新的节点就把之前tail的下一个指向新的,然后新的节点的下一个指向哨兵位,在把prev(前一个指针)连接,就完成了。

void push_back(const T& x)
{Node* newnode = new Node(x);Node* tail = _head->_prev;tail->_next = newnode;newnode->_prev = tail;newnode->_next = _head;_head->_prev = newnode;}

3.构造关于节点的模板

成员有节点的值,以及节点的前后指针,这里走list_node的构造,如果没有参数这个data会用匿名对象的data来拷贝给data,而匿名对象的data为0.

	template<class T>struct list_node{T _data;list_node<T>* _next;list_node<T>* _prev;list_node(const T& data = T()):_data(data), _next(nullptr), _prev(nullptr){}};void test_list1()
{list_node<int> x;/*list<int> It;It.push_back(1);It.push_back(2);It.push_back(3);It.push_back(4);list<int>::iterator it = It.begin();while (it != It.end()){cout << *it << " ";++it;}cout << endl;*/
}

4.list迭代器 list_iterator模板

在代码里有三个模版,第一个模板是关于节点的内容,节点的值,前后指针,第二个模板是指向节点的指针,可以通过这个去找到对应节点的位置,第三个模板是list的操作模板就是增删查改等操作的地方。

这个模板类的成员是Node* _node就是一个指向节点的指针,后面的operator就是移动指针和解引用指针以及布尔判断。

	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->_prev;return *this;}bool operator!=(const Self& s) const{return _node != s._node;}bool operator==(const Self& s) const{return _node == s._node;}};

 5.list模板

list的成员有Node* _head和size_t _size俩个,一个是指向节点的指针,另一个是链表的大小。

1.list构造

_head指向一个刚开辟的空间,然后把next和prev都指向自己,链表大小为0,

list()
{_head = new Node;_head->_next = _head;_head->_prev = _head;_size = 0;
}

2.begin()和end()

哨兵位的下一个就是第一个节点,哨兵位的上一个就是最后一个节点,切记end()是指哨兵位的位置,begin()是哨兵位的下一个。

iterator begin(){return _head->_next;}iterator end(){return _head;}

3.insert 

 在指定位置前一个位插入节点,cur来保存指定位置的节点,prev保存指定位置的前一个节点,用要插入节点的值构造节点,把构造节点的下一个位置连到指定位置的节点,构造的新节点前一个节点指向指定位置的前一个节点,然后把指定位置的前一个节点的next于新节点连接,最后把size加一。

void insert(iterator pos, const T& x){Node* cur = pos._node;Node* prev = cur->_prev;Node* newnode = new Node(x);newnode->_next = cur;cur->_prev = newnode;newnode->_prev = prev;prev->_next = newnode;++_size;}

 4.push_back和push_front

有了之前的insert,尾插就只用在哨兵位的前一个插入(哨兵位的前一个就是最后一个节点),头插就只用在哨兵位的下一个插入就可以。

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

5.erase 

删除指定位置的节点,先保存要删除节点的俩个指针,指向前一个的和指向下一个的,然后把指向前一个节点连接到指向下一个节点,最后把指定位置节点pos删除,最后把size--。

void erase(iterator pos){assert(pos != end());Node* prev = pos._node->_prev;Node* next = pos._node->_next;prev->_next = next;next->prev = prev;delete pos._node;--_size;}

 6.pop_back和pop_front

有了之前的erase,尾删就是end()哨兵位的上一个删除,头删就是begin()哨兵位的下一个。

void pop_back(){erase(--end());}void pop_front(){erase(begin());}

7.size

链表的大小在插入或者删除时会变,判空用重载==与0相比。

size_t size() const{return _size;}bool empty() const{return _size == 0;}

6.splice函数

void splice(iterator pos, list& x);

第一个参数为指定list的一个位置,往里面插入里一个list,这里插入后,另一个链表的值就会空。

// 一个链表节点转移给另一个链表
std::list<int> mylist1, mylist2;
std::list<int>::iterator it;// set some initial values:
for (int i = 1; i <= 4; ++i)mylist1.push_back(i);      // mylist1: 1 2 3 4for (int i = 1; i <= 3; ++i)mylist2.push_back(i * 10);   // mylist2: 10 20 30it = mylist1.begin();
++it;                         // points to 2mylist1.splice(it, mylist2); // mylist1: 1 10 20 30 2 3 4
for (auto e : mylist1){cout << e << " ";}cout << endl;

void splice(iterator position, list& x, iterator i);                             1

void splice(iterator position, list& x, iterator first, iterator last);    2

 1函数第一个参数是需要一个指向原链表的位置,第二个参数是要插入的链表,第三个是要插入链表的第i个位置的元素。

2是把区间的元素给放到指定的位置,1是单个,2是划定一个区间,把区间的元素都移到指定位置,这里输入2则it就是指向lt的2的位置, 则区间为lt的2到lt的end(),也就是把2后面的所有都放到1的前面。(往前插入)

	std::list<int>::iterator it;list<int> lt;lt.push_back(1);lt.push_back(2);lt.push_back(3);lt.push_back(4);lt.push_back(5);lt.push_back(6);for (auto e : lt){cout << e << " ";}cout << endl;int x = 0;cin >> x;it = find(lt.begin(), lt.end(), x);if (it != lt.end()){//lt.splice(lt.begin(), lt, it);lt.splice(lt.begin(), lt, it, lt.end());}for (auto e : lt){cout << e << " ";}cout << endl;
}

7.总代码

test.cpp

#include"list.h"#include<iostream>
#include<algorithm>
#include<list>
#include<vector>
using namespace std;void test_op2()
{srand(time(0));const int N = 1000000;list<int> lt1;list<int> lt2;for (int i = 0; i < N; ++i){auto e = rand() + i;lt1.push_back(e);lt2.push_back(e);}int begin1 = clock();// 拷贝vectorvector<int> v(lt2.begin(), lt2.end());// 排序sort(v.begin(), v.end());// 拷贝回lt2lt2.assign(v.begin(), v.end());int end1 = clock();int begin2 = clock();lt1.sort();int end2 = clock();printf("list copy vector sort copy list sort:%d\n", end1 - begin1);printf("list sort:%d\n", end2 - begin2);
}void test_list6()
{// 一个链表节点转移给另一个链表std::list<int> mylist1, mylist2;std::list<int>::iterator it;// set some initial values:for (int i = 1; i <= 4; ++i)mylist1.push_back(i);      // mylist1: 1 2 3 4for (int i = 1; i <= 3; ++i)mylist2.push_back(i * 10);   // mylist2: 10 20 30it = mylist1.begin();++it;                         // points to 2mylist1.splice(it, mylist2); // mylist1: 1 10 20 30 2 3 4// mylist2 (empty)// "it" still points to 2 (the 5th element// 调整当前链表节点的顺序list<int> lt;lt.push_back(1);lt.push_back(2);lt.push_back(3);lt.push_back(4);lt.push_back(5);lt.push_back(6);for (auto e : lt){cout << e << " ";}cout << endl;int x = 0;cin >> x;it = find(lt.begin(), lt.end(), x);if (it != lt.end()){//lt.splice(lt.begin(), lt, it);lt.splice(lt.begin(), lt, it, lt.end());}for (auto e : lt){cout << e << " ";}cout << endl;
}
int main()
{//test_list6();//test_op2();zym::test_list1();return 0;
}
#include"list.h"int main()
{//test_list6();//test_op2();zym::test_list1();return 0;
}

list.h

#pragma once#include<iostream>
using namespace std;namespace zym
{template<class T>struct list_node{T _data;list_node<T>* _next;list_node<T>* _prev;list_node(const T& data = T()):_data(data), _next(nullptr), _prev(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->_prev;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->_next = _head;_head->_prev = _head;_size = 0;}void push_back(const T& x){insert(end(), x);}void push_front(const T& x){insert(begin(), x);}void insert(iterator pos, const T& x){Node* cur = pos._node;Node* prev = cur->_prev;Node* newnode = new Node(x);newnode->_next = cur;cur->_prev = newnode;newnode->_prev = prev;prev->_next = newnode;++_size;}void pop_back(){erase(--end());}void pop_front(){erase(begin());}void erase(iterator pos){assert(pos != end());Node* prev = pos._node->_prev;Node* next = pos._node->_next;prev->_next = next;next->prev = prev;delete pos._node;--_size;}size_t size() const{return _size;}bool empty() const{return _size == 0;}private:Node* _head;size_t _size;};void test_list1(){list<int> It;It.push_back(1);It.push_back(2);It.push_back(3);It.push_back(4);list<int>::iterator it = It.begin();while (it != It.end()){cout << *it << " ";++it;}cout << endl;}
}

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

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

相关文章

【C++篇】栈的层叠与队列的流动:在 STL 的韵律中探寻数据结构的优雅之舞

文章目录 C 栈与队列详解&#xff1a;基础与进阶应用前言第一章&#xff1a;栈的介绍与使用1.1 栈的介绍1.2 栈的使用1.2.1 最小栈1.2.2 示例与输出 1.3 栈的模拟实现 第二章&#xff1a;队列的介绍与使用2.1 队列的介绍2.2 队列的使用2.2.1 示例与输出 2.3 队列的模拟实现2.3.…

[快速阅读八] Matlab中bwlookup的实现及其在计算二值图像的欧拉数、面积及其他morph变形中的应用。...

以前看过matlab的bwlookup函数&#xff0c;但是总感觉有点神秘&#xff0c;一直没有去仔细分析&#xff0c;最近在分析计算二值图像的欧拉数时&#xff0c;发现自己写的代码和matlab的总是对不少&#xff0c;于是又去翻了下matlab的源代码&#xff0c;看到了matlab里实现欧拉数…

JS轮播图实现自动轮播、悬浮停止轮播、点击切换,下方指示器与图片联动效果

代码&#xff1a; <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</title><s…

计算机网络原理总结C-网络层

网络层 网络层提供的两种服务网际协议IP 虚拟互连网络IP地址子网掩码&#xff08;无分类编址CIDR&#xff09;IP地址和MAC地址IP数据报格式&#xff08;路由&#xff09;转发分组的流程 因特网的路由选择协议&#xff08;动态路由协议&#xff09; 网际控制报文协议ICMPIP多播…

麒麟v10 arm64 部署 kubesphere 3.4 修改记录

arm64环境&#xff0c;默认安装 kubesphere 3.4 &#xff0c;需要修改几个地方的镜像&#xff0c;并且会出现日志无法显示 1 fluentbit:v1.9.4 报错 <jemalloc>: Unsupported system page size Error in GnuTLS initialization: ASN1 parser: Element was not found. &…

Java最全面试题->数据库/中间件->Redis面试题

文章目录 Redisredis的数据类型有哪些?Redis 内部结构有哪些?Memcache 与 Redis 的区别都有哪些?为什么 redis 需要把所有数据放到内存中?Redis 如何进行持久化?RDB和AOF的优缺点有哪些?什么是缓存穿透?如何避免?什么是缓存雪崩?何如避免?redis的淘汰策略有哪些?Red…

用更多的钱买电脑而不是手机

如果&#xff0c;我们对自己的定义是知识工作者&#xff0c;那么在工作、学习相关的电子设备投入上&#xff0c;真的别舍不得花钱。 需要留意的是&#xff0c;手机&#xff0c;对于大部分在电脑前工作的人&#xff0c;不是工作设备。在我看来&#xff0c;每年投入到电脑的钱&…

【高级IO】IO多路转接之select

select函数 我们知道IO 等待 拷贝&#xff0c;系统提供select函数来实现多路复用输入/输出模型&#xff1b;select系统调用是用来让我们的程序监视多个文件描述符的状态变化的&#xff1b;程序会停在select这里等待&#xff0c;直到被监视的文件描述符有一个或多个发生了状态…

植物健康,Spring Boot来助力

3系统分析 3.1可行性分析 通过对本植物健康系统实行的目的初步调查和分析&#xff0c;提出可行性方案并对其一一进行论证。我们在这里主要从技术可行性、经济可行性、操作可行性等方面进行分析。 3.1.1技术可行性 本植物健康系统采用SSM框架&#xff0c;JAVA作为开发语言&#…

钉钉录播抓取视频

爬取钉钉视频 免责声明 此脚本仅供学习参考&#xff0c;切勿违法使用下载他人资源进行售卖&#xff0c;本人不但任何责任! 仓库地址: GItee 源码仓库 执行顺序 poxyM3u8开启代理getM3u8url用于获取m3u8文件userAgent随机请求头downVideo|downVideoThreadTqdm单线程下载和…

【纯血鸿蒙】HarmonyOS和OpenHarmony 的区别

一、开源鸿蒙&#xff08;Open Harmony&#xff09; 鸿蒙系统愿来的设计初衷&#xff0c;就是让所有设备都可以运行一个系统&#xff0c;但是每个设备的运算能力和功能都不同&#xff0c;所以内核的设计上&#xff0c;采用了微内核的设计&#xff0c;除了最基础的功能放在内核…

logback 如何将日志输出到文件

如何作 将日志输出到文件需要使用 RollingFileAppender&#xff0c;该 Appender 必须定义 rollingPolicy &#xff0c;另外 rollingPollicy 下必须定义 fileNamePattern 和 encoder <appender name"fileAppender" class"ch.qos.logback.core.rolling.Rollin…

LLM | 论文精读 | 基于大型语言模型的自主代理综述

论文标题&#xff1a;A Survey on Large Language Model based Autonomous Agents 作者&#xff1a;Lei Wang, Chen Ma, Xueyang Feng, 等 期刊&#xff1a;Frontiers of Computer Science, 2024 DOI&#xff1a;10.1007/s11704-024-40231-1 一、引言 自主代理&#xff08;…

企业自建邮件系统选U-Mail ,功能强大、安全稳定

在现代企业运营中&#xff0c;电子邮件扮演着至关重要的角色&#xff0c;随着企业规模的增长和业务的多样化&#xff0c;传统的租用第三方企业邮箱服务逐渐显现出其局限性。例如&#xff0c;存储空间受限、数据安全风险、缺乏灵活的管理和备份功能&#xff0c;以及无法与其他企…

C++从入门到起飞之——红黑树 全方位剖析!

&#x1f308;个人主页&#xff1a;秋风起&#xff0c;再归来~&#x1f525;系列专栏&#xff1a;C从入门到起飞 &#x1f516;克心守己&#xff0c;律己则安 目录 1. 红⿊树的概念 2. 红⿊树的实现 2.1 构建整体框架 2.2 红黑树的插入 2.3 红黑树的验证 2.4 红黑树…

数据库、数据仓库、数据湖和数据中台有什么区别

很多企业在面对数据存储和管理时不知道如何选择合适的方式&#xff0c;数据库、数据仓库、数据湖和数据中台&#xff0c;这些方式都是什么&#xff1f;有什么样的区别&#xff1f;企业根据其业务类型该选择哪一种&#xff1f;本文就针对这些问题&#xff0c;来探讨下这些方式都…

ASP.NET Core 8.0 中使用 Hangfire 调度 API

在这篇博文中&#xff0c;我们将引导您完成将 Hangfire 集成到 ASP.NET Core NET Core 项目中以安排 API 每天运行的步骤。Hangfire 是一个功能强大的库&#xff0c;可简化 .NET 应用程序中的后台作业处理&#xff0c;使其成为调度任务的绝佳选择。继续阅读以了解如何设置 Hang…

山西农业大学20241025

06-VUE 一. 生命周期1. 概念2. 生命周期的钩子函数 二. 工程化开发和脚手架1. 开发vue的两种方式2. 脚手架 Vue CLI3. 使用步骤4 . 项目目录介绍4.1 项目目录4.2 总结 一. 生命周期 1. 概念 VUE生命周期: 就是vue实例从创建到销毁的整个 生命周期经历了四个阶段: ①创建 ②挂载…

Clickhouse 笔记(一) 单机版安装并将clickhouse-server定义成服务

ClickHouse 是一个高性能的列式数据库管理系统&#xff08;DBMS&#xff09;&#xff0c;主要用于在线分析处理&#xff08;OLAP&#xff09;场景。它由俄罗斯搜索引擎公司 Yandex 开发&#xff0c;并在 2016 年开源。ClickHouse 以其卓越的查询性能和灵活的扩展性而闻名&#…

2-133 基于matlab的粒子群算法PSO优化BP神经网络

基于matlab的粒子群算法PSO优化BP神经网络&#xff0c;BP神经网络算法采用梯度下降算法&#xff0c;以输出误差平方最小为目标&#xff0c;采用误差反向传播&#xff0c;训练网络节点权值和偏置值&#xff0c;得到训练模型。BP神经网络的结构(层数、每层节点个数)较复杂时&…