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

中文网站建设英文网站建设晋中住房与城乡建设厅网站

中文网站建设英文网站建设,晋中住房与城乡建设厅网站,wordpress最多多少用户,接外贸订单的平台本章是STL容器 list 的模拟实现。 之前已经使用 C语言 对带头双向循环链表 进行实现#xff0c;详见数据结构: 线性表(带头双向循环链表实现), 相较于之前的实现#xff0c;C 下多了对迭代器以及模板等相关语法特性。下面将着重讲解这些新知识。 文章目录 一. list 的基本框架…本章是STL容器 list 的模拟实现。 之前已经使用 C语言 对带头双向循环链表 进行实现详见数据结构: 线性表(带头双向循环链表实现), 相较于之前的实现C 下多了对迭代器以及模板等相关语法特性。下面将着重讲解这些新知识。 文章目录 一. list 的基本框架1. 结点的结构2. 链表初始化3. push_back 尾插 二. list 迭代器的实现1. 迭代器的结构2. ,--,*,,!3. -4. 利用模板实现const迭代器 三. 完整代码list.htest.cpp 一. list 的基本框架 1. 结点的结构 n个结点链接成一个链表首先要构造结点的结构C语言中结点是这样定义的 虽然可以用 typedef 使得该结点可以存放不同的数据类型但是如果在一个程序中有两个不同数据类型的链表就需要再重新创建新的结点结构体与此同时链表的相关操作也需要进行重新创建。这样一个程序中就有两个近乎相同的一长串代码C 的模板此时就给了完美的解决方案 // ListNode template typename T struct ListNode {ListNodeT *_next; // 指向后继结点的指针ListNodeT *_prev; // 指向前驱结点的指针T _data; // 存放结点的数据 };通过类模板即可以在创建链表的时候指定结点的类型以此推导出 T 的类型。 由于 C 中的关键字 struct 升级成了一个类, 这样就可以通过创建结点类的默认构造函数来实现结点的默认初始化。 STL 中 list 是一个带头双向循环链表那么结点初始化的时候可以使其的前驱和后继都指向空指针, 同时数据域的初始化调用结点类型的默认构造函数。 // ListNode template typename T struct ListNode {ListNodeT *_next; // 指向后继结点的指针ListNodeT *_prev; // 指向前驱结点的指针T _data; // 存放结点的数据ListNode(const T val T()) // 全缺省构造: _next(nullptr), _prev(nullptr), _data(val){} };2. 链表初始化 设计完结点的结构接下来就是 List 类的构建, 为了方便使用使用 typedef 对 ListNodeT 进行重命名。 List 只有一个成员就是指向头结点即哨兵位的指针。 构造函数也可以写出来了创建一个新结点该结点的前驱和后继指向自己同时 _head 的值为该结点的地址。为了方便拷贝构造以及其他构造函数复用这里将这个操作封装成一个私有函数。 namespace wr {template typename Tclass list{typedef ListNodeT Node;public:list(){empty_init():}private:void empty_init(){_head new Node;_head-_prev _head;_head-_next _head;}Node* _head;}; }3. push_back 尾插 此时完成尾插操作的实现就可以把一个链表的最初框架完成了尾插的实现就不过多赘述了。 push_back(const T val T()) {Node* newNode new Node(val);Node* tail _head-_prev;// tail newNode _headtail-_next newNode;newNode-_prev tail;newNode-_next _head;_head-_prev newNode; }这时候通过调试就可以确认链表创建并尾插成功: 二. list 迭代器的实现 list 的重点就是迭代器的实现。 之前的 vector 和 string 由于是顺序存储结构所有迭代器是原生指针通过 等操作可以直接访问到对应元素。 但是list 是链式存储结构在底层各结点的位置不是连续的单纯使用原生指针的加减是访问不到结点数据的。 那么怎么样才可以通过 iterator 等操作来实现访问结点的效果呢 得益于C自定义类型可以进行运算符重载但Node* 是内置类型不可以进行运算符重载 可以将Node*进行封装再重载 等操作 1. 迭代器的结构 templateclass T struct __list_iterator{typedef ListNodeT Node; // 重命名Node* _node; // 迭代器指向的结点指针// construct__list_iterator(Node* node nullptr): _node(node){} };2. ,–,*,,! 接着是实现 ,--,* 操作符的重载 使迭代器指向当前结点的后驱 -- 使迭代器指向当前结点的前驱 * 得到结点的数据 typedef __list_iteratorT self; // 重命名 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; }T operator*() {return _node-_data; }bool operator!(const self s) {return _node ! s._node; }bool operator(const self s) {return _node s._node; }在 list 类中添加 end, begin typedef __list_iteratorT iterator; iterator begin() {return _head-_next; } iterator end() {return _head; } const_iterator begin() const {return _head-_next; } const_iterator end() const {return _head; }随后进行测试迭代器构建成功 3. - 若结点的数据域的类型是自定义类型例如下面的自定义类型 AA struct AA{int _a1;int _a2; };当然可以先对迭代器进行解引用, 再访问成员(*it)._a1 或者直接使用箭头进行访问 it-_a1 这里直接给出 operator-()的实现 T* operator-() {return _node-data; }这样的实现方式会令人感到奇怪为什么是直接返回结点的数据域地址呢 这里类似于运算符重载中的后置——将int放入参数括号内也是一种特殊处理。 当出现迭代器后面跟了一个-时C语法规定省略了一个-, 实际上为 it.operator-()-_a1这样就可以理解为什么返回的是结点的数据域地址了。 为了实现逻辑自恰对此进行特殊处理。 4. 利用模板实现const迭代器 const迭代器和普通迭代器的区别是能否对迭代器指向的数据进行修改不是直接简单粗暴的 cosnt iterator 迭代器本身是需要改变的。 那么两者有区别的就是 operator*() 和 operator-() 的返回类型。 普通迭代器是T operator*(),T* operator-() const迭代器const T operator*(),const T* operator-() 既然两者十分相似就没有必要在重新创建一个 __const_list_iterator 这样的类导致代码冗余重复。 模板这个时候又发挥了作用可以直接在迭代器的类模板再添加两个类型在重命名迭代器的时候只要放入对应的类型让编译器进行类型推演即可 templateclass T, class Ref, class Ptr class __list_iterator{//... };templateclass T class list{ public:// 重命名typedef __list_iteratorT, T, T* iterator; typedef __list_iteratorT, const T, const T* const_iterator;//... };三. 完整代码 list 的其他接口实现就不过多赘述这里直接贴上模拟实现 list 的完整代码 list.h #ifndef __LIST_H__ #define __LIST_H__ #include assert.hnamespace wr {// ListNodetemplate typename Tstruct ListNode{ListNodeT *_next; // 指向后继结点的指针ListNodeT *_prev; // 指向前驱结点的指针T _data; // 存放结点的数据ListNode(const T val T()) // 全缺省构造: _next(nullptr), _prev(nullptr), _data(val){}};// __list_iteratortemplate typename T, typename Ref, typename Ptrstruct __list_iterator{typedef ListNodeT Node;typedef __list_iteratorT, Ref, Ptr self; // 重命名为selfNode *_node; // 迭代器指向的结点指针__list_iterator(Node *node nullptr): _node(node){}__list_iterator(const self s): _node(s._node){}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;}Ref operator*(){return _node-_data;}Ptr operator-(){return (operator*());}bool operator!(const self s){return _node ! s._node;}bool operator(const self s){return _node s._node;}};// listtemplate typename Tclass list{typedef ListNodeT Node;public:typedef __list_iteratorT, T , T * iterator;typedef __list_iteratorT, const T , const T * const_iterator;list(){empty_init();}list(int n, const T val T()){empty_init();for (int i 0; i n; i){push_back(val);}}templatetypename InputIteratorlist(InputIterator first, InputIterator last){empty_init();while (first ! last){push_back(*first);first;}}list(const listT l){empty_init();for (const auto e : l){push_back(e);}}listT operator(const listT l){swap(l);return *this;}~list(){clear();delete _head;_head nullptr;}// List Iteratoriterator begin(){return _head-_next;}iterator end(){return _head;}const_iterator begin() const{return _head-_next;}const_iterator end() const{return _head;}// List Capacitysize_t size() const{size_t size 0;const_iterator it begin();while (it ! end()){size;it;}return size;}bool empty() const{return !size();}// List AccessT front(){return *(begin());}const T front() const{return *(begin());}T back(){return *(--end());}const T back() const{return *(--end());}// List Modifyvoid push_back(const T val T()){// Node *newNode new Node(val);// Node *tail _head-_prev;// tail-_next newNode;// newNode-_prev tail;// newNode-_next _head;// _head-_prev newNode;insert(end(), val);}void pop_back(){erase(--end());}void push_front(const T val T()){insert(begin(), val);}void pop_front(){erase(begin());}iterator insert(iterator pos, const T val){ // 在pos位置前插入值为val的节点Node *cur pos._node;Node *prev cur-_prev;Node *newNode new Node(val);prev-_next newNode;newNode-_prev prev;newNode-_next cur;cur-_prev newNode;return newNode;}iterator erase(iterator pos){ // 删除pos位置的节点返回该节点的下一个位置assert(pos ! end());Node *cur pos._node;Node *prev cur-_prev;Node *next cur-_next;prev-_next next;next-_prev prev;delete cur;return next;}void clear(){iterator it begin();while (it ! end()){it erase(it);}}void swap(listT l){std::swap(_head, l._head);}private:void empty_init(){_head new Node;_head-_next _head;_head-_prev _head;}Node *_head;}; }#endif // __LIST_H__test.cpp #include iostream #include utility #include string #include list.husing namespace std; using namespace wr;#define SHOW(x) \for (auto e : x) \cout e ; \cout endl; \void Test1() {listint l;l.push_back(1);l.push_back(2);l.push_back(3);l.push_back(4);l.push_back(5);listint::iterator lt l.begin();while (lt ! l.end()){cout *lt ;lt;}cout endl; }void Test2() {listint l;l.push_back(1);l.push_back(2);l.push_back(3);l.push_back(4);l.push_back(5);l.push_back(6);SHOW(l);l.push_front(0);SHOW(l);l.pop_back();SHOW(l);l.pop_front();SHOW(l);l.clear();SHOW(l); }void Test3() {liststring l1;l1.push_back(1111);l1.push_back(2222);l1.push_back(3333);l1.push_back(4444);l1.push_back(5555);l1.push_back(6666);SHOW(l1);liststring l2;l2.push_back(aaaa);l2.push_back(bbbb);l2.push_back(cccc);l2.push_back(dddd);l2.push_back(eeee);SHOW(l2);l1.swap(l2);SHOW(l1);l1.front() 1111;l1.back() 9999;cout l1.front() endl;cout l1.back() endl;SHOW(l1); }void Test4() {listint l;cout l.empty() endl;cout l.size() endl;l.push_back(1);l.push_back(1);l.push_back(1);l.push_back(1);l.push_back(1);l.push_back(1);l.push_back(1);cout l.empty() endl;cout l.size() endl; }void Test5() {char a[] abcdeftg;listchar l1(a, a sizeof(a) / sizeof(char));SHOW(l1);cout l1.size() endl;listchar l2(l1);SHOW(l2);listchar l3;l3.push_back(1);l2.swap(l3);SHOW(l2);SHOW(l3); }int main() {Test1();//Test2();//Test3();//Test4();//Test5();return 0; }本章完。
http://www.w-s-a.com/news/170253/

相关文章:

  • 搭建视频播放网站网站排名诊断
  • 网站域名注册网站centos做网站服务器
  • 网站服务器共享的 vpsh5页面制作软件电脑版
  • 免费手机网站申请上海网站建设设计公司哪家好
  • 站长工具大全企业网上书店网站建设设计
  • 做网站的专业公司公司网站是做的谷歌的
  • 做网站前期工作wordpress图片并排
  • 免费注册网站哪个好wordpress评论修改
  • 合肥模板网站建设软件赤峰公司网站建设
  • 毕业设计都是做网站吗深圳网站制作企业邮箱
  • 网站排名 优帮云小规模公司简介怎么写
  • 那个做头像的网站好选择手机网站建设
  • 设计一个网站花多少时间做视频网站适合用什么服务器
  • asp网站开发环境订单系统单页面网站怎么做
  • 山东网站建设都有那些企业推广策略
  • 网站开发文档是什么概念衣服销售网站建设规划书范文
  • 中国建筑装饰网官网企业网站设计优化公司
  • 南海建设工程交易中心网站c2c交易平台有哪些?
  • 有没有专业做网站架构图的软件番禺建设网站哪个好
  • 建立网站第一步整站seo优化公司
  • php网站开发文章管理系统wordpress 评论 顶踩 心 插件
  • 网站做百度收录的意义html网页设计代码作业代码
  • 网站推广怎么做 知乎衡水做网站开发的
  • 重庆忠县网站建设报价网页构建
  • 怎么自己做单页网站怎么在阿里做网站
  • 公司网站重新备案做电商没几个能赚钱的
  • 网站开发我们都能解决怎样做网站吸引客户
  • 网站首页图片切换代码wordpress minfy
  • 什么程序做网站收录好企业搭建网站的必要性
  • 建设网站主题建站必须要域名吗