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

免费外贸网站源码百度如何精准搜索

免费外贸网站源码,百度如何精准搜索,网站开发定制宣传图片,wordpress图片列表页Clist模拟实现 list接口总结结点类的模拟实现迭代器的模拟实现迭代器模板参数迭代器类中的构造函数迭代器类中的运算符重载operator和operator - -operator! 和operatoroperator*operator->总览 list 类构造函数拷贝构造函数赋值运算符重载operatorclear&#xf…

C++list模拟实现

  • list接口总结
  • 结点类的模拟实现
  • 迭代器的模拟实现
    • 迭代器模板参数
    • 迭代器类中的构造函数
    • 迭代器类中的运算符重载
      • operator++和operator - -
      • operator!= 和operator==
      • operator*
      • operator->
      • 总览
  • list 类
      • 构造函数
      • 拷贝构造函数
      • 赋值运算符重载operator=
      • clear()
      • 析构函数
    • 迭代器相关函数
      • begin和end
  • 与容器修改有关函数
      • insert 插入
      • erase 删除
      • push_back()尾插
      • pop_back 尾删
      • push_front 头插
      • pop_front 头删
      • size

list接口总结

namespace bite
{// List的节点类template<class T>struct ListNode{ListNode(const T& val = T());ListNode<T>* _pre;ListNode<T>* _next;T _date;};//List的迭代器类template<class T, class Ref, class Ptr>class Listiterator{typedef ListNode<T>* Node;typedef Listiterator<T, Ref, Ptr> Self;public:Listiterator(Node* Node);Ref operator*();Ptr operator->();Self& operator++();dSelf operator++(int);Self& operator--();Self& operator--(int);bool operator!=(const Self& l);bool operator==(const Self& l);private:Node _node;};//list类template<class T>class list{typedef ListNode<T> Node;public:typedef Listiterator<T, T&, T*> iterator;typedef Listiterator<T, const T&, const T&> const_iterator;public:///// List的构造void init();list();list(const list<T>& val)list<T>& operator==(list<T> val)~list();///// List Iteratoriterator begin();iterator end();const_iterator begin();const_iterator end();///// List Capacitysize_t size()const;bool empty()const;// List Modifyvoid push_back(const T& val) { insert(end(), val); }void pop_back() { erase(--end()); }void push_front(const T& val) { insert(begin(), val); }void pop_front() { erase(begin()); }// 在pos位置前插入值为val的节点iterator insert(iterator pos, const T& val);// 删除pos位置的节点,返回该节点的下一个位置iterator erase(iterator pos);void clear();void swap(list<T>& lt);private:Node* _head;size_t _size;};
};

结点类的模拟实现

STL中的list为带头双向循环链表。
如图:
在这里插入图片描述
所以我们要实现list链表之前还要实现结点类。 结点中要存储前一个结点的地址和后一个结点的地址、还有数据。因此我们只需要设定成员变量和构造函数就行。

template <class T>  //设定模板结点中的数据类型可以是不同的
struct ListNode
{typedef ListNode<T> Node;ListNode(const T& val = T())//构造函数:_prev(nullptr),_next(nullptr),_date(val){}Node* _prev;//前驱指针Node* _next;//后驱指针T _date;//数据};

迭代器的模拟实现

我们在string和vector中迭代器模拟都是直接给定模板指针。但是到了list中我们就需要实现一个迭代器类型。why?
这是因为我们在string和vector中数据的存储都是存放在一块连续的空间。我们可以同过指针进行对数据的增删查改。
在这里插入图片描述
list并不是存放一块连续的空间,而是通过结点存放下一个结点的地址一个一个连结起来的。 所以我们不能通过指针来实现链表的增删查改。
迭代器是一种用于遍历集合或容器中元素的接口,它可以隔离对容器的访问方式和底层实现,从而实现解耦。迭代器可以依次访问容器中的每一个元素,而无需了解容器的内部细节。
既然我们的指针不能满足迭代器的行为,那我们就将指针封装成类,使其能够满足迭代器的需要。

迭代器模板参数

迭代器我们给处三个模板参数。

 template<class T, class Ref, class Ptr>

实现两个迭代器,一个iterator 和另一个 const_iterator。

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

从这里我们可以看出,Ref 代表的是引用类型和指针类型。

迭代器类中的构造函数

我们迭代器的底层就是对指针进行的封装,因此成员变量就一个就是结点指针。

Listiterator(Node* node):_node(node)
{}

迭代器类中的运算符重载

operator++和operator - -

list的迭代器没必要实现operator+,只需要实现自增和和自减
自增:

//前置++
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;
}

operator!= 和operator==

实现两个迭代器之间的比较。

bool operator!=(const self& val)
{return _node != val._node;
}bool operator==(const self& val)
{return _node == val._node;
}

operator*

当我们使用解引用操作符,想要得到的是这个地址所指向的数据。所以我们operator* 返回该地址所指向的数据就行。

Ref operator*()
{return _node->_date;
}

operator->

我们在使用list时,如果list内结点存储的数据不是内置类型,而是自定义类型,例如Date日期类。我们访问Date类中的成员,就需要用到operator->。
例如:

struct A //自定义类型
{A(int x=0 ,int y =0):_aa1(x),_aa2(y){}int _aa1;int _aa2;
};
void test()
{A aa1(0,0);list<A> lt;lt.push_back(aa1);lt.push_back(A(1, 1));lt.push_back({ 2,2 });lt.push_back({3,3});list<A>::iterator it = lt.begin();while (it != lt.end()){cout << it->_aa1 << " " << it->_aa2 << endl;;it++;}
}

operator->只需要返回结点数据的地址就行。

Ptr operator->()
{return &_node->_date;
}

这里有人就可能发现,这种方式访问自定义类型成员需要用到两个->。
在这里插入图片描述

在这里插入图片描述

这里其实是忽略了一个->,两个->第一个运算符重载的调用是指向A* ,另一个是原生指针的调用。为了让代码有良好的可读性,编译器做了特殊处理,忽略了一个->。

总览

template <class T , class Ref , class Ptr>
struct Listiterator
{typedef ListNode<T> Node;typedef Listiterator<T , Ref , Ptr> self;Node* _node;Listiterator(Node* node):_node(node){}Ref operator*(){return _node->_date;}Ptr operator->(){return &_node->_date;}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& val){return _node != val._node;}bool operator==(const self& val){return _node == val._node;}};

list 类

构造函数

list是一个双向带头循环链表,list初始化需要设置一个哨兵位,并使其的前驱指针和后驱指针都指向自己。

void init()
{_head = new Node;_head->_prev = _head;_head->_next = _head;_size = 0;
}
list()
{init();
}

拷贝构造函数

list的拷贝构造就是根据所给的对象,拷贝处一个新的对象。拷贝构造函数我们先给一个头结点使其前驱指针和后驱指针都指向自己,然后再遍历对象,让对象中的结点一个一个尾插入到新的list中去。

list(const list<T>& val)
{init();for (auto& e : val){push_back(e);}
}

赋值运算符重载operator=

我们这里直接使用现代写法。利用传入的参数通过编译器自动调用list构造函数构造出一个list对象,
再使用swap使其与原来的容器进行交换。

	list<T>& operator==(list<T> val){swap(val);return *this;}

clear()

clear函数只需要将链表中的结点和数据清理即可,给一个迭代器使其指向头结点,然后遍历链表将结点一个一个删除,除了哨兵位以外。

void clear()
{iterator it = begin();while (it != end()){it = erase(it);}
}

析构函数

析构函数首先我们先将list容器中的数据清除,让后在释放哨兵位和让_size归零。

~list()
{clear();delete _head;_head = nullptr;_size = 0;
}

迭代器相关函数

begin和end

在这里我们需要清楚的是begin为哨兵位的下一个结点,而end就是哨兵位。

iterator begin()
{return _head->_next;
}iterator end()
{return _head;
}

还有const begin 和end

const_iterator begin() const
{return _head->_next;
}const_iterator end() const 
{return _head;
}

与容器修改有关函数

insert 插入

insert函数作用是在pos位置插入一个新的结点。
如图:
在这里插入图片描述
我们要在pos位置插入一个新的结点(newnode)就得让新结点前驱指针指向pos结点前一个结点(prev),让prev的后驱指针指向newnode。newnode后驱指针指向pos结点,pos前驱指针指向newnode。

void insert(iterator pos , const T& val)
{Node* newnode = new Node(val);Node* cur = pos._node;Node* prev = cur->_prev;newnode->_next = cur;cur->_prev = newnode;newnode->_prev = prev;prev->_next = newnode;_size++;}

erase 删除

erase就是删除pos位置的结点。
如图:
在这里插入图片描述

iterator erase(iterator pos)
{assert(pos != _head);Node* del = pos._node;Node* prev = del->_prev;Node* next = del->_next;prev->_next = next;next->_prev = prev;delete del;--_size;return iterator(next);
}

注意: erase还要注意迭代器失效的问题因此我们的返回值指向的是下一个结点。

push_back()尾插

双向带头循环链表的尾插比较容易理解。新建一个结点使其的前驱指针指向尾结点,尾结点的后驱结点指向新的结点。新结点的后驱指针指向哨兵位,哨兵位的前驱指针指向新结点,再++_size。
在这里插入图片描述

void push_back(const T& val)
{Node* newnode = new Node(val);Node* tail = _head->_prev;newnode->_prev = tail;tail->_next = newnode;newnode->_next = _head;_head->_prev = newnode;_size++;
}

还可以复用insert函数,是push_back函数变得简单。

 void push_back(const T& val) { insert(end(), val); }   

pop_back 尾删

我们这里直接复用erase函数。

void pop_back(){erase(--end()); }   

push_front 头插

头插也是复用insert函数。

void push_front(const T& val) 
{ insert(begin(), val); 
}

pop_front 头删

void pop_front(){ erase(begin()); }

size

返回结点个数。

size_t size()
{return _size;
}
http://www.yayakq.cn/news/892094/

相关文章:

  • 青岛网站建设网址四库一平台建造师业绩查询
  • 怎么做加盟美容院网站南京网站制作服务商
  • 网站建设与管理的内容wordpress short code
  • 建设网站毕业设计wordpress获取位置
  • 深圳的网站建设公司价格建设创意网站
  • 临沂网站制作哪家好如何常看wordpress默认编辑器
  • dede网站模板怎么安装教程品牌建设经验交流材料
  • 友汇网 做公司网站做文案应该关注的网站推荐
  • 网站收录后然后怎么做网站建设目前流行什么
  • 做网站的一般多钱多种郑州网站建设
  • 即墨网站建设网站推广公司官网
  • 国内做外单的网站有哪些资料wordpress 打赏实现
  • p2p金融网站建设无限白嫖国外云服务器
  • 四川广汉市规划和建设局网站网站建设登录结构图
  • 做网站一定要服务器吗android毕业设计代做网站
  • 企业专业网站建设做网站泉州
  • 在哪个网站找婚照公司做那个类型的网站赚钱
  • seo网站优化建议wordpress新闻动态插件
  • 城市中国商业网站平台建设银行网站扫码支付在哪里
  • 个人网站站长万网域名注册流程
  • mip网站建设网站制作报价多少
  • 网站建设中的思想和算法全球咨询公司最新排名
  • 外贸网站有什么个人网站怎么做联盟推广
  • 屏山县龙华镇中心村建设招标网站wordpress站群 企业
  • 番禺响应式网站开发青岛做家纺的公司网站
  • 网站建设项目外包合同范本南京城乡建设局网站
  • 云南建设工程有限公司网络seo优化推广
  • 外贸电商做俄罗斯市场网站兴化网站网站建设
  • 景点与网站合作方案怎么做求网站2021给个网址
  • 网站可信认证必须做网站建设需求说明