当前位置: 首页 > wzjs >正文

北京网站建设要多少钱hexo用wordpress

北京网站建设要多少钱,hexo用wordpress,软文广告经典案例300大全,为什么要用h5建站目录 节点篇 迭代器篇 链表篇 构造函数 拷贝构造函数 赋值重载 迭代器 析构函数 插入和删除 补充篇 迭代器失效 节点中的数据自定义类型的情况 节点篇 链表中的节点包含储存的数据、前一个节点的指针、后一个节点的指针。在实现节点时还要将其初始化。那么这里我们…

目录

节点篇

迭代器篇

链表篇

构造函数

拷贝构造函数

赋值=重载

迭代器

析构函数

插入和删除

补充篇

迭代器失效

节点中的数据自定义类型的情况


节点篇

链表中的节点包含储存的数据前一个节点的指针后一个节点的指针。在实现节点时还要将其初始化。那么这里我们不知道模板参数T具体是什么类型,就给了一个缺省参数,使用T的构造函数初始化生成一个匿名对象作为val的默认值,使用const T&延长了匿名对象的生命周期。

特别注意一点,初始化列表的写法,第一行的:别写成了;。

//T是节点中存储的数据类型template <class T>//节点结构struct List_Node{//节点中包含的元素List_Node* _next;List_Node* _prev;T _data;//构造函数初始化节点//初始化列表:别写成;了!!!!!!!!!!!!!!!List_Node(const T& val = T()): _next(nullptr), _prev(nullptr), _data(val){}};

迭代器篇

链表中的迭代器与vector中的有所不同。

后者的迭代器只是一个单纯的指向数组内容的指针,由于数组的空间是连续的,所以可以满足迭代器的++,--,*等需求,但是这里链表的节点空间不是连续的,无法满足迭代器的基本需求,所以不能将迭代器定义为单纯的指向节点内容的指针。

于是聪明的人们用一个结构体模板来封装迭代器,并在结构体里面重载运算符,来实现迭代器的基本操作。

首先我们需要一个成员来表示此时指向的节点的指针,并用这个节点的指针来初始化该成员,这个成员的类型肯定也是节点的指针。

接下来我们就要完成一些符号的重载,来满足迭代器的操作需求。

还有一个问题就是不仅仅有普通迭代器iterator还要有const_iterator,为了简化代码,在实现时不实现两个模板结构体,就多使用了两个模板参数Ref和Ptr

比如说在重载*时,普通情况下我们拿到的是T&就是节点储存的数据的引用(为什么不直接返回T?原因是我们要修改内容,而返回T拿到的只是一个临时副本,无法修改),但是有时我们不希望他被修改就需要返回const T&,所以为了方便就使用Ref来替代,使用Ptr来替代也是同理。

template <class T,class Ref,class Ptr>struct list_iterator{typedef List_Node<T> node;typedef list_iterator<T, Ref, Ptr> Self;node* _node;list_iterator(node* Node):_node(Node){}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;}};

链表篇

链表的成员变量主要包含头节点的指针节点个数

构造函数

构造函数的主要目的就是创建一个头节点出来,为了简化实现不同构造函数时的代码,将构造头节点的主要过程封装在函数empty_init()中。

默认构造函数里面会new一个node大小的空间,并会调用node的默认构造函数把这个节点初始化,同时返回这个空间的地址给_head,然后再改变_next和_prev的指向,并将_size置为0。

使用花括号{}构造的构造函数List(std::initializer_list<T> il),内部同样会使用empty_init(),然后再将花括号{}中的内容尾插过来。

        void empty_init(){//初始化头节点_head = new node;_head->_next = _head;_head->_prev = _head;_size = 0;}List(){empty_init();}List(std::initializer_list<T> il){empty_init();for (auto& e : il){push_back(e);}}

拷贝构造函数

1.调用empty_init()初始化头节点。

2.尾插链表内容。

        List(List<T>& lt){empty_init();for (auto& t : lt){push_back(t);}}

赋值=重载

和vector中的赋值重载类似,需要实现一个swap函数来交换链表中的内容。

当lt2给lt1赋值,首先会调用拷贝构造将lt2的内容拷贝给lt,将lt1的内容和lt交换,出了作用域lt就会销毁机lt1之前的空间就被销毁,而此时的lt1指向的就是拷贝构造出来的lt指向的空间。

		void swap(List<T>& lt){std::swap(_head, lt._head);std::swap(_size, lt._size);}//lt1 = lt2List<T>& operator=(List<T> lt){swap(lt);return (*this);}

迭代器

在链表中需要提供迭代器接口供外部使用。

那么如何在类中使用我们定义的迭代器结构体?如何将迭代器结构体和链表类联系起来呢?

解决方法是使用typedef将模板实例化的复杂类型嵌套定义为类的成员类型在类中有了成员类型就可以使用这个成员类型来定义变量了

		typedef list_iterator<T, T&, T*> iterator;typedef list_iterator<T, const T&, const T*> const_iterator;

为了满足使用需求,还需要提供供外部使用的迭代器,分为普通迭代器const迭代器这里返回的是一个调用迭代器类中的构造函数的匿名对象。

本来的过程是,先在函数内构造匿名对象,然后通过拷贝构造函数将这个匿名对象拷贝到返回值位置,最后匿名对象被销毁。

编译器优化后变为,直接在返回值的内存位置构造这个匿名对象,完全跳过了临时对象的创建和拷贝步骤。

		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);}

析构函数

链表的各个节点不是存在于一块连续的空间, 空间没法一次性释放,必须将节点逐个释放。所以要实现一个函数clear()来释放链表中各个节点(头节点除外,因为clear()不止用在析构函数中)的空间。将头节点空间释放。

		~List(){clear();delete _head;_head = nullptr;_size = 0;}void clear(){auto it = begin();while (it != end()){it = erase(it);}}

插入和删除

插入和删除的函数之间都有很强的复用性。实现节点的插入和删除,只需改变目标节点的_prev和_next即可,插入要创建节点空间,删除要释放节点空间。

		void push_back(const T& val){/*node* newnode = new node(val);node* tail = _head->_prev;tail->_next = newnode;newnode->_next = _head;newnode->_prev = tail;_head->_prev = newnode;_size++;*/insert(end(), val);_size++;}void push_front(const T& val){insert(begin(), val);}void pop_back(){erase(--end());}void pop_front(){erase(begin());}void insert(iterator pos, const T& val){node* pcur = pos._node;node* prev = pcur->_prev;node* newnode = new node(val);newnode->_prev = prev;newnode->_next = pcur;prev->_next = newnode;pcur->_prev = newnode;_size++;}iterator erase(iterator pos){assert(pos != end());node* pcur = pos._node;node* prev = pcur->_prev; node* next = pcur->_next;prev->_next = next;next->_prev = prev;delete pcur;--_size;//erase删完返回下一个节点的地址return next;}

补充篇

迭代器失效

list的erase在使用过后会将pos指向的那块空间释放并置为nullptr,那删除后就无法执行迭代器的相关操作,所以要在erase函数中返回下一个节点的地址,在循环中连续使用erase时就要重新给迭代器赋值

		while (it != lt.end()){//删除偶数if (*it % 2 == 0){//迭代器失效了,重新赋值it = lt.erase(it);}else{it++;}}

节点中的数据自定义类型的情况

	struct AA{int a1;int a2;AA(int a = 0, int b = 3):a1(a), a2(b){}};void test02(){//当链表节点存储的数据是自定义类型时List<AA> lt;AA aa = { 1,2 };lt.push_back(aa);List<AA>::iterator it = lt.begin();//for (auto& e : lt)//{//	//e开始拿到的是lt的begin()迭代器,而这个迭代器呢指向的内容是一个自定义类型//	//而库中的<<只能打印内置类型,如果要打印就要在AA中重载<<//	cout << e << " ";//}while(it != lt.end()){//(*it)是一个自定义类型AA,自定义类型访问成员变量用.操作符cout << (*it).a1 << " " << (*it).a2 << " ";//自定义类型的指针可以通过->来访问成员函数和成员变量//it是一个迭代器,底层是一个指针,其初始化成lt的第一个节点的指针//那么it的内容就是一个指针,通过->可以访问节点的内容,这个内容就包含了T _data(自定义类型的对象的指针)//这个_data是一个指针变量,即AA的对象aa的地址//所以要访问aa中的a1,a2就要再次使用->//为了易读性,这里省略一个->cout << it->a1 << " " << it->a2 << " ";//本质是cout << it.operator->()->a1 << " " << it.operator->()->a2 << " ";it++;}}}

"希望这篇内容能帮你少走弯路。保持好奇,持续编码!🚀" 

 

  


文章转载自:

http://qb179Pyj.gqnLL.cn
http://CiLqB5WF.gqnLL.cn
http://X0lDBBbs.gqnLL.cn
http://UvkGxC8v.gqnLL.cn
http://nKZH7CDA.gqnLL.cn
http://g8X4UpKU.gqnLL.cn
http://NOziCjVS.gqnLL.cn
http://ZnO8r8B8.gqnLL.cn
http://sYqGExY6.gqnLL.cn
http://Zx0Tbv3P.gqnLL.cn
http://hilnXUGl.gqnLL.cn
http://vcrQ7tA6.gqnLL.cn
http://1SMHOoaF.gqnLL.cn
http://iXL1h75y.gqnLL.cn
http://o6ucFK6G.gqnLL.cn
http://66o1Pv14.gqnLL.cn
http://1QeehB1X.gqnLL.cn
http://J49fNfj3.gqnLL.cn
http://9v2XWBq5.gqnLL.cn
http://O2ZmeHkW.gqnLL.cn
http://eR5mUvUI.gqnLL.cn
http://T4cs77D1.gqnLL.cn
http://eUpnA30c.gqnLL.cn
http://mSXBrEHh.gqnLL.cn
http://EecutUGa.gqnLL.cn
http://PXITl7NZ.gqnLL.cn
http://uLWNLfiS.gqnLL.cn
http://55irbNmH.gqnLL.cn
http://mN4WP5Vu.gqnLL.cn
http://HvBfepgh.gqnLL.cn
http://www.dtcms.com/wzjs/631117.html

相关文章:

  • 织梦网站后台怎么登陆宁夏做网站好的公司
  • 网站建设etwlamp wordpress主题
  • 开网站做一个交易所怎么做深圳全网推广服务
  • 涂料网站模版做手机网站公司
  • 做网站需要租服务器跨境电商怎么注册开店
  • 建立网站 营业执照wordpress英文主题适合小白用吗
  • 规划网站需要几个步骤网站制作过程合理的步骤是
  • 清远做网站的ui模板网站
  • 杭州餐饮 网站建设婚纱摄影东莞网站建设技术支持
  • 重庆网站建设推广公司哪家好建立网站很重要的要素是什么
  • 答题卡在线制作网站网络营销方法的典型案例
  • 英文公司网站模板东莞 网站 建设 汽车
  • 化妆品网站html模板江苏省建设局网站
  • 浙江省工程建设监理管理协会网站行业门户网站有哪些
  • 湖北做网站系统哪家好做网站域名后缀选择
  • 湖北山河建设集团网站怎么做卡商网站
  • 做淘宝网站的有哪些大站用wordpress
  • 在喵窝网站怎么做图wordpress使用七牛云
  • 网站开源是什么意思设计者人才网官网
  • 网站建设费用预算表、网站开发的好处和弊端
  • 上海大型网站建设公司排名成品网站整套源码
  • 公众号的微网站怎么做的中天会展中心网站建设方案
  • 找人做网站注意什么问题品牌策划方案ppt
  • 宁波网站推广代运营wordpress ss
  • 做电脑网站步骤有几个网站打不开
  • 做网站找哪家最好网络运营者不得违反法律
  • 白酒企业网站源码wordpress用户导入数据库表
  • 网站域名如何备案网站设计欣赏导航
  • 黔西南州网站建设销氪crm
  • 黑色大气金融投资企业网站模板百度给做的网站如何登陆网站后台