C++(List的模拟实现)

1.成员变量

上一节已知信息 list是带哨兵卫的双向链表链表 ,所以list类成员变量应该有 节点以及节点个数信息

cpp 复制代码
	private:
		//定义哨兵位
		Node* _head;
		//记录插入节点个数
		size_t _size;
 

2.节点类

每个节点应包含指向下一节点指针、上一节点指针以及自身数据的信息

cpp 复制代码
	template<class T>
	//节点最好用struct定义 保证对外是共有 避免class默认私有 的麻烦
	struct list_node
	{
		list_node<T>* _next;
		list_node<T>* _prev;
		T _val;
		//构造函数
		list_node(const T& val = T())
			:_next(nullptr)
			, _prev(nullptr)
			, _val(val)
		{

		}
	};

3.迭代器封装类

3.1类型重定义,定义节点

cpp 复制代码
//定义类模板 Ref迭代器返回的类型。 Ptr指针指向
	template<class T,class Ref,class Ptr>
	// 迭代器封装的类
	struct __list_iterator
	{
		typedef list_node<T> Node;
		//c++中可以这么使用,在内部引用自身类型 (别名)
		typedef __list_iterator <T, Ref, Ptr> self;
			Node* _node;

3.2构造函数

cpp 复制代码
		//构造函数
		__list_iterator(Node* node)
			:_node(node)
		{}

3.3 operator*()

cpp 复制代码
		//Ref代表返回值的类型 在我们这里 可以是T& 也可以是 const T&
		Ref operator*()
		{
			return _node->_val;
		}
	

3.4operator->()

cpp 复制代码
	//Ptr代表返回值的类型,在这里可以是T*
		Ptr operator->()
		{
			return &_node->_val;
		}

3.5operator++()

cpp 复制代码
		self& operator++()
		{
			_node = _node->_next;
			return *this;
		}

3.6operator++(int)

cpp 复制代码
		//后置++,返回值 因为tmp是临时变量
		self operator++ (int)
		{
			self tmp(*this);
			_node = _node->_next;
			return tmp;

		}

3.7operator--()

cpp 复制代码
		//前置--
		self& operator--()
		{
			_node = _node->_prev;
			return *this;
		}

3.8operator++(int)

cpp 复制代码
		//后置--
		self operator--(int)
		{
			self tmp(*this);

			_node = _node->_prev;

			return tmp;
		}

3.9比较

cpp 复制代码
		//比较
		bool operator!= (const self& it) const //传的对象是const
		{
			return _node != it._node;
		}
		bool operator== (const self& it) const //
		{
			return _node == it._node;
		}

4.list类

4.1类型重定义

cpp 复制代码
	template<class T>
	class list
	{
		typedef list_node<T> Node;
	public:
		typedef __list_iterator<T, T&, T*> iterator;
		typedef __list_iterator<T, const T&, const T*> const_iterator;

4.2成员函数

4.2.1构造函数

cpp 复制代码
		list()
		{
			empty_init();
		}

4.2.2 初始化函数

cpp 复制代码
		void empty_init()  // 
		{
			_head = new Node;
			_head->_prev = _head;
			_head->_next = _head;

			_size = 0;
		 }

4.2.3拷贝构造函数

cpp 复制代码
		list(const list<T>& lt)// 拷贝构造
		{
			empty_init();
			for (auto& e : lt)
			{
				push_back(e);
			}

		}

4.2.4交换函数

cpp 复制代码
		//交换
		void swap(const list<T>& lt)
		{
		std:swap(_head, lt._head);
		std:swap(_size, lt._size);
		}
		list<T>& operator= (list<T> lt)
		{
			swap(lt);
			return *this;
		}

4.2.5析构函数

cpp 复制代码
		~list()
		{
			clear();
			delete _head;
			_head = nullptr;
		}

4.2.6清除函数

cpp 复制代码
		void clear()
		{
			iterator it = begin();
			while(it != end())
			{
				it = erase(it);
			}

			_size = 0;
		}

4.2.7插入insert

cpp 复制代码
		//插入
		iterator insert(iterator pos, const T& x)
		{
			Node* cur = pos._node;
			Node* prev = cur->_prev;
			Node* newnode = new Node(x);

			prev->_next = newnode;
			newnode->_prev = prev;

			newnode->_next = cur;
			cur->_prev = newnode;
			++_size;
			return newnode;
		}

4.2.8 擦除erase

cpp 复制代码
		iterator erase(iterator pos)
		{
			assert(pos != end());
			Node* cur = pos._node;
			Node* prev = cur->_prev;
			Node* next = cur->_next;
			prev->_next = next;
			next->_prev = prev;

			delete cur;
			--_size;
			//返回删除节点的下个位置
			return next;

		}

4.2.9 push_back()

cpp 复制代码
		void push_back(const T& x)
		{
			insert(end(), x);
			
		}

4.2.10push_front()

cpp 复制代码
		void push_front(const T& x)
		{
			insert(begin(), x);

		}

4.2.11pop_front()

cpp 复制代码
		void pop_front()
		{
			erase(begin());
		}
		size_t size()
		{
			return _size;
		}

4.2.12 pop_back()

cpp 复制代码
		void pop_back()
		{
			erase(--end());//end()前一个位置
		}

5测试函数

cpp 复制代码
	void test_list1()
	{
		list<int>lt;
		lt.push_back(1);
		lt.push_back(2);
		lt.push_back(3);
		lt.push_back(4);
		list<int>::iterator it = lt.begin();

		while (it != lt.end())
		{
			(*it) += 1;
			std::cout << *it << " ";
			++it;
		}
		std::cout << std::endl;
		//范围for是傻瓜式替代方式
		for (auto e : lt)
		{
			std::cout << e << " ";
		}
		std::cout << std::endl;

		Print(lt);
	}

	struct A
	{
		A(int a1 = 0, int a2 = 0)
			:_a1(a1)
			, _a2(a2)
		{};
		int _a1;
		int _a2;

	};

	void test2_list2()
	{
		list<A> lt;
		lt.push_back(A(1, 1));
		lt.push_back(A(2, 2));
		lt.push_back(A(3, 3));
		lt.push_back(A(4, 4));

		list<A> ::iterator it = lt.begin();
		while(it != lt.end())
		{
			//对it解引用 得到是结构体对象
			std::cout << (*it)._a1 << " " << (*it)._a2 << std::endl;
			//通过结构体指针指向 -> -> 编译器直接省略成一个
			std::cout << it->_a1 << " " << it->_a2 << std::endl;
			++it;

			
		}
		std::cout << std::endl;
	}
相关推荐
乐悠小码5 分钟前
数据结构------队列(Java语言描述)
java·开发语言·数据结构·链表·队列
史努比.7 分钟前
Pod控制器
java·开发语言
敲敲敲-敲代码16 分钟前
游戏设计:推箱子【easyx图形界面/c语言】
c语言·开发语言·游戏
ROC_bird..25 分钟前
STL - vector的使用和模拟实现
开发语言·c++
机器视觉知识推荐、就业指导25 分钟前
C++中的栈(Stack)和堆(Heap)
c++
MavenTalk31 分钟前
Move开发语言在区块链的开发与应用
开发语言·python·rust·区块链·solidity·move
XiaoLeisj1 小时前
【JavaEE初阶 — 多线程】生产消费模型 & 阻塞队列
java·开发语言·java-ee
2401_840192271 小时前
python基础大杂烩
linux·开发语言·python
@东辰1 小时前
【golang-技巧】- 定时任务 - cron
开发语言·golang·cron
机器人天才一号1 小时前
C#从入门到放弃
开发语言·c#