C++——实现一个简单的迭代器

1、迭代器的原理

为了提高C++编程的效率,STL中提供了许多容器,包括vector、list、map等。为了统一访问方式,STL为每种容器在实现的时候设计了一个内嵌的iterator类,不同的容器有自己专属的迭代器,使用迭代器来访问容器中的数据。迭代器对一些基本操作如*、–、++、==、!=进行了重载,使其具有了遍历复杂数据结构的能力,其遍历机制取决于所遍历的容器,迭代器的使用和指针的使用非常相似。通过begin,end函数获取容器的头部和尾部迭代器,当begin和end返回的迭代器相同时表示容器为空。简单来说,迭代器就是一个遍历的过程,像使用指针一样使用迭代器就可以访问这个容器。

  • 迭代器就是一个类的对象,通过对这个类对象进行操作(如:++, --等)可以实现对容器的遍历,这样用户便可以不用关心它的实现。

在这里插入图片描述

  • 如上图所示:迭代器有三成员,但都是指针,并且一个容器里面会存在两个迭代器,一个是起始迭代器(begin),一个是终止迭代器(end)。
  • 起始迭代器:起始指针始终指向起始位置,终止指针始终指向容器最后一个位置,现在指针(可能叫法不太严谨)可以指向容器中的任意位置,但可以通过重载运算符(++,–)来操作现在指针指向的位置。
  • 终止迭代器:起始指针和终止指针是一样的,现在指针不一样,现在指针始终是指向终止指针的后面一个(也就是null),一直指向null。

2、迭代器的实现

定义一个迭代类所需要的操作:
在这里插入图片描述
这里我们使用一下之前我写过的一个链表容器来辅助实现:

class iterator//迭代类
	{
	private:
		node* m_start;//起始指向
		node* m_cur;//现在指向
		node* m_end;//中止指向
	public:
		iterator(node* start, node* cur, node* end): m_start(start), m_cur(cur), m_end(end){}
		T& operator*() {//重载*运算符
			if (m_cur == nullptr)
				throw underflow_error("链表为空。");//抛出异常
			else
				return m_cur->m_data;
		}
		//重载++运算符
		iterator& operator++() {
			if (m_cur == nullptr)
				m_cur = m_start;
			else
				m_cur = m_cur->m_next;
			return *this;
		}
		//重载--运算符
		iterator& operator--() {
			if (m_cur == nullptr)
				m_cur = m_tail;
			else
				m_cur = m_cur->pre;
			return *this;
		}

		//重载==运算符
		bool operator==(const iterator& that)const {
			return m_start == that.m_start && m_cur == that.m_cur && m_end == that.m_end;
		}
		//重载!=运算符
		bool operator!=(const iterator & that)const {
			return !(*this == that);
		}
		friend class list;
	};

这个迭代类是定义在链表容器类里面的成员类,下面总代码中就知道了。

  • 我们做了迭代类的实现,但我们还要实现一下迭代器的对象,我们需要在链表类里面定义一个函数用来实现迭代类的对象,也就是迭代器,我们分别定义begin和end两个迭代器。
//创建迭代器
	iterator begin() {
		return iterator(m_head, m_head, m_tail);
	}

	//创建第二个迭代器
	iterator end() {
		return iterator(m_head, nullptr, m_tail);
	}

这样我们只要创建一个容器的对象来调用这两个函数就产生两个迭代器了,然后用迭代类里面的重载运算符就可以使用迭代器遍历容器了。

3、容器查找

查找很简单,遍历判断就行了:

template<class IT, class TD>
IT find(const IT &begin, const IT &end, const TD& number)
{
	for (IT it = begin; it != end; ++it)
	{
		if (*it == number)
			return it;
	}
	return end;
}

4、容器排序

我们要为一个容器写一个排序函数对容器进行排序。
我们采用快速排序的方式,那我们先来讲一下什么是快速排序:
在这里插入图片描述

排序("<"template<class IT>
void sort(const IT& begin, const IT& end)
{
	IT p = begin;
	IT last = end;
	--last;
	
	for (IT i = begin, j = last; i != j;)
	{
		while (i != p && *i < *p)//两个变量不相等并且i<p的值就++
			++i;
		if (i != p)
		{
			swap(*i, *p);
			p = i;
		}
		while (j != p && *p < *j)
			--j;
		if (j != p)
		{
			swap(*p, *j);
			p = j;
		}
		
	}
	IT be = begin;
	++be;
	if (p != begin && p != be)
		sort(begin, p);//递归左边
	be = p;
	++be;
	if (be != end &&  be!= last)
		sort(be, end);//递归右边
}

代码可能有点烂,但能力之内了,请见谅。
但我们这样的话就只能升序了,而如果想要降序的话就还需要重新写一个函数,这样的话就非常麻烦,所以我们可以实现一个比较器来配合着上面这个代码,就相当于进行了一个优化。

比较器:简单来说就是一个类,制造容器的人不负责制造比较器这个类,需要用户自己来定义一个这样的类。

//一个简单的比较器
lass MSD
{
public:
	bool operator()(int a, int b) {
		return a > b;//可以是大于或小于
	}
};

//排序(比较器)
template<class IT, class MSD>//MSD是一个类
void sort(const IT& begin, const IT& end, MSD msd)
{
	IT p = begin;
	IT last = end;
	--last;

	for (IT i = begin, j = last; i != j;)
	{
		while (i != p && msd(*i, *j))
			++i;
		if (i != p)
		{
			swap(*i, *p);
			p = i;
		}
		while (j != p && msd(*p, *j))
			--j;
		if (j != p)
		{
			swap(*p, *j);
			p = j;
		}

	}
	IT be = begin;
	++be;
	if (p != begin && p != be)
		sort(begin, p, msd);
	be = p;
	++be;
	if (be != end && be != last)
		sort(be, end, msd);
}

总代码

#include<iostream>
using namespace std;

template<typename T>
class list
{
private:
	class node//节点
	{
	public:
		node(const T &data, node * p, node* n): m_data(data),m_pre(p), m_next(n){}
		T m_data;
		node* m_pre;//前驱
		node* m_next;//后继
	};
	node* m_head;//链表头节点
	node* m_tail;//链表未节点
public:
	class iterator
	{
	private:
		node* m_start;//起始指向
		node* m_cur;//现在指向
		node* m_end;//中止指向
	public:
		iterator(node* start, node* cur, node* end): m_start(start), m_cur(cur), m_end(end){}
		T& operator*() {//重载*运算符
			if (m_cur == nullptr)
				throw underflow_error("链表为空。");//抛出异常
			else
				return m_cur->m_data;
		}
		//重载++运算符
		iterator& operator++() {
			if (m_cur == nullptr)
				m_cur = m_start;
			else
				m_cur = m_cur->m_next;
			return *this;
		}
		//重载--运算符
		iterator& operator--() {
			if (m_cur == nullptr)
				m_cur = m_end;
			else
				m_cur = m_cur->pre;
			return *this;
		}

		//重载==运算符
		bool operator==(const iterator& that)const {
			return m_start == that.m_start && m_cur == that.m_cur && m_end == that.m_end;
		}
		//重载!=运算符
		bool operator!=(const iterator & that)const {
			return !(*this == that);
		}
		friend class list;
	};
	//创建迭代器
	iterator begin() {
		return iterator(m_head, m_head, m_tail);
	}

	//创建第二个迭代器
	iterator end() {
		return iterator(m_head, nullptr, m_tail);
	}

	//利用迭代器添加元素
	void add(iterator& that, const T &num)
	{
		if (that == end())
			push_back(num);
		else
		{
			node* p = new  node(num, that.m_cur->m_pre, that.m_cur);
		
			if (that.m_cur->m_pre)
				that.m_cur->m_pre->m_next = p;
			else
				m_head = p;
			p->m_next->m_pre = p;
		}
	}

	//删除元素
	void eares(iterator& that)
	{
		if (that == end())
			return;
		node* p = that.m_cur;
		if (p->m_pre)
			p->m_pre->m_next = p->m_next;
		else
			m_head = p->m_next;
		if (p->m_next)
			p->m_next->m_pre = p->m_pre;
		else
			m_tail = p->m_pre;
		delete p;
	}

	//缺省构造
	list():m_head(nullptr), m_tail(nullptr){}

	//复制构造
	list(const list& that) {
		for (node* p = that.m_head; p; p = p->m_next)
			push_back(p->m_data);
	}

	//析构函数
	~list() {
		clear();
	}
	
	//判断链表是否为空
	bool empty() {
		return m_head == nullptr && m_tail == nullptr;
	}

	//链表清空
	void clear() {
		while (!empty())
			pop_prent();
	}

	//添加头节点
	void push_prent(const T & data) {
		m_head = new node(data, nullptr, m_head);
		if (m_head->m_next)
			m_head->m_next->m_pre = m_head;
		else
			m_tail = m_head;
	}

	//删除头节点
	void pop_prent() {
		if (empty())
			return;
		node* ponde = m_head->m_next;
		delete m_head;
		if (ponde)
			ponde->m_pre = nullptr;
		else
			m_tail = nullptr;
		m_head = ponde;
	}

	//添加未节点
	void push_back(const T& data) {
		m_tail = new node(data, m_tail, nullptr);
		if (m_tail->m_pre)
			m_tail->m_pre->m_next = m_tail;
		else
			m_tail = m_head;
	}

	//删除尾节点
	void pop_back() {
		if (empty())
			return;
		node* ponde = m_tail->m_pre;
		delete m_tail;
		if (ponde)
			ponde->m_next = nullptr;
		else
			m_head = nullptr;
		m_tail = ponde;
	}

	//获取链表头元素
	T& get_prent() {
		if (empty())
			throw underflow_error("链表为空。");//抛出异常
		return m_head->m_data;
	}
	const T& get_prent() const {
		return const_cast<list*>(this)->get_prent();
	}

	//获取链表未元素
	T& get_back() {
		if(empty())
			throw underflow_error("链表为空。");//抛出异常
		return m_tail->m_data;
	}
	const T& get_back()const {
		return const_cast<list*>(this)->get_back();
	}

	//获取链表大小
	size_t get_size() {
		size_t i = 0;
		for (node* p = m_head; p; p = p->m_next)
			++i;
		return i;
	}
};

//利用迭代器遍历打印
void print(list<int> & ls)
{
	using IT = list<int>::iterator;
	for (IT it = ls.begin(); it != ls.end(); ++it)
	{
		cout << *it << "   ";
	}
	cout << endl;
}

//查找
template<class IT, class TD>
IT find(const IT &begin, const IT &end, const TD& number)
{
	for (IT it = begin; it != end; ++it)
	{
		if (*it == number)
			return it;
	}
	return end;
}

//一个简单的比较器
lass MSD
{
public:
	bool operator()(int a, int b) {
		return a > b;//可以是大于或小于
	}
};

//排序(比较器)
template<class IT, class MSD>//MSD是一个类
void sort(const IT& begin, const IT& end, MSD msd)
{
	IT p = begin;
	IT last = end;
	--last;

	for (IT i = begin, j = last; i != j;)
	{
		while (i != p && msd(*i, *j))
			++i;
		if (i != p)
		{
			swap(*i, *p);
			p = i;
		}
		while (j != p && msd(*p, *j))
			--j;
		if (j != p)
		{
			swap(*p, *j);
			p = j;
		}

	}
	IT be = begin;
	++be;
	if (p != begin && p != be)
		sort(begin, p, msd);
	be = p;
	++be;
	if (be != end && be != last)
		sort(be, end, msd);
}

//代码实现
//-----------------------------
//代码使用

int main()
{
	list<int> ls;
	for (int i = 0; i < 5; i++)
		ls.push_prent(10 + i);
	for (int i = 0; i < 5; i++)
		ls.push_back(100 + i);
	print(ls);

	using IT = list<int>::iterator;
	IT it = ls.begin();
	
	ls.eares(it);//删除it所指向的节点
	print(ls);
	cout << "--------------------" << endl;
	IT ib = ls.begin();
	ls.add(++ib, 120);//添加节点到第二位置
	print(ls);
	
	cout << "---------" << endl;
	cout << "找到一个数并删除它:" << endl;
	IT its = finds(ls.begin(), ls.end(), 100);
	if (its != ls.end())
		ls.eares(its);
	print(ls);

	cout << "-----排序-----" << endl;
	MSD  msd;
	sort(ls.begin(), ls.end(), msd);
	print(ls);
	return 0;
}

可能说的有点不好,但需要你学习关于链表的知识才能搞清楚这个知识。

  • 5
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小白学编程*

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值