list的模拟实现

本文详细介绍了C++中双向链表(list)的实现,包括ListNode结构、迭代器的实现、begin()和end()方法、insert和erase操作,以及构造函数、析构、swap和size/empty成员函数。
摘要由CSDN通过智能技术生成

目录

1.构建节点

2.迭代器的实现

3.begin() 和 end()

4.insert插入和erase删除功能

5.构造函数及其初始化

6.析构及其清除

7.list类中的swap

8.size及判空


list是一个双向带头链表

在list的实现中最难实现的无非就是迭代器了,其他的功能只要学扎实了数据结构的链表后就能很容易理解。

我这里实现的list类中私有保存了一个head节点已经size。

1.构建节点

保存三个数据,分别为前一个位置指针,后一个位置指针,以及当前位置的值。

注意:要一个构造函数,方便构造初始化。

	template<class T>
	struct ListNode
	{
		ListNode<T>* _next;
		ListNode<T>* _prev;
		T _data;

		ListNode(const T& x = T())
			:_next(nullptr)
			, _prev(nullptr)
			, _data(x)
		{}
	};

2.迭代器的实现

实现++、--是其次,最主要的是iterator的 * 和 -> 功能,*就是返回这个位置的_data就ok了,而->就有点难理解了,返回的是_data这个位置的地址-》

因为编译器会做优化:

	struct D
	{
		int _d1;
		int _d2;

		D(int d1 = 0, int d2 = 0)
			:_d1(d1)
			,_d2(d2)
		{}
	};

对于这个类。

cout << it->_d1 << ":" << it->_d2 << endl;

你去对it进行->操作时,编译器的底层实际是这样处理的:

cout << it.operator->()->_d1 << ":" << it.operator->()->_d2 << endl;

会变成两个解引用操作,这就是为什么->要返回这个位置的数据的指针。

详细代码:

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->_data;
		}

		// 返回指针(难点)
		Ptr operator->()
		{
			return &_node->_data;
		}

		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->_next;

			return tmp;
		}

		bool operator==(const Self& lt)
		{
			return _node == lt._node;
		}

		bool operator!=(const Self& lt)
		{
			return _node != lt._node;
		}
	};

模版参数这样设置三个是为了让编译器可以自动生成普通迭代器和const迭代器。

3.begin() 和 end()

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

		iterator end()
		{
			//return iterator(_head);
			return _head;
		}

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

		const_iterator end() const
		{
			return _head;
		}

实现这个也是可以使用范围for的前提,因为范围for的底层就是用的迭代器。

4.insert插入和erase删除功能

为什么我不去讲push_back、push_front、pop等函数呢,因为当实现了insert和erase后,这些功能都能直接复用insert和erase

插入的思路很简单,就是保存前一个位置,然后再将每个节点之间的关系捋一遍就好了。

删除类似。

详细代码:

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

			prev->_next = node;
			node->_prev = prev;
			node->_next = cur;
			cur->_prev = node;
			_size++;
		}

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

			prev->_next = next;
			next->_prev = prev;

			delete cur;
			cur = nullptr;
			_size--;

			return iterator(next);
		}

然后后续的操作就可以直接复用:

5.构造函数及其初始化

        void empty_init()
		{
			_head = new Node(0);
			_head->_next = _head;
			_head->_prev = _head;

			_size = 0;
		}

		// 构造
		list()
		{
			empty_init();
		}

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

6.析构及其清除

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

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

7.list类中的swap

在list类中实现swap可以复用库的中swap:

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

顺便可以实现赋值操作符的重载:

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

8.size及判空

        size_t size() const
		{
			return _size;
		}

		bool empty()
		{
			return _size == 0;
		}

完整代码:

#pragma once
#include <assert.h>
#include <iostream>
using namespace std;

namespace YC
{
	template<class T>
	struct ListNode
	{
		ListNode<T>* _next;
		ListNode<T>* _prev;
		T _data;

		ListNode(const T& x = T())
			:_next(nullptr)
			, _prev(nullptr)
			, _data(x)
		{}
	};

	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->_data;
		}

		// 返回指针(难点)
		Ptr operator->()
		{
			return &_node->_data;
		}

		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->_next;

			return tmp;
		}

		bool operator==(const Self& lt)
		{
			return _node == lt._node;
		}

		bool operator!=(const Self& lt)
		{
			return _node != lt._node;
		}
	};

	template<class T>
	struct list
	{
		typedef ListNode<T> Node;
	public:
		typedef ListIterator<T, T&, T*> iterator;
		typedef ListIterator<T, const T&, const T*> const_iterator;

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

		iterator end()
		{
			//return iterator(_head);
			return _head;
		}

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

		const_iterator end() const
		{
			return _head;
		}

		void empty_init()
		{
			_head = new Node(0);
			_head->_next = _head;
			_head->_prev = _head;

			_size = 0;
		}

		// 构造
		list()
		{
			empty_init();
		}

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

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

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

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

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

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

			prev->_next = node;
			node->_prev = prev;
			node->_next = cur;
			cur->_prev = node;
			_size++;
		}

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

			prev->_next = next;
			next->_prev = prev;

			delete cur;
			cur = nullptr;
			_size--;

			return iterator(next);
		}

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

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

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

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

		size_t size() const
		{
			return _size;
		}

		bool empty()
		{
			return _size == 0;
		}

	private:
		Node* _head;
		size_t _size;
	};

	void test_list1()
	{
		list<int> lt;
		lt.push_back(1);
		lt.push_back(2);
		lt.push_back(3);
		lt.push_back(4);
		lt.push_back(5);

		list<int>::iterator it = lt.begin();
		while (it != lt.end())
		{
			*it += 10;
			cout << *it << " ";
			++it;
		}
		cout << endl;

		lt.push_front(10);
		lt.push_front(20);
		lt.push_front(30);

		for (auto e : lt)
		{
			cout << e << " ";
		}
		cout << endl;

		lt.pop_back();
		lt.pop_back();
		lt.pop_front();
		lt.pop_front();

		for (auto e : lt)
		{
			cout << e << " ";
		}
		cout << endl;
	}

	struct D
	{
		int _d1;
		int _d2;

		D(int d1 = 0, int d2 = 0)
			:_d1(d1)
			,_d2(d2)
		{}
	};

	void test_list2()
	{
		list<D> lt;
		D dd1(1, 1);
		D dd2 = { 1 , 1 };
		lt.push_back(dd1);
		lt.push_back(dd2);
		lt.push_back(D{ 2, 2 });
		lt.push_back({ 3, 3 });
		lt.push_back({ 4, 4 });

		D* ptr = &dd1;
		(*ptr)._d1;
		ptr->_d1;

		list<D>::iterator it = lt.begin();
		while (it != lt.end())
		{
			//*it += 10;
			//cout << (*it)._a1 << ":" << (*it)._a2 << endl;

			cout << it->_d1 << ":" << it->_d2 << endl;// 下方为未进行代码简化的代码(即operator展开)
			//cout << it.operator->()->_d1 << ":" << it.operator->()->_d2 << endl;

			++it;
		}
		cout << endl;
	}
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值