【C++链表】

目录

前言

最近用C++写了一下list的基本功能,感触颇深。本以为会跟之前用C写list一样会很轻松,没想到更难了。要考虑的东西跟多了,而且模板报错真的太恶心了(小小吐槽一下,其实就是自己学的不够扎实,还得练呐)。下面的内容是我自己在写链表时的顺序及注意点。

一、搭建链表实现的框架

二、链表的构造函数

当把一个框架搭建好后,第一步就是写的构造函数。

三、链表的尾插

构造函数写完后就要开始往链表里插入数据了,所以第三步我开始写链表的尾插(这里都是比较简单的跟之前C语言没什么两样)。我懒得画图解释了,直接上代码。

复制代码
void push_back(const T& val)
{
	Node* newnode = new Node(val);
	Node* tail = _head->_prev;

	//链接
	tail->_next = newnode;
	newnode->_prev = tail;

	newnode->_next = _head;
	_head->_prev = newnode;
}

四、链表的遍历(重点)

迭代器的遍历

先看看库实现的链表我们是怎么拿过来用的。

为了完成跟库里一样,我们还需要设计迭代器。

重载*、++其实很简单。但是重载!=有个比较坑的地方。

const修饰的迭代器

首先要清楚我们期望的const修的的迭代器是具有怎么的功能。

我们期望被const修饰过的迭代器指向的内容不要被修改,但是可以通过重载的++修改本身。

那这样行不行?如:

cpp 复制代码
typedef const _list_iterator<T> const_iterator;


五、代码实现

其他的功能其实都不难,都很好写。所以不想画图解释了,直接上代码。

cpp 复制代码
#pragma once
#include<iostream>
using namespace std;
namespace Ting
{
	template<class T>
	struct _list_node
	{
		_list_node<T>* _prev;
		_list_node<T>* _next;
		T _val;

		//构造函数
		_list_node(const T& val = T())
			:_next(nullptr)
			, _prev(nullptr)
			, _val(val)
		{}
	};

	template<class T,class Ref,class Ptr>
	struct _list_iterator
	{
		typedef _list_node<T> Node;
		typedef _list_iterator<T,Ref,Ptr> self;
		Node* _node;

		_list_iterator(Node* node)
			:_node(node)
		{}
		bool operator!=(const self& it)//这个const有说法
		{
			return _node != it._node;
		}
		self& operator++()
		{
			_node = _node->_next;
			return *this;
		}
		self operator++(int)
		{
			_list_iterator<T> temp(*this);
			_node = _node->_next;
			return temp;
		}
		Ref operator*()
		{
			return _node->_val;
		}
		Ptr operator->()
		{
			return &(_node->_val);
		}
	};

	template<class T>
	class _list
	{
		typedef _list_node<T> Node;
	public:
		typedef _list_iterator<T,T&,T*> iterator;
		//如何设计const迭代器
		typedef _list_iterator<T, const T&, const T*> const_iterator;

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

		iterator end()
		{
			return _head;
		}

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

		const_iterator end() const
		{
			return _head;
		}

		_list()
		{
			_head = new Node;
			_head->_next = _head;
			_head->_prev = _head;
		}
		
		void 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;
		}

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

		void pop_back()
		{
			Node* tail = _head->_prev;
			Node* newtail = tail->_prev;

			_head->_prev = newtail;
			newtail->_next = _head;
			
		}

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

		iterator insert(iterator pos, const T& val = T())
		{
			Node* cur = pos._node;
			Node* pre = cur->_prev;
			Node* newnode =new Node(val);

			pre->_next = newnode;
			newnode->_prev = pre;

			newnode->_next = cur;
			cur->_prev = newnode;

			return newnode;
		}

		iterator erase(iterator pos)
		{
			Node* cur = pos._node;
			Node* pre = cur->_prev;
			Node* next = cur->_next;

			pre->_next = next;
			next->_prev = pre;
			delete cur;

			return next;
		}

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

		//拷贝构造
		_list(_list<T>& lt)
		{
			_head = new Node;
			_head->_next = _head;
			_head->_prev = _head;

			iterator it = lt.begin();
			while (it != lt.end())
			{
				push_back(*it);
				++it;
			}
		}

		void swap(_list<T>& lt)
		{
			std::swap(_head, lt._head);
		}

		_list<T>& operator=(_list<T> lt)
		{
			swap(lt);
			return *this;
		}

		~_list()
		{
			clear();
		}
	private:
		Node* _head;
	};
}
相关推荐
怕什么真理无穷8 小时前
C++_面试15_零拷贝
c++·面试·职场和发展
AA陈超8 小时前
ASC学习笔记0007:用于与GameplayAbilities系统交互的核心ActorComponent
c++·笔记·学习·ue5·虚幻引擎
大袁同学8 小时前
【哈希hash】:程序的“魔法索引”,实现数据瞬移
数据结构·c++·算法·哈希算法·散列表
沐怡旸8 小时前
【穿越Effective C++】条款21:必须返回对象时,别妄想返回其reference——对象返回的语义与效率平衡
c++·面试
2501_941112618 小时前
C++与Docker集成开发
开发语言·c++·算法
智者知已应修善业9 小时前
【51单片机:两边向中间流水:即两边先点亮然后熄灭,次边的点亮再熄灭,直到最中间的两个点亮再熄灭,然后重复动作。】2023-3-4
c语言·c++·经验分享·笔记·嵌入式硬件·算法·51单片机
@卞10 小时前
ST 表相关练习题
数据结构·c++·算法
报错小能手10 小时前
C++笔记 bind函数模板
开发语言·c++·笔记
Vanranrr10 小时前
表驱动编程实战:让 UI 逻辑既清晰又好维护
c++·ui
Vanranrr10 小时前
车机项目中的 Widget 设计反思:从“能用”到“好用”的改进方向
c语言·c++·架构