list的模拟实现

目录

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. list模拟实现

    2024-04-27 06:24:07       33 阅读
  2. C++ list模拟实现

    2024-04-27 06:24:07       49 阅读
  3. 【C++】List模拟实现

    2024-04-27 06:24:07       28 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-04-27 06:24:07       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-04-27 06:24:07       100 阅读
  3. 在Django里面运行非项目文件

    2024-04-27 06:24:07       82 阅读
  4. Python语言-面向对象

    2024-04-27 06:24:07       91 阅读

热门阅读

  1. DNA序列k-mers哈希映射和相似序列查找

    2024-04-27 06:24:07       31 阅读
  2. webpack和vite

    2024-04-27 06:24:07       30 阅读
  3. vue使用外部的模板

    2024-04-27 06:24:07       30 阅读
  4. 债市的牛熊

    2024-04-27 06:24:07       32 阅读
  5. python数据分析与可视化

    2024-04-27 06:24:07       42 阅读
  6. Python笔记|不可变序列之元组

    2024-04-27 06:24:07       31 阅读
  7. golang学习笔记——FAQ 1.22.2

    2024-04-27 06:24:07       36 阅读
  8. mxnet gluon GRU 文档

    2024-04-27 06:24:07       34 阅读
  9. Linux:使用ssl加密网站为https

    2024-04-27 06:24:07       35 阅读
  10. ttcp测试网络吞吐量

    2024-04-27 06:24:07       41 阅读