C++实现list容器

Posted Wecccccccc

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++实现list容器相关的知识,希望对你有一定的参考价值。

代码如下:

#pragma once
#include <iostream>
using namespace std;

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

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


//template<typename T>
//struct ListIterator
//{
//	typedef ListNode<T> Node;
//	typedef ListIterator<T>  Self;
//	Node *_node;
//
//	ListIterator(Node * node = nullptr) :_node(node) {}
//
//
//	//但是该操作并不方便,通过解引用再获取对象值。
//	/*以上的操作支持内置类型的基本操作,但是并不能满足当结点存储的内置类型的操作,
//	当对对象解引用时,是返回的结点的_data,但是这个_data是一个对象,
//	也就并非能得到内置类型的值。*it得到的是对象,再通过.来获得对象的属性值。
//	例如:
//	struct A
//	{
//		int _a;
//		A(int a = 0):_a(a){}
//	};
//
//	使用时:
//	List<A> lst;
//	List<A>::iterator it = lst.begin();
//	cout<<(*it)._a<<endl;
//
//	*/
//	T &operator*()
//	{
//		return _node->_data;
//	}
//
//
//	//在STL库中的迭代器可以直接通过->_a来获取,迭代器是一个对象,
//	//怎么可以通过->来获取自定义类型的属性呢?我们就必须重载->来实现。
//	//就是it->获得自定义类型对象的地址,
//	//再通过->就可以获得自定义类型对象的指定的值it->->_a
//	//	只是在C++会进行优化,省略了其中的一个->。
//	//	下面是实现第一个->的代码
例如:
	List<A> lst;
	List<A>::iterator it = lst.begin();
	cout << it->_a << endl;
//
//
//	T *operator->()
//	{
//		return &(_node->_data)
//	}
//
//	Self & operator++()
//	{
//		_node = _node->_next;
//		return *this;
//	}
//
//	Self operator++(int)
//	{
//		Self tmp(_node);
//		_node = _node->_next;
//		return tmp;
//	}
//
//	Self &operator--()
//	{
//		_node = _node->prev;
//		return *this;
//	}
//
//	Self operator--(int)
//	{
//		Self tmp(_node);
//		_node = _node->prev;
//		return tmp;
//	}
//
//	bool operator ==(const Self &s)
//	{
//		return _node == s._node;
//	}
//
//	bool operator!=(const Self &s)
//	{
//		return _node != s._node;
//	}
//};


//template<typename T>
//struct ConstListIterator
//{
//	typedef ListNode<T> Node;
//	typedef ConstListIterator<T> Self;
//	Node * _node;
//	ConstListIterator(Node *node = nullptr) :_node(node) {}
//
//	ConstListIterator(const Self &s):node(s._node){}
//
//	Self & operator++()
//	{
//		_node = _node->_next;
//		return *this;
//	}
//
//	Self operator++(int)
//	{
//		Self tmp(_node);
//		_node = _node->_next;
//		return tmp;
//	}
//
//	Self &operator--()
//	{
//		_node = _node->prev;
//		return *this;
//	}
//
//	Self operator--(int)
//	{
//		Self tmp(_node);
//		_node = _node->prev;
//		return tmp;
//	}
//
//	bool operator ==(const Self &s)
//	{
//		return _node == s._node;
//	}
//
//	bool operator!=(const Self &s)
//	{
//		return _node != s._node;
//	}
//
//	const T&operator*()
//	{
//		return _node->_data;
//	}
//
//	const T*operator->()
//	{
//		return &(_node->_data);
//	}
//	
//};



//上面是iterator 和 const_iterator 的分开实现,
//但是STL库中实现并不是这样子的,我们发现两个迭代器类型只是类中两个成员函数的返回值不一样而已。
//其他代码逻辑都是一样的,所以我们可以通过多加两个模板类型来解决这个问题,让他们成为一个类,只是类型有所差别。
//在原来的迭代器中将模板改为template<class T, class Ref, class Ptr> T为普通类型,Ref为引用类型,Ptr为指针类型。

template<typename T, typename Ref, typename Ptr>
struct ListIterator
{
	typedef ListNode<T> Node;
	typedef ListIterator<T, Ref, Ptr> Self;
	Node *_node;

	ListIterator(Node *node = nullptr) :_node(node) {}

	ListIterator(const Self &s) : _node(s._node) {}

	Self & operator++()
	{
		_node = _node->_next;
		return *this;
	}

	Self operator++(int)
	{
		Self tmp(_node);
		_node = _node->_next;
		return tmp;
	}

	Self &operator--()
	{
		_node = _node->_prev;
		return *this;
	}

	Self operator--(int)
	{
		Self tmp(*this);
		_node = _node->_prev;
		return tmp;
	}

	Ref operator*()
	{
		return _node->_data;
	}

	Ptr operator->()
	{
		return &(_node->_data);
	}

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

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


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


	/*typedef ListIterator<T> iterator;

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

	iterator end()
	{
		return iterator(_header);
	}

	typedef ConstListIterator<T> const_iterator;

	const_iterator cbegin() const
	{
		return const_iterator(_header->_next);
	}

	const_iterator cend() const
	{
		return const_iterator(_header);
	}*/

	//上面是由于iterator 和 const_iterator 的分开实现,所以要这样写。


	//下面是iterator 和 const_iterator 合在一起后的写法。
	iterator begin()
	{
		return iterator(_header->_next);
	}

	iterator end()
	{
		return iterator(_header);
	}

	const_iterator cbegin() const
	{
		return const_iterator(_header->_next);
	}

	const_iterator cend() const
	{
		return const_iterator(_header);
	}



	List() :_header(new Node())
	{
		_header->_next = _header->_prev = _header;
	}

	List(int n, const T&val = T()) :_header(new Node())
	{
		_header->_next = _header->_prev = _header;
		for (size_t i = 0; i < n; i++)
		{
			push_back(val);
		}
	}

	template<typename inputIterator>
	List(inputIterator first, inputIterator last) :_header(new Node())
	{
		_header->_next = _header->_prev = _header;
		while (first != last)
		{
			push_back(*first);
			++first;
		}
	}

	//拷贝构造函数,现代写法
	List(List<T> &l) :_header(new Node())
	{
		_header->_next = _header->_prev = _header;
		List<T> tmp(l.begin(), l.end());
		swap(tmp);
	}


	//交换两个对象的头结点
	void swap(List<T> &l)
	{
		Node *tmp = l._header;
		l._header = this->_header;
		this->_header = tmp;
	}


	/*利用了拷贝构造函数创建新空间,
	然后再交换他们的头结点,
	tmp离开函数就会自动释放了*/

	List<T> &operator = (List<T> tmp)
	{
		swap(tmp);
		return *this;
	}

	void push_back(const T &val)
	{
		Node *tail = _header->_prev;
		Node *newNode = new Node(val);

		tail->_next = newNode;
		newNode->_prev = tail;

		newNode->_next = _header;
		_header->_prev = newNode;
	}

	void clear()
	{
		if (_header != nullptr)
		{
			Node *cur = _header->_next;
			while (cur != _header)
			{
				Node *next = cur->_next;
				delete[] cur;
				cur = nullptr;
				cur = next;
			}
		}
	}

	size_t size() const
	{
		int sz = 0;
		Node *cur = _header->_next;
		while (cur != _header)
		{
			++sz;
			cur = cur->_next;
		}
		return sz;
	}

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

			prev->_next = next;
			next->_prev = prev;
			delete[] pos._node;
			return iterator(next);
		}
		return pos;
	}

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

		prev->_next = newNode;
		newNode->_prev = prev;
		newNode->_next = cur;
		cur->_prev = newNode;
	}

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

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

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



	~List()
	{
		clear();
		delete _header;
		_header = nullptr;
	}
private:
	Node *_header;
};

template<typename T>
void PrintFor(List<T> &lst)
{
	for (auto &e : lst)
	{
		cout << e << " ";
	}
	cout << endl;
}

测试代码如下:

#include <iostream>
#include "List.h"
using namespace std;

struct A
{
	int _a;
	A(int a = 0) :_a(a) {};
};

int main()
{
	List<int> lst;
	List<int> lst2(3, 1);
	string str = "12345";
	List<char> lst3(str.begin(), str.end());
	lst.push_back(1);
	lst.push_back(2);
	lst.push_back(3);
	lst.push_back(4);

	List<int>::iterator it = lst.begin();
	while (it != lst.end())
	{
		cout << *it << " ";
		++it;
	}
	cout << endl;
	List<A> lst4;
	lst4.push_back(1);
	lst4.push_back(2);
	lst4.push_back(3);
	lst4.push_back(4);

	List<A>::iterator it1 = lst4.begin();
	while (it1 != lst4.end())
	{
		cout << it1->_a << " ";
		++it1;
	}
	cout << endl;

	PrintFor(lst2);

	List<int> lst5;
	lst5.push_back(1);
	lst5.push_back(2);
	lst5.push_back(3);
	lst5.push_back(4);
	lst5.push_back(5);

	List<int>::iterator it2 = lst5.begin();
	while (it2 != lst5.end())
	{
		if (*it2 % 2 == 0) it2 = lst5.erase(it2);
		else ++it2;
	}
	PrintFor(lst5);

	return 0;
}

测试结果:
在这里插入图片描述

以上是关于C++实现list容器的主要内容,如果未能解决你的问题,请参考以下文章

c++之容器——list的源码模拟实现

C++初阶第十一篇——list(list常见接口的用法与介绍+list的模拟实现+list迭代器原理)

C++ 初阶List底层框架模拟实现

C++ 初阶List底层框架模拟实现

C++:STL——List的模拟实现

c++:list模拟实现“任意位置插入删除我最强ƪ(˘⌣˘)ʃ“