C++ list模拟实现

目录

简单了解

cpp 复制代码
    // 升序 < less
	lt.sort(); //归并算法
	// 降序 > greater
	//greater<int> gt;
	//lt.sort(gt);
	lt.sort(greater<int>());

如果想测两个排序的效率,记得用release,因为debug下测试不准确

cpp 复制代码
void test()
{
	srand(time(0));
	const int N = 1000000;

	list<int> lt1;
	list<int> lt2;

	for (int i = 0; i < N; ++i)
	{
		auto e = rand();
		lt1.push_back(e);
		lt2.push_back(e);
	}

	int begin1 = clock();

	// 拷贝到vector
	vector<int> v(lt2.begin(), lt2.end());
	// 对vector排序
	std::sort(v.begin(), v.end());

	// 拷贝回lt2
	lt2.assign(v.begin(), v.end());

	int end1 = clock();

	int begin2 = clock();
	lt1.sort();
	int end2 = clock();

	printf("list copy vector sort copy list sort:%d\n", end1 - begin1);
	printf("list sort:%d\n", end2 - begin2);
}

每个节点的结构

cpp 复制代码
template<class T>
	struct list_node
	{
		list_node<T>* next;
		list_node<T>* prev;
		T date;
		list_node(const T&x=T())
			:date(x)
			,next(nullptr)
			,prev(nullptr)
		{}
	};

迭代器失效即迭代器所指向的节点的无效,即该节点被删除了。因为list的底层结构为带头结点的双向循环链表,在list中进行插入时是不会导致list的迭代器失效的,只有在删除时才会失效,并且失效的只是指向被删除节点的迭代器,其他迭代器不会受到影响。

需要用typename的情况

当我们想用一个函数负责打印容器里的数据:

cpp 复制代码
	 //实例化
	template<typename T>
	//template<class T>
	void print_list(const list<T>& lt)
	{
		// list<T>未实例化的类模板,编译器不能去他里面去找
		// 编译器就无法list<T>::const_iterator是内嵌类型,还是静态成员变量
		// 前面加一个typename就是告诉编译器,这里是一个类型,等list<T>实例化,再去类里面去取
		typename list<T>::const_iterator it = lt.begin();
		while (it != lt.end())
		{
			cout << *it << " ";
			++it;
		}
		cout << endl;
	}

改进:

cpp 复制代码
template<typename Container>
	void print_container(const Container& con)
	{
		typename Container::const_iterator it = con.begin();
		while (it != con.end())
		{
			cout << *it << " ";
			++it;
		}
		cout << endl;
	}

list的反向迭代器

可以给反向迭代器专门给一个类型,和正向迭代器相似

修改数据一般用到 *和-> ,那么加上const就不能修改了

如果重新再写一份反向的会比较冗余

正向和反向迭代器的区别就是返回值不一样

库里实现的:都是__list_iterator这个类模板,但是传了三个模板参数

模拟实现list

cpp 复制代码
#include<assert.h>
#include<iostream>
#include<algorithm>
#include<list>
#include<vector>
using namespace std;

namespace ls
{
	template<class T>
	struct list_node
	{
		list_node<T>* next;
		list_node<T>* prev;
		T date;
		list_node(const T&x=T())
			:date(x)
			,next(nullptr)
			,prev(nullptr)
		{}
	};
	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)
		{}
		Ref operator*()
		{
			return _node->date;
		}
		Ptr operator->()
		{
			return &_node->date;
		}
		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->prev;
			return tmp;
		}
		bool operator!=(const self& s)
		{
			return _node != s._node;
		}
		bool operator==(const self& s)
		{
			return _node == s._node;
		}
	};
	template<class T>
	class list
	{
		typedef list_node<T> Node;
	public:
		typedef __list_iterator<T,T&,T*> iterator;
		typedef __list_iterator<T,const T&,const T*> const_iterator;
		list()
			:_head(nullptr)
			,_size(0)
		{
			empty_init();
		}
		list(int n, const T& x = T())
			:_head(nullptr)
			, _size(0)
		{
			empty_init();
			while (n--)
			{
				push_back(x);
			}
		}
		list(iterator first, iterator last)
		{
			empty_init();
			while (first != last)
			{
				push_back(*first);
				++first;
			}
		}
		list(const list<T>& l)
		{
			empty_init();
			for (auto e : l)
			{
				push_back(e);
			}
		}
		list<int>& operator=(list<T> tmp)
		{
			swap(tmp);
			return *this;
		}
		~list()
		{
			clear();
			delete[] _head;
			_head = nullptr;
		}
		iterator begin()
		{
			return iterator(_head->next);
		}
		iterator end()
		{
			return iterator(_head);
		}
		const_iterator begin()const
		{
			return const_iterator(_head->next);
		}
		const_iterator end()const
		{
			return const_iterator(_head);
		}
		size_t size()const
		{
			return _size;
		}
		bool empty()const
		{
			return _size == 0;
		}
		void clear()
		{
			iterator it = begin();
			while (it != end())
			{
				it=erase(it);
			}
		}
		void empty_init()
		{
			_head = new Node;
			_head->next = _head;
			_head->prev = _head;
			_size = 0;
		}
		void push_back(const T& x)
		{
			iterator it = end();
			insert(it,x);
		}
		void push_front(const T& x)
		{
			insert(begin(), x);//隐式类型转换
		}
		void pop_back()
		{
			erase((--end()));
		}
		void pop_front()
		{
			iterator it = iterator(begin());
			erase(it);
		}
		iterator insert(iterator pos,const T& x)//pos位置之前插入,返回新节点位置的iterator
		{
			Node* prev = pos._node->prev;
			Node* cur = pos._node;
			Node* newnode = new Node(x);
			prev->next = newnode;
			newnode->prev = prev;
			newnode->next = cur;
			cur->prev = newnode;

			++_size;
			return iterator(newnode);
		}
		iterator erase(const iterator& pos)//返回被删的下一位置的迭代器
		{
			assert(_size > 0);
			Node* prev = pos._node->prev;//
			Node* next = pos._node->next;
			delete[]pos._node;
			prev->next = next;
			next->prev = prev;
			--_size;

			return iterator(next);
		}
		void swap(list<T>& l)
		{
			std::swap(l._head, _head);
			std::swap(l._size, _size);
		}
	private:
		Node* _head=nullptr;
		size_t _size = 0;
	};
}
相关推荐
ö Constancy1 小时前
c++ 笔记
开发语言·c++
fengbizhe1 小时前
笔试-笔记2
c++·笔记
徐霞客3201 小时前
Qt入门1——认识Qt的几个常用头文件和常用函数
开发语言·c++·笔记·qt
fpcc1 小时前
redis6.0之后的多线程版本的问题
c++·redis
螺旋天光极锐斩空闪壹式!2 小时前
自制游戏:监狱逃亡
c++·游戏
工业3D_大熊2 小时前
3D可视化引擎HOOPS Luminate场景图详解:形状的创建、销毁与管理
java·c++·3d·docker·c#·制造·数据可视化
暮色_年华3 小时前
Modern Effective C++ Item 11:优先考虑使用deleted函数而非使用未定义的私有声明
c++
流星白龙3 小时前
【C++习题】10.反转字符串中的单词 lll
开发语言·c++
Smile丶凉轩3 小时前
微服务即时通讯系统的实现(服务端)----(1)
c++·git·微服务·github
萝卜兽编程3 小时前
优先级队列
c++·算法