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

html5手机网站教程关键词优化心得

html5手机网站教程,关键词优化心得,东莞品牌网站建设,工作细胞black目录 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/222419.html

相关文章:

  • 比特币交易网站开发北京网站优化技术
  • 织梦装修公司网站模板学大教育培训机构怎么样
  • 小商品网站建设排名优化关键词公司
  • 产品网站推广方案推广链接
  • 网站开发设计前景深圳seo外包公司
  • 网站建设一般用什么语言好网络营销软件排行
  • 住宅和城乡建设部网站西安网站关键词优化费用
  • 北京企业建设网站公司哪家好调研报告万能模板
  • 岳阳网站建设公司兰州seo外包公司
  • 深圳龙岗网站建设公司网站策划书模板
  • 企业电子商务网站建设总结搜索引擎优化培训班
  • 深圳网站建设做一个公司网站要多少钱东莞网络营销渠道
  • 沧州网站建设自己的网站怎么样推广优化
  • 做网站需要撑握哪些技术长沙seo运营
  • 淘宝优惠网站如何做软件制作
  • 邯郸市教育考试院官网优化加速
  • 网站建设的整体流程seo主要做什么
  • 图书网站建设的规模策划书近期国内新闻热点事件
  • 没注册可以做网站吗武汉百度推广公司
  • 大气html5网络公司网站源码千锋教育北京校区
  • 网站建设教程txt老域名
  • 直销网站建设 优帮云百度网盘客服电话人工服务
  • 公司网站开发费账务处理做网站公司哪家比较好
  • 公司网站建设情况说明北京网站seo哪家公司好
  • 视频网站制作费用手机端seo
  • 有什么做数学题的网站百度售后电话人工服务
  • 公司内部网站建设奖励办法兰州压热搜
  • php语言做网站网站建设维护
  • 当当网站建设优点美国seo薪酬
  • 模版网站怎么做推广软件赚钱的平台