2024年最全【C++】list容器模拟实现_容器模拟c+,Glide的缓存机制

img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取

复用push_back

list(const list<T>& l)
{
	CreatHead();
	auto it = l.cbegin();
	while (it != l.cend())
	{
		push\_back(\*it);
		it++;
	}
}

迭代器构造

将迭代器构造方法写成函数模板,可以传入不同类型的迭代器来构造list对象

template<class InputIterator>
list(InputIterator first, InputIterator last)
{
	CreatHead();
	while (first != last)
	{
		push\_back(\*first);
		first++;
	}
}

赋值运算符重载

与拷贝构造写法相同

list<T>& operator=(const list<T>& l)
{
	if (this != &l)
	{
		clear();//先清空当前对象中的节点
		auto it = l.cbegin();
		while (it != l.cend())
		{
			push\_back(\*it);
			it++;
		}
	}
	return \*this;
}

析构

清空当前对象,释放头节点空间,将头节点置空

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

迭代器

正向迭代器

begin
此处的iterator是对ListIterator<T, T&, T*>的重命名,这里会返回一个ListIterator<T, T&, T*>类对象

iterator begin()
{
	//iterator it(head->next);
	//return it;
	//head->next是传递给迭代器类对象构造函数的参数,调用iterator的构造函数
	return iterator(head->next);//构造匿名对象返回
}

end

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

const类型迭代器
iterator和const_iterator 是两个不同的类:
在这里插入图片描述
两者使用的是相同的类模板,但是传递的参数不同,最终实例化的也是不同的类。
cbegin&cend

const_iterator cbegin()const
{
	return const\_iterator(head->next);
}
const_iterator cend()const
{
	return const\_iterator(head);
}

反向迭代器

rbegin&rend
返回正向迭代器的end和begin

reverse_iterator rbegin()
{
	return reverse\_iterator(end());
}
reverse_iterator rend()
{
	return reverse\_iterator(begin());
}

crbegin&crend
复用正向迭代器的cend和cbegin

const_reverse_iteraotr crbegin()const
{
	return const\_reverse\_iteraotr(cend());
}
const_reverse_iteraotr crend()const
{
	return const\_reverse\_iteraotr(cbegin());
}

容量操作

size
遍历链表,统计节点个数

size_t size()
{
	auto it = cbegin();
	size_t count = 0;
	while (it != cend())
	{
		++count;
		++it;
	}
	return count;
}

empty
如果head->next是head本身则表明链表为空

bool empty()
{
	return head->next == head;
}

resize
改变节点个数,若新的节点个数大于旧的,则调用push_back填充元素;若新的节点个数小于原来的调用pop_back尾删
在这里插入图片描述

元素访问

front
复用迭代器解引用的方法,返回begin()位置元素

T& front()
{
	return \*begin();
}
const T& front()const
{
	return \*cbegin();
}

back
back表示最后一个元素,但是end()指向的是最后一个元素的下一个位置,需要定义临时变量,不能直接对end()进行- -。

T& back()
{
	auto it = end();
	//return --end()//错误写法
	it--;
	return \*it;
}
const T& back()const
{
	auto it = end();
	it--;
	return \*it;
}

打印链表

定义一个打印链表的函数模板,检验方法。通过迭代器遍历链表,打印每一个节点的数据。

template<class T>
void PrintList(const list<T>& l)
{
	auto it = l.cbegin();
	while (it != l.cend())
	{
		cout << \*it << " ";
		++it;
	}
	cout << endl;
}

元素修改

尾插与尾删

push_back
复用insert方法在end位置插入

void  push\_back(const T& value)
{
	insert(end(), value);
}

pop_back
先判断链表是否为空,复用erase方法在end的前一个位置进行插入

void pop\_back()
{
	if (empty())
	{
		return;
	}
	auto it = end();
	it--;
	erase(it);
}

头插与头删

复用insert与erase方法,在begin()位置进行插入或删除

void push\_front(const T& value = T())
{
	insert(begin(), value);
}
void pop\_front()
{
	erase(begin());
}

⭐insert

任意位置的插入:申请新节点,连接新节点与链表,断开旧的连接。
这里传入的参数是一个迭代器类对象,不能直接进行操作,要对对象中封装的_pNode指针进行操作。
返回值是新插入的节点的迭代器,所以要用申请的新节点的指针newnode构造一个迭代器类对象返回,不能直接返回newnode

iterator insert(iterator Insertpos, const T& value)
{
	Node\* newnode = new Node(value);
	Node\* pos = Insertpos._pNode;//\_pNode是节点类型的指针
	newnode->next = pos;
	newnode->prev = pos->prev;
	newnode->prev->next = newnode;
	pos->prev = newnode;
	//return newnode;
	//⭐迭代器是封装的Node\*指针,此时不能再返回newnode
	return iterator(newnode);//构造匿名对象返回
}

⭐erase

任意位置的删除:分别改变前后两个节点的next和prev指针的指向即可

iterator erase(iterator Erasepos)
{
	Node\* pos = Erasepos._pNode;
	Node\* ret = pos->next;
	pos->prev->next = pos->next;
	pos->next->prev = pos->prev;
	delete pos;
	return iterator(ret);
}

区间删除:复用单个节点删除的方法,遍历要删除的区间。
要用接收erase的返回值,防止迭代器失效

iterator erase(iterator first, iterator last)
{
	auto it = first;
	while (it != last)
	{
		//it=erase(it);
		//后置++会构造临时对象返回,不会导致迭代器失效
		erase(it++);
	}
	return it;
}

clear&swap

clear复用erase区间删除的方法,从begin删除到end位置;
swap方法调用标准库中的swap,交换两个链表的头节点。

void clear()
{
	erase(begin(), end());
}
void swap(list<T>& l)
{

	std::swap(head, l.head);
}

附:完整list类,含测试用例

#include<iostream>
#include<vector>
using namespace std;

namespace ZH
{
	/
	//节点类模板, 
	template<class T>
	struct ListNode
	{
		ListNode<T>\* prev;
		ListNode<T>\* next;
		T data;

		ListNode(const T& value = T())
			:prev(nullptr)
			, next(nullptr)
			, data(value)
		{ }
	};
	
	/
	//迭代器类模板
	//list的迭代器不能使用原生态的指针,要进行封装
	//T:迭代器指向的元素类型
	//Ref:给operator\*使用,返回引用类型,不要写成T&
	//Ptr:返回值使用,不要写成T\*
	template<class T,class Ref,class Ptr>
	class ListIterator
	{
	public:
		typedef ListNode<T> Node;//化简节点类的名字
		typedef Ref Reference;//在反向迭代器类中使用
		typedef Ptr Pointer;

		typedef ListIterator<T, Ref, Ptr> Self;//简化迭代器类的名字

		//构造函数
		ListIterator(Node\* pNode=nullptr)
			:\_pNode(pNode)
		{}

		//重载部分需要使用的运算符即可:\*、->、++、--、==
		Ref operator\*()
		{
			return _pNode->data;
		}
		//T为自定义类型时有意义,
		Ptr operator->()
		{
			return &_pNode->data;
		}
		//前置++,返回值是迭代器自身类型的引用
		Self& operator++()
		{
			_pNode = _pNode->next;
			return \*this;
		}
		//后置
		Self operator++(int)
		{
			Self temp(\*this);
			_pNode = _pNode->next;
			return temp;
		}
		Self& operator--()
		{
			_pNode = _pNode->prev;
			return (\*this);
		}
		Self operator--(int)
		{
			Self temp(\*this);
			_pNode = _pNode ->prev;
			return temp;
		}
		//迭代器能进行比较
		bool operator!=(const Self& it)
		{
			return _pNode != it._pNode;
		}
		bool operator==(const Self& it)
		{
			return _pNode == it._pNode;
		}

		Node\* _pNode;//成员变量,节点类型指针
	};

	
	//反向迭代器类模板,对迭代器进行复用
	template<class Iterator>
	class ListReverseIterator
	{
	public:
		//typedef Iterator::Reference Reference;
		//typedef Iterator::Pointer Pointer;
		typedef typename Iterator::Reference Reference;//typename指定Reference是Iterator中的数据类型
		typedef typename Iterator::Pointer Pointer;
		typedef ListReverseIterator<Iterator> Self;

		ListReverseIterator(Iterator it)
			: \_it(it)
		{ }

		Reference operator\*()
		{
			//\*做特殊处理,先--,再解引用返回
			auto temp = _it;
			--temp;
			return \*temp;
		}
		Pointer operator->()
		{
			return &(operator\*());
		}
		Self operator++()
		{
			--_it;
			return \*this;
		}
		Self operator++(int)
		{
			Self temp(\*this);
			--_it;
			return \*this;
		}
		Self operator--()
		{
			++_it;
			return \*this;
		}
		Self operator--(int)
		{
			Self temp(\*this);
			++_it;
			return temp;
		}
		bool operator==(const Self& rit)
		{
			return _it == rit;
		}
		bool operator!=(const Self& rit)
		{
			return _it == rit._it;
		}

	private:
		Iterator _it;//正向迭代器
	};

	template<class T>
	class list
	{
		typedef ListNode<T> Node;
		//typedef Node\* iterator;//不能使用Node\*作迭代器
		//迭代器
		typedef ListIterator<T, T&, T\*> iterator;
		typedef ListIterator< T, const T&, const T\*> const_iterator;
		
		typedef ListReverseIterator<iterator> reverse_iterator;
		typedef ListReverseIterator<const_iterator> const_reverse_iteraotr;

	public:
		///
		//构造
		list()
		{
			CreatHead();
		}
		list(int n, const T& value=T())
		{
			CreatHead();
			for (int i = 0; i < n; ++i)
			{
				push\_back(value);
			}
		}
		list(const list<T>& l)
		{
			CreatHead();
			auto it = l.cbegin();
			while (it != l.cend())
			{
				push\_back(\*it);
				it++;
			}
		}
		//迭代器区间构造
		template<class InputIterator>
		list(InputIterator first, InputIterator last)
		{
			CreatHead();
			while (first != last)
			{
				push\_back(\*first);
				first++;
			}
		}
		//赋值运算符重载
		list<T>& operator=(const list<T>& l)
		{
			if (this != &l)
			{
				clear();//先清空当前对象中的节点
				auto it = l.cbegin();
				while (it != l.cend())
				{
					push\_back(\*it);
					it++;	
				}
			}
			return \*this;
		}
		~list()
		{
			clear();
			delete head;
			head = nullptr;
		}
	public:
		//迭代器
		iterator begin()
		{
			//iterator it(head->next);
			//return it;
			//iterator是对ListIterator<T, T&, T\*>的重命名
			//这里会返回一个ListIterator<T, T&, T\*>类对象
			//head->next是传递给迭代器类对象构造函数的参数,调用iterator的构造函数
			return iterator(head->next);//构造匿名对象返回
		}
		iterator end()
		{
			return iterator(head);
		}
		//const类型迭代器
		const_iterator cbegin()const
		{
			return const\_iterator(head->next);
		}
		const_iterator cend()const
		{
			return const\_iterator(head);
		}

		//反向迭代器
		//反向迭代器的成员变量是一个迭代器类对象
		//end()即为传递给反向迭代器类构造函数的参数
		reverse_iterator rbegin()
		{
			return reverse\_iterator(end());
		}
		reverse_iterator rend()
		{
			return reverse\_iterator(begin());
		}
		//反向const类型迭代器
		const_reverse_iteraotr crbegin()const
		{
			return const\_reverse\_iteraotr(cend());
		}
		const_reverse_iteraotr crend()const
		{
			return const\_reverse\_iteraotr(cbegin());
		}

		/
		//容量
		size_t size()
		{
			auto it = cbegin();
			size_t count = 0;
			while (it != cend())
			{
				++count;
				++it;
			}
			return count;
		}
		bool empty()
		{
			return head->next == head;
		}
		void resize(int newsize,const T& value=T())
		{
			size_t oldsize = size();
			if (newsize > oldsize)
			{
				while (oldsize++<newsize)
				{
					push\_back(value);
				}
			}
			if (newsize < oldsize)
			{
				while (oldsize-- < newsize)
				{
					pop\_back();
				}
			}
		}

		///
		//元素访问
		T& front()
		{
			return \*begin();
		}
		const T& front()const
		{
			return \*cbegin();
		}
		T& back()
		{
			auto it = end();
			it--;
			return \*it;
		}
		const T& back()const
		{
			auto it = end();
			it--;
			return \*it;
		}


		/
		//元素修改
		void  push\_back(const T& value)
		{
			insert(end(), value);
		}

		void pop\_back()
		{
			if (empty())
			{
				return;
			}
			auto it = end();
			it--;
			erase(it);
		}
		void push\_front(const T& value = T())
		{
			//Node\* pos = head->next;
			/\*Node\* newnode = new Node(value);
 newnode->next = head->next;
 newnode->prev = head;
 head->next->prev = newnode;
 head->next = newnode;\*/
		    //复用insert
			insert(begin(), value);
		}
		void pop\_front()
		{
			erase(begin());
		}

		//⭐insert
		// iterator是ListIterator<T, T&, T\*>
		iterator insert(iterator Insertpos, const T& value)
		{
			Node\* newnode = new Node(value);
			Node\* pos = Insertpos._pNode;//\_pNode是节点类型的指针
			newnode->next = pos;
			newnode->prev = pos->prev;
			newnode->prev->next = newnode;
			pos->prev = newnode;
			//return newnode;
			//⭐迭代器是封装的Node\*指针,此时不能再返回newnode
			return iterator(newnode);//构造匿名对象返回
		}
		//⭐erase
		iterator erase(iterator Erasepos)
		{
			Node\* pos = Erasepos._pNode;
			Node\* ret = pos->next;
			pos->prev->next = pos->next;
			pos->next->prev = pos->prev;
			delete pos;
			return iterator(ret);
		}
		iterator erase(iterator first, iterator last)
		{
			auto it = first;
			while (it != last)
			{
				//it=erase(it);
				erase(it++);
			}
			return it;
		}

		void clear()
		{
			erase(begin(), end());
		}
		void swap(list<T>& l)
		{
			std::swap(head, l.head);
		}

	private:
		//提供一个创造头结点的方法
		void CreatHead()
		{
			//调用节点类的构造方法
			head = new Node();
			head->next = head;
			head->prev = head;
		}
	private:
		Node\* head;

	};


![img](https://img-blog.csdnimg.cn/img_convert/f4b3fb97ef8bf8ed308edc171c9fd961.png)
![img](https://img-blog.csdnimg.cn/img_convert/77cd14960cb2891520113deaa8d97894.png)

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!**

**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**

**[如果你需要这些资料,可以戳这里获取](https://bbs.csdn.net/topics/618668825)**

 = pos->next;
			pos->next->prev = pos->prev;
			delete pos;
			return iterator(ret);
		}
		iterator erase(iterator first, iterator last)
		{
			auto it = first;
			while (it != last)
			{
				//it=erase(it);
				erase(it++);
			}
			return it;
		}

		void clear()
		{
			erase(begin(), end());
		}
		void swap(list<T>& l)
		{
			std::swap(head, l.head);
		}

	private:
		//提供一个创造头结点的方法
		void CreatHead()
		{
			//调用节点类的构造方法
			head = new Node();
			head->next = head;
			head->prev = head;
		}
	private:
		Node\* head;

	};


[外链图片转存中...(img-2lPAWWlE-1715755647097)]
[外链图片转存中...(img-nXqNdoqh-1715755647098)]

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!**

**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**

**[如果你需要这些资料,可以戳这里获取](https://bbs.csdn.net/topics/618668825)**

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值