【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;
	};
}
相关推荐
AA陈超8 分钟前
004 T02 - 俯视角摄像机系统 设计文档
网络·c++·ue5·虚幻引擎
bu_shuo17 分钟前
c与cpp中的argc和argv
c语言·c++·算法
蓝创精英团队22 分钟前
VCPKG 跨平台C++ 库管理器
c++·vcpkg
Jayden_Ruan2 小时前
C++组合的输出
c++·算法·深度优先
froyoisle2 小时前
CSP 真题解析:[CSP-J 2020-T3] 表达式
c++·算法·csp·信息学·信奥赛
Darkwanderor3 小时前
动、静态库相关内容的详细介绍
linux·c语言·开发语言·c++
文祐3 小时前
C++类之虚函数表没有虚继承的菱形继承
开发语言·c++·算法
孬甭_5 小时前
C++ string类
开发语言·c++
盐焗鹌鹑蛋5 小时前
【C++】C++11:右值引用、移动语义万能引用
c++
LingzhiPi5 小时前
零知ESP32--RC522NFC考勤打卡系统
c++·单片机·嵌入式硬件