[C++STL]C++实现list容器

代码如下:

#pragma once
#include <iostream>
using namespace std;template<typename T>
struct ListNode
{T _data;ListNode<T> *_next;ListNode<T> *_prev;ListNode(const T & val = T()) :_data(val), _next(nullptr), _prev(nullptr) {};
};//template<typename T>
//struct ListIterator
//{
//	typedef ListNode<T> Node;
//	typedef ListIterator<T>  Self;
//	Node *_node;
//
//	ListIterator(Node * node = nullptr) :_node(node) {}
//
//
//	//但是该操作并不方便,通过解引用再获取对象值。
//	/*以上的操作支持内置类型的基本操作,但是并不能满足当结点存储的内置类型的操作,
//	当对对象解引用时,是返回的结点的_data,但是这个_data是一个对象,
//	也就并非能得到内置类型的值。*it得到的是对象,再通过.来获得对象的属性值。
//	例如:
//	struct A
//	{
//		int _a;
//		A(int a = 0):_a(a){}
//	};
//
//	使用时:
//	List<A> lst;
//	List<A>::iterator it = lst.begin();
//	cout<<(*it)._a<<endl;
//
//	*/
//	T &operator*()
//	{
//		return _node->_data;
//	}
//
//
//	//在STL库中的迭代器可以直接通过->_a来获取,迭代器是一个对象,
//	//怎么可以通过->来获取自定义类型的属性呢?我们就必须重载->来实现。
//	//就是it->获得自定义类型对象的地址,
//	//再通过->就可以获得自定义类型对象的指定的值it->->_a
//	//	只是在C++会进行优化,省略了其中的一个->。
//	//	下面是实现第一个->的代码
例如:
	List<A> lst;
	List<A>::iterator it = lst.begin();
	cout << it->_a << endl;
//
//
//	T *operator->()
//	{
//		return &(_node->_data)
//	}
//
//	Self & operator++()
//	{
//		_node = _node->_next;
//		return *this;
//	}
//
//	Self operator++(int)
//	{
//		Self tmp(_node);
//		_node = _node->_next;
//		return tmp;
//	}
//
//	Self &operator--()
//	{
//		_node = _node->prev;
//		return *this;
//	}
//
//	Self operator--(int)
//	{
//		Self tmp(_node);
//		_node = _node->prev;
//		return tmp;
//	}
//
//	bool operator ==(const Self &s)
//	{
//		return _node == s._node;
//	}
//
//	bool operator!=(const Self &s)
//	{
//		return _node != s._node;
//	}
//};//template<typename T>
//struct ConstListIterator
//{
//	typedef ListNode<T> Node;
//	typedef ConstListIterator<T> Self;
//	Node * _node;
//	ConstListIterator(Node *node = nullptr) :_node(node) {}
//
//	ConstListIterator(const Self &s):node(s._node){}
//
//	Self & operator++()
//	{
//		_node = _node->_next;
//		return *this;
//	}
//
//	Self operator++(int)
//	{
//		Self tmp(_node);
//		_node = _node->_next;
//		return tmp;
//	}
//
//	Self &operator--()
//	{
//		_node = _node->prev;
//		return *this;
//	}
//
//	Self operator--(int)
//	{
//		Self tmp(_node);
//		_node = _node->prev;
//		return tmp;
//	}
//
//	bool operator ==(const Self &s)
//	{
//		return _node == s._node;
//	}
//
//	bool operator!=(const Self &s)
//	{
//		return _node != s._node;
//	}
//
//	const T&operator*()
//	{
//		return _node->_data;
//	}
//
//	const T*operator->()
//	{
//		return &(_node->_data);
//	}
//	
//};//上面是iterator 和 const_iterator 的分开实现,
//但是STL库中实现并不是这样子的,我们发现两个迭代器类型只是类中两个成员函数的返回值不一样而已。
//其他代码逻辑都是一样的,所以我们可以通过多加两个模板类型来解决这个问题,让他们成为一个类,只是类型有所差别。
//在原来的迭代器中将模板改为template<class T, class Ref, class Ptr> T为普通类型,Ref为引用类型,Ptr为指针类型。template<typename T, typename Ref, typename Ptr>
struct ListIterator
{typedef ListNode<T> Node;typedef ListIterator<T, Ref, Ptr> Self;Node *_node;ListIterator(Node *node = nullptr) :_node(node) {}ListIterator(const Self &s) : _node(s._node) {}Self & operator++(){_node = _node->_next;return *this;}Self operator++(int){Self tmp(_node);_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 &(_node->_data);}bool operator!=(const Self &s){return _node != s._node;}bool operator==(const Self &s){return _node == s._node;}
};template<typename T>
class List
{
public:typedef ListNode<T> Node;typedef ListIterator<T, T &, T *> iterator;typedef ListIterator<T, const T&, const T*> const_iterator;/*typedef ListIterator<T> iterator;iterator begin(){return iterator(_header->_next);}iterator end(){return iterator(_header);}typedef ConstListIterator<T> const_iterator;const_iterator cbegin() const{return const_iterator(_header->_next);}const_iterator cend() const{return const_iterator(_header);}*///上面是由于iterator 和 const_iterator 的分开实现,所以要这样写。//下面是iterator 和 const_iterator 合在一起后的写法。iterator begin(){return iterator(_header->_next);}iterator end(){return iterator(_header);}const_iterator cbegin() const{return const_iterator(_header->_next);}const_iterator cend() const{return const_iterator(_header);}List() :_header(new Node()){_header->_next = _header->_prev = _header;}List(int n, const T&val = T()) :_header(new Node()){_header->_next = _header->_prev = _header;for (size_t i = 0; i < n; i++){push_back(val);}}template<typename inputIterator>List(inputIterator first, inputIterator last) :_header(new Node()){_header->_next = _header->_prev = _header;while (first != last){push_back(*first);++first;}}//拷贝构造函数,现代写法List(List<T> &l) :_header(new Node()){_header->_next = _header->_prev = _header;List<T> tmp(l.begin(), l.end());swap(tmp);}//交换两个对象的头结点void swap(List<T> &l){Node *tmp = l._header;l._header = this->_header;this->_header = tmp;}/*利用了拷贝构造函数创建新空间,然后再交换他们的头结点,tmp离开函数就会自动释放了*/List<T> &operator = (List<T> tmp){swap(tmp);return *this;}void push_back(const T &val){Node *tail = _header->_prev;Node *newNode = new Node(val);tail->_next = newNode;newNode->_prev = tail;newNode->_next = _header;_header->_prev = newNode;}void clear(){if (_header != nullptr){Node *cur = _header->_next;while (cur != _header){Node *next = cur->_next;delete[] cur;cur = nullptr;cur = next;}}}size_t size() const{int sz = 0;Node *cur = _header->_next;while (cur != _header){++sz;cur = cur->_next;}return sz;}iterator erase(iterator pos){if (pos != end()){Node *next = pos._node->_next;Node *prev = pos._node->_prev;prev->_next = next;next->_prev = prev;delete[] pos._node;return iterator(next);}return pos;}void insert(iterator pos, const T &val){Node * newNode = new Node(val);Node *prev = pos._node->_prev;Node *cur = pos._node;prev->_next = newNode;newNode->_prev = prev;newNode->_next = cur;cur->_prev = newNode;}void push_front(const T& val){insert(begin(), val);}void pop_back(){erase(--end());}void pop_front(){erase(begin());}~List(){clear();delete _header;_header = nullptr;}
private:Node *_header;
};template<typename T>
void PrintFor(List<T> &lst)
{for (auto &e : lst){cout << e << " ";}cout << endl;
}

测试代码如下:

#include <iostream>
#include "List.h"
using namespace std;struct A
{int _a;A(int a = 0) :_a(a) {};
};int main()
{List<int> lst;List<int> lst2(3, 1);string str = "12345";List<char> lst3(str.begin(), str.end());lst.push_back(1);lst.push_back(2);lst.push_back(3);lst.push_back(4);List<int>::iterator it = lst.begin();while (it != lst.end()){cout << *it << " ";++it;}cout << endl;List<A> lst4;lst4.push_back(1);lst4.push_back(2);lst4.push_back(3);lst4.push_back(4);List<A>::iterator it1 = lst4.begin();while (it1 != lst4.end()){cout << it1->_a << " ";++it1;}cout << endl;PrintFor(lst2);List<int> lst5;lst5.push_back(1);lst5.push_back(2);lst5.push_back(3);lst5.push_back(4);lst5.push_back(5);List<int>::iterator it2 = lst5.begin();while (it2 != lst5.end()){if (*it2 % 2 == 0) it2 = lst5.erase(it2);else ++it2;}PrintFor(lst5);return 0;
}

测试结果:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/310487.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java动态追踪技术--BTrace

Java动态追踪技术 需求翻译官的日常工作不是在的改bug&#xff0c;发布代码&#xff0c;就是在加日志查找bug的路上。查BUG的过程是痛苦的&#xff0c;我们总是在不停的看代码&#xff0c;修改代码&#xff0c;添加日志&#xff0c;从而帮助我们发现问题&#xff0c;这种形式是…

C#黔驴技巧之实现统计结果排名

本节是实现统计排名的一点技巧&#xff0c;可能有一部分童鞋在实现排名统计绕了一大圈&#xff0c;最后还不如两行代码就搞定&#xff0c;代码清晰而可读性强&#xff0c;接下来我们来一起来看看。我们知道在SQL Server中可以利用Row_Number、Rank等函数进行排名&#xff0c;在…

数据结构与算法--二叉树实现原理

二叉树 二叉树&#xff08;binary tree&#xff09;是一棵树&#xff0c;其中每个节点都不能有多于两个的子节点二叉树的一个性质是一颗平均二叉树的深度要比节点个数N小得多&#xff08;重点&#xff09;&#xff0c;对二叉树的分析得出其平均深度为O(N\sqrt NN​)&#xff0…

[C++STL]C++实现stack容器适配器

代码如下: #include <iostream> #include <deque> using namespace std;template<typename T,typename Con deque<T>> class Stack { public:Stack() {}void Push(const T &x) {_c.push_back(x);}void Pop(){_c.pop_back();}T & Top(){retur…

Istio Pilot架构解析

本文节选自 ServiceMesher 社区联合编写的《Istio Handbook——Istio 服务网格进阶实战》。本书地址&#xff1a;https://github.com/servicemesher/istio-handbook/在应用从单体架构向微服务架构演进的过程中&#xff0c;微服务之间的服务发现、负载均衡、熔断、限流等服务治理…

数据结构与算法--二叉查找树实现原理

二叉查找树 二叉树的一个重要应用就是他在查询中的使用&#xff0c;假设书中每个节点存储一项数据。在我们的案例中&#xff0c;任意复杂的项在java中都容易处理&#xff0c;但为了简单还是假设都是整数。还假设他们都是不重复的整数&#xff0c;使二叉树称为二叉查找树的性质…

[C++STL]C++实现queue容器适配器

代码如下: #include <iostream> #include <deque>using namespace std;template<typename T,typename Con deque<T>> class Queue { public:Queue(){}void Push(const T & x){_c.push_back(x);}void Pop(){_c.pop_front();}T &Back(){return…

当模板方法遇到了委托函数,你的代码又可以精简了

现如今当你翻看一些开源项目源码的时候&#xff0c;你会发现现在到处充斥着委托函数&#xff0c;如Func,Action,Predicate&#xff0c;确实现在的C#在函数式编程 的路上越来越成为主流&#xff0c;越来越显示威力&#xff0c;曾经的一些经典设计模式写法&#xff0c;在函数式下…

数据结构与算法--面试必问AVL树原理及实现

数据结构与算法–AVL树原理及实现 AVL&#xff08;Adelson-Velskii 和landis&#xff09;树是带有平衡条件的二叉查找树&#xff0c;这个平衡条件必须容易实现&#xff0c;并且保证树的深度必须是O(logN)。因此我们让一棵AVL树中每个节点的左子树和右子树的高度最多相差1&…

MySQL8.0新特性

在这之前Mysql的版本是5.7&#xff0c;也是目前使用最广泛的一个版本。现在新版本跳过了6和7直接来到了8&#xff0c;那么V6和V7版本去哪里了呢&#xff1f;比较靠谱的说法是v6用作了内部的其他用途而v7的话是因为mysql有个产品叫做clusterdb他有7这个版本&#xff0c;所以这个…

数据结构与算法--B树原理及实现

B树 前几篇文中讨论的数据结构我们都是假设所有的数据都存储在计算机的主存中。可说总要那么海量的数据需要通过个中数据结构去存储&#xff0c;我们不可能有这么多内存区存放这些数据。那么意味着我们需要将他们放磁盘。所以这个时候范问时间复杂度O决定了他是否能适合存储磁盘…

[C++STL]C++实现priority_queue容器适配器

代码如下: #pragma once #include <iostream> #include <vector> using namespace std;template<typename T> struct Less {bool operator()(const T &a, const T &b){return a < b;} };template<typename T> struct Greater {bool operat…

为什么要用内插字符串代替string.format

知道为什么要用内插字符串&#xff0c;只有踩过坑的人才能明白&#xff0c;如果你曾今使用string.format超5个以上占位符&#xff0c;那其中的痛苦我想你肯定是能够共鸣的。一&#xff1a;痛苦经历先上一段曾今写过的一段代码&#xff0c;大家来体会一下&#xff1a;LogHelper.…

SpringCloud Alibaba 框架下公司架构图

上一篇&#xff1a;Docker容器实战思维 下一篇&#xff1a;分布式事务理论模型

C++ 实现堆

代码如下(小根堆): #include <iostream> #include <assert.h> using namespace std;//小根堆,堆排序从大到小排 class Heap { public:Heap():data(nullptr), size(0), capacity(0) {}~Heap(){delete[] data;data nullptr;size 0;capacity 0;}/*void Swap(int *…

iPhone上运行Linux也要来了

FOSSBRTES 报道称&#xff0c;用户很快将可以通过双启动功能&#xff0c;像在 Android 设备上那样在 iPhone 上运行 Linux。目前&#xff0c;iOS 越狱极客、开发人员 Raffaele 以及 mcg29 已在其 Github 页面上发布了详细说明&#xff0c;详细介绍了如何双启动 64 位 iOS 设备。…

数据结构与算法--图论,最短路算法,拓扑排序算法

图论若干定义 图&#xff08;graph&#xff09;G&#xff08;V,E&#xff09;由定点vertex的集合V&#xff0c; 和边edge的集合E组成。每一条边都是一个点对点&#xff08;v&#xff0c;w&#xff09;&#xff0c;其中 v,w 属于V集合的子集 如果点对点 是有序的&#xff0c;那…

谁说.NET不适合搞大数据、机器学习和人工智能

SciSharp StackSciSharp STACK: https://scisharp.github.io/SciSharp/基于.NET的开源生态系统&#xff0c;用于数据科学、机器学习和AI。SciSharp将所有主要的ML/AI框架从Python引入.NET.特点为.NET开发者.NET开发者使用他们所了解和喜爱的工具可以最高效的工作。我们的使命是…

C++ 泛型编程 实现红黑树RBTree

代码如下: #include <iostream> #include <ctime> using namespace std;enum COLOR {BLACK,RED };template<typename T> struct RBTreeNode {RBTreeNode<T> * _parent;RBTreeNode<T> * _left;RBTreeNode<T> * _right;T _val;COLOR _color…

数据结构与算法--图论-深度优先搜索及其应用

深度优先搜索 深度优先搜索&#xff08;depth-first search&#xff09; 是对先序遍历&#xff08;preorder traversal&#xff09;的推广&#xff0c;我们从某个顶点v开始处理v&#xff0c;然后递归的遍历所有与v邻接顶点。如果这个过程是对一棵树进行&#xff0c;那么&#…