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

厦门手机网站设计公司seo专业培训需要多久

厦门手机网站设计公司,seo专业培训需要多久,香港服务器要不要备案,湖州做网站建设的公司目录 1.list的定义 2.迭代器 2.1基本功能实现 2.2const迭代器 2.2.1基本迭代器的完善 2.2.2const迭代器的基本实现 2.2.3模板优化语法 2.3自定义类型数据迭代器 2.3.1使用情景 2.3.2嵌套类模板 3.其他接口的实现 3.1insert与erase 3.2头插与头删 3.3析构与拷贝构造…

目录

1.list的定义

2.迭代器

2.1基本功能实现

2.2const迭代器

2.2.1基本迭代器的完善

2.2.2const迭代器的基本实现

2.2.3模板优化语法

2.3自定义类型数据迭代器

2.3.1使用情景

2.3.2嵌套类模板

3.其他接口的实现

3.1insert与erase

3.2头插与头删

3.3析构与拷贝构造

3.4赋值运算符重载与构造扩展


1.list的定义

STL中的list容器不同于数据结构中常见的单链表,而是一种带头双向链表,因此在实现过程中也以此结构为基础实现。对于链表,最基本的便的其结点,因此我们先实现结点的定义:

template<class T>
struct _list_node
{T val;_list_node* next;_list_node* prev;
};

 完成结点的定义后,我们便成将list容器抽象为以头结点(哨兵位)为头的多结点链,结点间能通过彼此互相访问。因此list的成员变量便是头结点(_head)。

对list进行初始化,因是带头双向链表,因此初始化就是将头结点初始化为一个next与prev都指向头的结点,但在这之前需要给_head申请(new)一个结点(Node)的空间,new自定义类型的时候会调用结点类的构造函数,因此这时还需要完善结点类的构造函数

//结点
template<class T>
struct _list_node
{T val;_list_node* next;_list_node* prev;//完善构造_list_node():val(0),next(nullptr),prev(nullptr){}
};//list链表
template<class T>
class list
{
public:typedef _list_node<T> Node;//构造list(){_head = new Node;_head->next = _head;_head->prev = _head;}private:Node* _head;
};

2.迭代器

2.1基本功能实现

迭代器的基本功能就是通过类指针的形式来遍历容器元素,对于vector这种底层为数据的容器,可以用最简单的指针来完成迭代器的封装,而list这种底层非连续空间的容器,则需要将遍历的方式封装为一种迭代器类。初步接触迭代器封装,可以通过使用来逐步实现:

namespace my_list
{void test01(){list<int> lt1;list<int>::iterator it = lt1.begin();while (it != lt1.end()){cout << *it << ' ';++it;}cout << endl;}
}

迭代器最基本的使用无非就是要完成上面的功能,list最基本元素是结点,因此迭代器成员变量代表的也应是结点, 接下来要实现的便是++迭代器能完成指向下一个结点,迭代器解引用能返回结点中的值。代码如下:

	//迭代器(一、初代)template<class T>struct _list_iterator{typedef _list_node<T> Node;Node* _node;_list_iterator(Node* node):_node(node){}T& operator*(){return _node->val;}_list_iterator<T> operator++(){_node = _node->next;return *this;}bool operator!=(const _list_iterator<T>& it)//注意不能使用非const引用{return _node != it._node;}};//list链表template<class T>class list{public:typedef _list_node<T> Node;typedef _list_iterator<T> iterator;//构造list(){_head = new Node;_head->next = _head;_head->prev = _head;}//迭代器iterator begin(){return iterator(_head->next);}iterator end(){return iterator(_head);}private:Node* _head;};

这里需要注意的是begin与end的返回值为临时对象(具有常性)不能用非const引用来接受,因此在!=重载函数中的参数选择为const引用。

下面通过push_back插入数据来检验一下:

void push_back(const T& x)
{Node* newnode = new Node;newnode->val = x;newnode->next = _head;newnode->prev = _head->prev;_head->prev->next = newnode;_head->prev = newnode;
}
namespace my_list
{void test01(){list<int> lt1;lt1.push_back(1);lt1.push_back(2);lt1.push_back(3);lt1.push_back(4);lt1.push_back(5);list<int>::iterator it = lt1.begin();while (it != lt1.end()){cout << *it << ' ';++it;}cout << endl;}
}int main()
{my_list::test01();return 0;
}

运行结果如下:

这里也算基本完成迭代器功能。

2.2const迭代器

2.2.1基本迭代器的完善

在完成const迭代器前,先对之前的基本迭代器进行完善,即完善相对应的运算符重载。

_list_iterator<T> operator++(int)
{_list_iterator<T> tmp(*this);_node = _node->next;return *this;
}_list_iterator<T>& operator--()
{_node = _node->prev;return *this;
}_list_iterator<T> operator--(int)
{_list_iterator<T> tmp(*this);_node = _node->prev;return tmp;
}bool operator== (const _list_iterator<T>& it)
{return _node == it._node;
}

2.2.2const迭代器的基本实现

const迭代器的功能是迭代器可以修改,但让迭代器指向的内容不能修改。因此这里的迭代器不能像vector中的直接在iterator前加const修饰,因为vector中迭代器底层是指针,const修饰的实际是指针类型;而list中迭代器是一种自定义类型,使用const修饰的效果为迭代器不能修改,但迭代器指向的内容可以修改。

因此这里要实现const迭代器功能主要是让解引用返回的对象不能修改,也就是让返回值变为const T&即可。

但这里的iterator需变为const_iterator,类的类型发生了改变,因此这里需要再重新创建一个const迭代器类:

//二、const迭代器
template<class T>
struct _list_iterator
{typedef _list_node<T> Node;Node* _node;_list_iterator(Node* node):_node(node){}T& operator*(){return _node->val;}_list_iterator<T> operator++(){_node = _node->next;return *this;}bool operator!=(const _list_iterator<T>& it){return _node != it._node;}_list_iterator<T> operator++(int){_list_iterator<T> tmp(*this);_node = _node->next;return *this;}_list_iterator<T>& operator--(){_node = _node->prev;return *this;}_list_iterator<T> operator--(int){_list_iterator<T> tmp(*this);_node = _node->prev;return tmp;}bool operator== (const _list_iterator<T>& it){return _node == it._node;}
};template<class T>
struct _list_const_iterator
{typedef _list_node<T> Node;Node* _node;_list_const_iterator(Node* node):_node(node){}_list_const_iterator(const _list_iterator<T>& it):_node(it._node){ }const T& operator*(){return _node->val;}_list_const_iterator<T> operator++(){_node = _node->next;return *this;}bool operator!=(const _list_const_iterator<T>& it){return _node != it._node;}_list_const_iterator<T> operator++(int){_list_const_iterator<T> tmp(*this);_node = _node->next;return *this;}_list_const_iterator<T>& operator--(){_node = _node->prev;return *this;}_list_const_iterator<T> operator--(int){_list_const_iterator<T> tmp(*this);_node = _node->prev;return tmp;}bool operator== (const _list_const_iterator<T>& it){return _node == it._node;}
};

list中迭代器相关函数const重载如下:

//迭代器
iterator begin()
{return iterator(_head->next);
}iterator end()
{return iterator(_head);
}const_iterator begin()const
{return const_iterator(_head->next);
}const_iterator end()const
{return const_iterator(_head);
}

在const迭代器类中为支持非const迭代器转换为const迭代器,重载了使用迭代器初始化的拷贝构造。

这里能不能将代码进行简化呢?

2.2.3模板优化语法

const迭代器仅仅是在解引用时返回值不同,按前面写法便要写两个类。若这时将解引用返回的类型用模板表示,这时通过不同的模板实例化也能区分两种类。具体实现方法如下:

//二、const迭代器
template<class T, class Ref>
struct _list_iterator
{typedef _list_node<T> Node;typedef _list_iterator<T, Ref> Self;Node* _node;_list_iterator(Node* node):_node(node){}_list_iterator(const _list_iterator<T, T&>& it):_node(it._node){}Ref operator*(){return _node->val;}Self operator++(){_node = _node->next;return *this;}bool operator!=(const Self& it){return _node != it._node;}Self operator++(int){Self tmp(*this);_node = _node->next;return *this;}Self& operator--(){_node = _node->prev;return *this;}Self operator--(int){Self tmp(*this);_node = _node->prev;return tmp;}bool operator== (const Self& it){return _node == it._node;}
};

这样通过模板实例化的不同也能实现const迭代器与普通迭代器的分离。

2.3自定义类型数据迭代器

2.3.1使用情景

list作为一种顺序容器,除储存内置类型外,也可储存自定义类型,如储存位置数据(Pos):

struct Pos
{int _row;int _col;Pos(int row = 0, int col = 0):_row(row),_col(col){}
};void test02()
{list<Pos> lt1;list<Pos>::iterator it = lt1.begin();while (it != lt1.end()){}
}

对于这种自定义类型,重载的解引用出来是Pos结构体,要访问其中数据还要自己处理:

void test02()
{list<Pos> lt1;lt1.push_back({ 1,1 });lt1.push_back({ 2,2 });lt1.push_back({ 3,3 });list<Pos>::iterator it = lt1.begin();while (it != lt1.end()){cout << (*it)._row << ':' << (*it)._col << endl;++it;}
}

但在STL库中,迭代器对于这种自定义类型还提供了类似结构体指针的访问方法:

但对于我们自己的list容器,迭代器并不是指向该自定义类型指针,因此这里实际是对->运算符的重载。->的重载实际是要返回Pos的指针,这里为了区分const与非const,依旧使用模板优化语法。 

template<class T, class Ref, class Ptr>
struct _list_iterator
{typedef _list_node<T> Node;typedef _list_iterator<T, Ref, Ptr> Self;Ptr operator->(){return &(_node->val);}
};

但这里需要注意:->重载后返回的是结构体的指针,即整个it->代表的是结构体指针,原则上需要在it->后再使用->调用数据,但编译器简化成了一个->。

2.3.2嵌套类模板

先来看看下面场景:

template <class T>
void Print(const list<T>& lt)
{list<T>::const_iterator it = lt.begin();while (it != lt.end()){cout << *it << ' ';++it;}cout << endl;
}

运行结果如下:

可以看到这种写法是错误的,原因是在类模板未实例化时,不能去找类模板后面东西,编译器分不清const_iterator是嵌套内类,还是静态成员变量。这时可以用typename告诉编译器这里是类型:

template <class T>
void Print(const list<T>& lt)
{typename list<T>::const_iterator it = lt.begin();while (it != lt.end()){cout << *it << ' ';}cout << endl;
}

当然也可以用auto接收迭代器:

auto it = lt.begin();

3.其他接口的实现

在实现完迭代器后,便能接着实现许多依托于迭代器功能的接口。

3.1insert与erase

insert与erase接口实现逻辑类似:

iterator insert(const iterator& pos, const T& x)
{Node* newnode = new Node(x);Node* cur = pos._node;newnode->prev = cur->prev;newnode->next = cur;cur->prev->next = newnode;cur->prev = newnode;return iterator(newnode);
}iterator erase(const iterator& pos)
{Node* next = pos._node->next;Node* prev = pos._node->prev;next->prev = prev;prev->next = next;delete pos._node;return iterator(next);
}

3.2头插与头删

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

3.3析构与拷贝构造

void empty_init()
{_head = new Node;_head->next = _head;_head->prev = _head;
}//构造
list()
{empty_init();
}list(const list<T>& lt)
{empty_init();const_iterator it = lt.begin();while (it != lt.end()){push_back(*it);++it;}
}~list()
{clear();delete _head;_head = nullptr;
}void clear()
{iterator it = begin();while (it != end()){it = erase(it);}
}

3.4赋值运算符重载与构造扩展

list(std::initializer_list<T> il)
{empty_init();for (const auto& e : il){push_back(e);}
}//赋值重载
void swap(list<T>& lt)
{if (this != &lt){std::swap(_head, lt._head);}
}list<T>& operator=(list<T> lt)
{swap(lt);return *this;
}

http://www.dtcms.com/wzjs/298384.html

相关文章:

  • 网站做后台教程网站如何在百度刷排名
  • logo设计 效果图广东知名seo推广多少钱
  • 项目立项查询平台企业站seo价格
  • 做英文网站要做适合已经的头条新闻 最新消息条
  • 响应式公司网站生哥seo博客
  • 网站导航条模板品牌全案营销策划
  • 园林景观设计公司的培训手册模板网站seo优化怎么做
  • c 做网站优点建立自己的网站平台
  • 用html做简单网站seo每日一帖
  • 网上做网站赚钱吗西安百度推广运营公司
  • 滨江道网站建设深圳seo技术
  • 官网源码下载网页优化方案
  • 网站建设评估潍坊网站收录
  • 易语言网站批量注册怎么做seo网站推广助理招聘
  • 免费建站免费的免费友情链接适用网站
  • 武汉生活网抖音seo排名优化公司
  • 外国做刹车片的企业网站简述什么是seo
  • 租整套房做民宿的网站搜索引擎成功案例分析
  • dede多个网站怎么做百度搜索关键词排名
  • 网站开发用哪个框架b站广告投放平台入口
  • 成都网站开发公司有哪些广东短视频seo营销
  • 学校网站建设步骤过程查询网站
  • 网站首页被降权的原因吴中seo网站优化软件
  • 银川做网站设计的公司怎么样引流加微信
  • 文登市城乡建设局网站山东关键词网络推广
  • 淘宝有做钓鱼网站的吗制作网站的最大公司
  • 在网站上做支付功能 需要什么企业网站优化报告
  • 做单平台网站制作所有代刷平台推广
  • 建设政府网站的原因西安seo报价
  • 做网站时用插件需要注明吗深圳网络推广专员