百度推广和网站建设服装详情页设计

news/2025/9/22 18:43:37/文章来源:
百度推广和网站建设,服装详情页设计,下载空间大的网站建设,如何做网站联盟营销#x1f3d6;️作者#xff1a;malloc不出对象 ⛺专栏#xff1a;C的学习之路 #x1f466;个人简介#xff1a;一名双非本科院校大二在读的科班编程菜鸟#xff0c;努力编程只为赶上各位大佬的步伐#x1f648;#x1f648; 目录 前言一、list类的模拟实现1.1 list的… ️作者malloc不出对象 ⛺专栏C的学习之路 个人简介一名双非本科院校大二在读的科班编程菜鸟努力编程只为赶上各位大佬的步伐 目录 前言一、list类的模拟实现1.1 list的主体框架1.2 无参构造函数1.3 push_back1.4 正向迭代器1.5 反向迭代器1.6 insert1.7 erase1.8 clear1.9 析构函数1.10 构造函数1.11 赋值运算符重载1.12 empty1.13 front back1.14 完整代码 二、vector与list的对比 前言 本篇文章我们要来模拟实现的是list类它的底层是用带头结点的双向循环链表实现的。 一、list类的模拟实现 1.1 list的主体框架 既然我们是用双向循环链表实现的那么每个结点肯定都存储着next、prev与data信息那么接下来我们就来定义一个类对它的结点进行初始化操作。 templateclass T // 模板参数T struct list_node {list_nodeT* _next; //list_nodeT* 是类型list_nodeT* _prev;T _data;list_node(const T val T()) // 匿名对象初始化: _next(nullptr), _prev(nullptr), _data(val){} };我们把节点定义好之后我们就来定义list类了list类的成员变量只需要一个哨兵位的头结点就可以了。 template class T class list {typedef list_nodeT node; private:node* _head; // 哨兵位头节点 };1.2 无参构造函数 list() {_head new node; // 申请一个节点_head-_next _head; // _head-_next指向自己_head-_prev _head; // _head-_prev也指向自己 }1.3 push_back 双向链表的插入和删除都是非常好实现的因为每个结点都有上一个节点和下一个节点的信息。这里我们要想实现尾插我们要找到尾结点再改变它的指向就行了非常的简单这里我就不做过多的赘述了。另外后续在我们实现insert和erase之后全都可以进行复用这里只是先给大家打个样。 void push_back(const T x) {node* tail _head-_prev;node* newnode new node(x);tail-_next newnode;newnode-_prev tail;newnode-_next _head;_head-_prev newnode; }1.4 正向迭代器 有了尾插之后我们可以往链表里面插入数据下面我们想遍历一下链表我们知道list不支持[]下标访问原因是因为它是不连续的空间所以我们必须使用迭代器对它进行遍历。 我们知道在实现vector类(SGI版本)时我们的迭代器是作为一个原生指针来使用的而在vector类(P.J.版本)中我们的迭代器是自定义类型对原生指针的封装但本质上它们都是在模拟指针的行为那么在list类中迭代器到底充当什么角色呢我们知道迭代器支持 - -操作这是为了找到后一个数据和前一个数据的位置对于list而言它是双向链表它的空间是不连续的假设迭代器是一个原生指针的话指针 - -一步取决于指针所指向的类型对于不连续的空间来说 - -能否刚好指向下一个位置或者上一个位置一切都是未知数因此我们的迭代器在list中是对自定义类型原生指针的封装 我们先来看看SGI版本下对正向迭代器的封装源码 好了也许我们有些地方可能有些不太懂而且标准库的源码采用了非常多的命名替换这是命名规范的问题接下来我们模拟实现的时候不采用标准库这种方式我们尽量的实现简洁易懂些。 最原始的代码 templateclass T struct __list_iterator {typedef list_nodeT node;typedef __list_iteratorT self;node* _node;__list_iterator(node* x) // 初始化结点: _node(x){}T operator*(){return _node-_data;}T* operator-(){return _node-_data;}self operator(){_node _node-_next;return *this;}self operator(int){__list_iterator tmp *this;_node _node-_next;return tmp;}self operator--(){_node _node-_prev;return *this;}self operator--(int){__list_iterator tmp *this;_node _node-_prev;return tmp;}bool operator!(const self s){return _node ! s._node;}bool operator(const self s){return _node s._node;} };这是我们最原始的代码那么大家知道为什么源码为什么会多出两个模板参数吗这里我们实现的是正向迭代器那么我们要实现const正向迭代器版本呢难道要再去写一个__list_const_iterator类吗 显然这样出现了大量的代码重复我们是极其不支持这种实现方式的所以我们必须想办法让他们之间可以进行复用我们只需要改变一下返回值类型、参数类型就能实现iterator和const_iterator版本这里模板参数的作用就体现出来了我们可以添加一个模板参数到时候我们可以实例化一份iterator和const_iterator。至于第三个模板参数是为了重载-运算符函数的它同样的有T*版本和const T*版本。 为什么要重载-运算符 struct AA {int _a1;int _a2;AA(int a1, int a2): _a1(a1), _a2(a2){} };void test() {listAA lt;lt.push_back(AA(1, 1));lt.push_back(AA(2, 2));lt.push_back(AA(3, 3));listAA::iterator it lt.begin();while (it ! lt.end()){cout (*it)._a1 (*it)._a2 endl; it;}cout endl; }我们可以看到上诉代码对于一个自定义类型要想访问它的成员变量就必须得写成(*it)._a1、(*it)._a2先*it得到AA对象再访问它的成员变量这种写法是不是未免有些麻烦了我们平常可以直接使用-去访问它的成员变量就像这段代码我们可以写成it-_a1、it-_a2但是我们此时未重载-运算符所以为了方便使用这里我们还需要重载一下-运算符。 对于__list_iterator类我们可以重载-写出下面的代码 T* operator-() {return _node-_data; }但你有没有发现一些奇怪之处 好了关于为什么要重载-运算符这里我们已经讲清楚了那么为什么这跟添加第三个模板参数有什么关系呢原因很简单一个T*版一个const T*版添加第三个模板参数Ptr也是为了复用T*版本。 所以最终我们的__list_iterator可以写成这种版本 templateclass T, class Ref, class Ptr struct __list_iterator {typedef list_nodeT node;typedef __list_iteratorT, Ref, Ptr self;node* _node;__list_iterator(node* x) // 初始化结点: _node(x){}Ref operator*(){return _node-_data;}Ptr operator-(){return _node-_data;}self operator(){_node _node-_next;return *this;}self operator(int){self tmp(*this);_node _node-_next;return tmp;}self operator--(){_node _node-_prev;return *this;}self operator--(int){self tmp(*this);_node _node-_prev;return tmp;}bool operator(const self s){return _node s._node;}bool operator!(const self s){return _node ! s._node;}};我们在list类中就可以实例化iterator和const_iterator这两种版本的迭代器list类中迭代器的定义如下 typedef list_nodeT node; public:typedef __list_iteratorT, T, T* iterator;typedef __list_iteratorT, const T, const T* const_iterator;iterator begin(){return iterator(_head-_next);}const_iterator begin() const{return const_iterator(_head-_next);}iterator end(){return iterator(_head);}const_iterator end() const{return const_iterator(_head);} 我们来进行测试一下 我们可以看到对应的过程当listint显式声明模板类时此时我们的类模板就根据类型实例化出一个具体的类。 1.5 反向迭代器 我们知道C追求极致的性能既然能复用绝不会写出两份差不多的代码所以我们实现反向迭代器并不会像正向迭代器那样倒着来而是去复用正向迭代器 反向迭代器其实也是一种适配器它可以适配出各种容器的反向迭代器其中最重要的就是将正向迭代器作为底层结构来封装反向迭代器反向迭代器 就复用正向迭代器的 - -反向迭代器 - - 就复用正向迭代器的 。 我们的反向迭代器既然是作为适配器去使用那么我们就把它封装到单独的一个类中对它进行模拟实现并且正向迭代作为它的模板参数进行复用它的功能 反向迭代器的模拟实现 // iterator.h namespace curry {templateclass Iterator, class Ref, class Ptrstruct ReverseIterator{typedef ReverseIteratorIterator, Ref, Ptr Self;Iterator _cur; // _cur就是一个正向迭代器ReverseIterator(Iterator it) : _cur(it){}Ref operator*(){Iterator tmp _cur;--tmp;return *tmp;}Self operator(){--_cur;return *this;}Self operator(int){Self tmp *this;--_cur;return tmp;}Self operator--(){_cur;return *this;}Self operator--(int){Self tmp *this;_cur;return tmp;}// 返回当前对象的地址Ptr operator-(){return (operator*());}bool operator!(const Self s){return _cur ! s._cur;}bool operator(const Self s){return _cur s._cur;}}; }只要知道了反向迭代器与正向迭代器的特性我们就能够很容易的通过复用正向迭代器的成员函数来实现反向迭代器的成员函数同时反向迭代器其实解决了所有的双向迭代器的问题因为只要将对应容器的正向迭代器作为反向迭代器的模板参数我们就能够对反向迭代器进行复用所以我们之前的vector类的反向迭代器也能够直接使用它的正向迭代器复用实现这是一种非常巧妙的思想 1.6 insert void insert(iterator pos, const T x) {node* cur pos._node; // 当前位置node* prev cur-_prev; // 前一个位置node* newnode new node(x);prev-_next newnode;newnode-_prev prev;newnode-_next cur;cur-_prev newnode; }实现了insert接口函数那么我们的push_back与push_front都是可以复用的。 push_back(int x) void push_back(const T x) {insert(end(), x); }push_front(int x) void push_back(const T x) {insert(begin(), x); }list类与vector类的insert不同之处在于list类insert不会导致迭代器失效因为它的空间的不连续的并且没有挪动数据造成迭代器失效所以我们也可以看到它的返回值为void并不需要放回插入位置的迭代器。 1.7 erase iterator 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;return iterator(next); }迭代器失效即迭代器所指向的节点的无效即该节点被删除了所以对于list类的erase会导致指向删除节点的迭代器失效其他迭代器不会受到影响而vector类进行erase会导致当前位置或者后续迭代器失效所以正确的解决办法是给迭代器重新赋值 实现了erase函数接口pop_back()以及pop_front()就可以进行复用了。 pop_back() void pop_back() {erase(--end()); }pop_front() void pop_front() {erase(begin()); }1.8 clear void clear() {iterator it begin();while (it ! end()){it erase(it); // erase返回下一个位置的迭代器} }clear释放链表中的结点_head哨兵位头结点除外。 1.9 析构函数 ~list() {clear();delete _head;_head nullptr; }析构函数的作用是释放所有结点我们可以先调用clear依次释放链表中的结点最后再释放头结点。 1.10 构造函数 传统写法 void empty_init() {// 创建并初始化哨兵位头节点_head new node;_head-_prev _head;_head-_next _head; }// 拷贝构造传统写法 lt2(lt1) list(const listT lt) {empty_init();for (auto e : lt) // 加引用避免自定义类型的拷贝构造{push_back(e);} }现代写法 template class Iterator // 双向迭代器类型构造 list(Iterator first, Iterator last) {empty_init();while (first ! last){push_back(*first);first;} }void swap(listT tmp) {std::swap(_head, tmp._head); // 交换哨兵位的头节点 }// 拷贝构造现代写法 lt2(lt1) list(const listT lt) {empty_init(); listT tmp(lt.begin(), lt.end()); // 迭代器区间初始化swap(tmp); }1.11 赋值运算符重载 传统写法 listT operator(const listT lt) {if (this ! lt) // 防止自己给自己赋值{clear(); // 清理数据for (auto e : lt){push_back(e);}}return *this; }现代写法 listT operator(listT lt) {swap(lt);return *this; }一些常用的函数接口就讲到这里了还有一些简单的函数接口读者下来也可以自己去尝试实现一下。 1.12 empty bool empty() {return _head-_next _head _head-_prev _head; }1.13 front back T front() {assert(!empty());return *begin(); }const T front() const {assert(!empty());return *begin(); }T back() {assert(!empty());return *(--end()); }const T back() const {assert(!empty());return *(--end()); }1.14 完整代码 // list.h#include iterator.hnamespace curry {templateclass Tstruct list_node{list_nodeT* _next;list_nodeT* _prev;T _data;list_node(const T val T()): _next(nullptr), _prev(nullptr), _data(val){}};templateclass T, class Ref, class Ptrstruct __list_iterator{typedef list_nodeT node;typedef __list_iteratorT, Ref, Ptr self;node* _node;__list_iterator(node* x) // 初始化结点: _node(x){}Ref operator*(){return _node-_data;}Ptr operator-(){return _node-_data;}self operator(){_node _node-_next;return *this;}self operator(int){self tmp(*this);_node _node-_next;return tmp;}self operator--(){_node _node-_prev;return *this;}self operator--(int){self tmp(*this);_node _node-_prev;return tmp;}bool operator(const self s){return _node s._node;}bool operator!(const self s){return _node ! s._node;}};templateclass Tclass list{typedef list_nodeT node;public:typedef __list_iteratorT, T, T* iterator;typedef __list_iteratorT, const T, const T* const_iterator;typedef ReverseIteratoriterator, T, T* reverse_iterator;typedef ReverseIteratorconst_iterator, const T, const T* const_reverse_iterator;iterator begin(){return iterator(_head-_next);}reverse_iterator rbegin(){return reverse_iterator(_head);}const_iterator begin() const{return const_iterator(_head-_next);}const_reverse_iterator rbegin() const{return const_reverse_iterator(_head);}iterator end(){return iterator(_head);}reverse_iterator rend(){return reverse_iterator(_head-_next);}const_iterator end() const{return const_iterator(_head);}const_reverse_iterator rend() const{return const_reverse_iterator(_head-_next);}list(){empty_init();}// 现代写法list(const listT lt){empty_init();listT tmp(lt.begin(), lt.end());swap(tmp);}templateclass Iteratorlist(Iterator first, Iterator last){empty_init();while (first ! last){push_back(*first);first;}}listT operator(listT lt){swap(lt);return *this;}// 释放所有结点~list(){clear();delete _head;_head nullptr;}void swap(listT tmp){std::swap(_head, tmp._head);}// 释放结点但是_head头结点不处理void clear(){iterator it begin();while (it ! end()){it erase(it);}}void empty_init(){_head new node;_head-_next _head;_head-_prev _head;}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);prev-_next newnode;newnode-_prev prev;newnode-_next cur;cur-_prev newnode;}void pop_back(){erase(--end());}void pop_front(){erase(begin());}iterator 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;return iterator(next);}T front(){assert(!empty());return *begin();}const T front() const{assert(!empty());return *begin();}T back(){assert(!empty());return *(--end());}const T back() const{assert(!empty());return *(--end());}bool empty(){return _head-_next _head _head-_prev _head;}private:node* _head;}; }二、vector与list的对比 vector与list都是STL中非常重要的序列式容器由于两个容器的底层结构不同导致其特性以及应用场景不同其主要不同如下 vectorlist底层结构动态顺序表一段连续空间带头结点的双向循环链表随机访问支持随机访问访问某个元素效率O(1)不支持随机访问访问某个元素效率O(N)插入和删除任意位置插入和删除效率低需要搬移元素时间复杂度为O(N)插入时有可能需要增容增容开辟新空间拷贝元素释放旧空间导致效率更低任意位置插入和删除效率高不需要搬移元素时间复杂度为O(1空间利用率底层为连续空间不容易造成内存碎片空间利用率高缓存利用率高层节点动态开辟小节点容易造成内存碎片空间利用率低缓存利用率低迭代器原生态指针对原生态指针(节点指针)进行封装迭代器失效在插入元素时要给所有的迭代器重新赋值因为插入元素有可能会导致重新扩容致使原来迭代器失效删除时当前迭代器需要重新赋值否则会失效插入元素不会导致迭代器失效删除元素时只会导致当前迭代器失效其他迭代器不受影响使用场景需要高效存储支持随机访问不关心插入删除效率大量插入和删除操作不关心随机访问 以上就是本文的所有内容了如有错处或者疑问欢迎大家在评论区相互交流orz~

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

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

相关文章

装饰公司网站源码商务网站规划与设计实训心得

Telnet(Telecommunication Network)是一种基于文本的远程终端协议,允许用户通过网络连接到远程计算机,并在远程计算机上执行命令;它使用TCP作为传输层协议,并依赖于网络连接在客户端和服务器之间进行通信&a…

广州做创客教室的厂家网站网站开发视频是存储的

docker同一容器中不同服务以别名访问 1、创建bridge网络 docker network create testnet 2、查看Docker网络 docker network ls 3、运行容器连接到testnet网络 使用方法&#xff1a;docker run -it --name <容器名> —network --network-alias <网络别名> <…

深入解析:基于 Kubernetes 的湖仓一体架构部署指南

深入解析:基于 Kubernetes 的湖仓一体架构部署指南2025-09-22 18:39 tlnshuju 阅读(0) 评论(0) 收藏 举报pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; disp…

电脑网站设计页面网站的图形拖拽验证码怎么做的

组成部分&#xff1a; 1. 文档声明1. 格式&#xff1a;<?xml 属性列表 ?>2. 属性列表&#xff1a;* version&#xff1a;版本号&#xff0c;必须的属性* encoding&#xff1a;编码方式。告知解析引擎当前文档使用的字符集&#xff0c;默认值&#xff1a;ISO-8859-1* st…

完整教程:真空发生器的工作原理

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

淄博网站建设淄博wordpress 商品 模板

大家好&#xff0c;我是烤鸭:今天分享的是java 和 php des 加密。因为接口对接&#xff0c;难免不同语言&#xff0c;加密又是必不可少的。作为接口的提供方&#xff0c;必须把加密规则写好&#xff0c;最好有不同语言的加密demo。1. java版本的des加密解密工具类DESTools.j…

深圳网站建设黄浦网络-骗钱专业网站建设的

jboss eclipse您是否编写有错误的代码&#xff1f; 不&#xff0c;当然不是。 对于我们其余的人&#xff0c;他们确实会编写带有bug的代码&#xff0c;我想解决一个非常敏感的问题&#xff1a;调试在生产服务器上运行的应用程序。 因此&#xff0c;您的应用程序已准备好进行部…

网站名称 如何注册沈阳市住房和城乡建设局网站

下载安装ECharts&#xff0c;完成如下样式图形。 代码和截图上传 完成 3.1.3.5 图的标记线和标记点 中的任务点 在一些折线图或柱状图当中&#xff0c;可以经常看到图中对最高值和最低值进行了标记。 在ECharts中&#xff0c;标记点&#xff08;markPoint&#xff09;常用于表示…

湖北自适应网站建设报价建设银行客户端官方网站

在互联网技术飞速发展的今天&#xff0c;各种技术席卷而来&#xff0c;总是让人感觉压力山大。作为.NET开发者&#xff0c;我们该如何刷新自己&#xff0c;实现价值的提升呢&#xff1f;2019年.NET中国开发者峰会之后&#xff0c;我们汇总了.NET技术圈一些优秀开发者的公众号&a…

ftp怎么连接网站网页在线制作app

描述 给一个长度为n链表&#xff0c;若其中包含环&#xff0c;请找出该链表的环的入口结点&#xff0c;否则&#xff0c;返回null。 数据范围&#xff1a; &#x1d45b;≤10000n≤10000&#xff0c;1<结点值<100001<结点值<10000 要求&#xff1a;空间复杂度 &…

国内电商平台怎么做网站优化建设河南

eclipse使用指南 eclipse下载地址&#xff1a; 1、eclipse快捷键 2、将eclipse新建项目的默认编码GBK改为UTF-8 3、Java 编程下 Eclipse 如何设置单行代码显示的最大宽度 4、使用Eclipse创建模板并格式化代码5、Java compiler level does not match the version of the install…

长春省妇幼网站做四维专业建站培训

题目描述 一个n*m矩阵由n行m列共n*m个数排列而成。两个矩阵A和B可以相乘当且仅当A的列数等于B的行数。一个N*M的矩阵乘以一个M*P的矩阵等于一个N*P的矩阵&#xff0c;运算量为nmp。 矩阵乘法满足结合律&#xff0c;A*B*C可以表示成(A*B)*C或者是A*(B*C)&#xff0c;两者的运算…

每日博客

今天做什么:今天上午上算法课和数据结构课,下午上java课 遇到的问题:没有问题

seo网站查询工具哈尔滨市工程建设招投标网

文章目录 前言1. ubuntu安装VNC2. 设置vnc开机启动3. windows 安装VNC viewer连接工具4. 内网穿透4.1 安装cpolar【支持使用一键脚本命令安装】4.2 创建隧道映射4.3 测试公网远程访问 5. 配置固定TCP地址5.1 保留一个固定的公网TCP端口地址5.2 配置固定公网TCP端口地址5.3 测试…

【分布式架构实战】Spring Cloud 与 Dubbo 深度对比:从架构到实战,谁才是微服务的王者? - 详解

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

探展打卡 Serverless,2025 云栖大会来了

2025 云栖大会即将于 9 月 24 日至 26 日在杭州云栖小镇盛大开幕,本次大会分别设置 Serverless 体验区与【Serverless 助力 AI Agent 开发与落地】分论坛,参会者可现场体验热门 Serverless 产品,近距离了解最新技术…

从 0 到 1,AI 走进服装店:记住每位顾客的喜好,比你还靠谱

原文: https://mp.weixin.qq.com/s/lrodWLbUiJ12O-p_ZsL6XA 一个店长的烦恼 最近这段时间,“机器人” 相关的话题几乎刷屏了社交平台 —— 会跑步的人形机器人、紧张刺激的机器人拳击比赛,各种黑科技场景让人目不暇接…

STM32HAL 飞快入门(十九):UART 编程(二)—— 中断方式实现收发及局限分析

STM32HAL 飞快入门(十九):UART 编程(二)—— 中断方式实现收发及局限分析pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-fa…

有关网站建设的外文参考文献公司装修报价

vp9协议梳理-header头文件 本文是对vp9视频码流中header中包含的语法元素的一个分类整理&#xff0c;及其对具体的解码过程的影响的分析。 这里写目录标题 vp9协议梳理-header头文件1. Vp9码流中的header头文件2. profile3. show_existing_frame, frame_to_show_map_idx4. fr…

做兽设的网站wordpress网盘主题

高级分布式系统汇总&#xff1a;高级分布式系统目录汇总-CSDN博客 自动化是关于一切人造系统自动、智能、自主、高效和安全运行的科学与技术 计算机控制技术是实现自动化的主要方法和手段 分布式控制技术是伴随着机器大工业生产而诞生的特殊计算机控制技术 计算机控制系统 …