【C++】list容器模拟实现_容器模拟c+,2024年最新学海无涯

先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7

深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新大数据全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
img
img
img
img
img

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

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

如果你需要这些资料,可以添加V获取:vip204888 (备注大数据)
img

正文

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 是两个不同的类:  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/7964c7dd2d3240c99bfc4b46c3a4fcda.png)  
 两者使用的是相同的类模板,但是传递的参数不同,最终实例化的也是不同的类。  
 **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尾删  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/6a9f80f256594a86b6dde9cc4e3b9aff.png)


### 元素访问


**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
void PrintList(const list& 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& l)
{

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

}


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



#include
#include
using namespace std;

namespace ZH
{
/
//节点类模板,
template
struct ListNode
{
ListNode* prev;
ListNode* 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;

};

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

}

void Test1()
{
ZH::list l1;
ZH::list l2(3, 1);
PrintList(l2);
ZH::list l3(l2.begin(), l2.end());
PrintList(l3);
vector v{ 0,1,2,3,4 };
ZH::list l4(v.begin(), v.end());
PrintList(l4);
}

void Test2()
{
vector v{ 1,2,3,4 };
ZH::list L1(v.begin(), v.end());
L1.push_back(5);
L1.push_back(6);
L1.push_front(0);
PrintList(L1);
L1.pop_back();
L1.pop_front();
PrintList(L1);
L1.erase(–L1.end());
PrintList(L1);
}

void Test3()
{
ZH::list L1;
L1.push_back(1);
L1.push_back(2);
L1.push_back(3);
L1.push_front(0);
PrintList(L1);
L1.resize(6, 5);
PrintList(L1);
}

struct A
{
int a;
int b;
int c;
};

void Test4()
{
A aa{ 1,2,3 };
A bb{ 4,5,6 };
A cc{ 7,8,9 };
ZH::list L;
L.push_back(aa);
L.push_back(bb);
L.push_back(cc);
auto it = L.begin();
while (it != L.end())
{
//⭐it->得到的是节点的地址
//本应是it->->a,编译器做了特殊处理
cout << it->a << " ";
it++;

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip204888 (备注大数据)
img

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

intList(L1);
L1.pop_back();
L1.pop_front();
PrintList(L1);
L1.erase(–L1.end());
PrintList(L1);
}

void Test3()
{
ZH::list L1;
L1.push_back(1);
L1.push_back(2);
L1.push_back(3);
L1.push_front(0);
PrintList(L1);
L1.resize(6, 5);
PrintList(L1);
}

struct A
{
int a;
int b;
int c;
};

void Test4()
{
A aa{ 1,2,3 };
A bb{ 4,5,6 };
A cc{ 7,8,9 };
ZH::list L;
L.push_back(aa);
L.push_back(bb);
L.push_back(cc);
auto it = L.begin();
while (it != L.end())
{
//⭐it->得到的是节点的地址
//本应是it->->a,编译器做了特殊处理
cout << it->a << " ";
it++;

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip204888 (备注大数据)
[外链图片转存中…(img-erBe3F0h-1713338154542)]

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值