list的使用和模拟实现

什么是list

简单的理解:它的底层就是带头双向循环链表
所以他不支持随机访问,也就是operator[ ]重载

在这里插入图片描述

一些函数接口的基本使用

和vector基本类似,这里就不详细说了

     list<int> lt1; //无参构造
	list<int> lt2(10, 5); // 10个5
	list<int> lt3(lt2);  //拷贝构造
	list<int> lt4(lt2.begin(), lt2.end()); //迭代器区间去构造

其实关于正向和反向的迭代器,
正向的迭代器 ++ ,其实他是向后走
反向的迭代器++,他是向前走

void test1()
{
	list<int> lt;
	lt.push_back(1);
	lt.push_back(2);
	lt.push_back(3);
	lt.push_back(4);

	list<int>::iterator it = lt.begin();
	while (it != lt.end())
	{
		cout << *it << " ";
		it++;
	}
	cout << endl;

	list<int>::reverse_iterator rit = lt.rbegin();
	while (rit != lt.rend())
	{
		cout << *rit <<" ";
		rit++;
	}
	cout << endl;
}

在这里插入图片描述

关于迭代器的详细说明

其实迭代器按功能分类,一共有5种:输入,输出,向前(单向),双向,随机访问
我们需要掌握的就是常见的三种
1,单向:只支持向前走 ++ , 单链表(forward_list)
2, 双向:向前,向后都可以 ++, – 双向循环链表(list)
3, 随机访问:权限最大,都支持 数组和字符串vector,string

在这里插入图片描述
从算法()中使用sort(排序),find(查找),reverse(逆置)。

也就是说find()支持 单向,双向,随机访问
sort()只支持 随机访问
reverser 支持随机访问 和双向

可以这样尝试理解一下(随机访问 > 双向 > 单向 > 输入/输出)

在这里插入图片描述

void test2()
{
	vector<int> v;
	v.push_back(3);
	v.push_back(10);
	v.push_back(1);
	v.push_back(0);
	sort(v.begin(), v.end());
	PrintCon(v);      //打印升序  0  1  3  10
	
	sort(v.begin(), v.end(), greater<int>()); //这greater<int>()需头文件<algorithm>
	PrintCon(v);    //打印降序 10 3 1 0       

}

关于list迭代器失效的说明

vector 插入的时候,迭代器会失效,而list不会
vector 删除的时候,迭代器会失效,list也会
为什么呢?

在这里插入图片描述

list的模拟实现

首先,关于迭代器,因为原生指针不满足迭代器的要求,所以我们需要将迭代器封装成一个类对象,通过运算符的重载来实现
迭代器的各个功能要求。
在这里插入图片描述

迭代器的模拟实现

先看看大致的框架
在这里插入图片描述

迭代器是类对象,这里模拟实现的迭代器不是指针了,而是一个类对象(内置类型)

template <class T,class Ref, class Ptr>
	struct _list_iterator
	{
		typedef _list_node<T> node;
		typedef _list_iterator<T,Ref,Ptr>  sef;

		node* _pnode;

		_list_iterator(node* newnode = nullptr)
		{
			_pnode = newnode;
		}

		//*it --->返回引用
		Ref operator*()
		{
			return _pnode->_val;
		}

		bool operator==(const sef& s)
		{
			return _pnode == s._pnode;
		}

		bool operator!=(const sef& s)
		{
			return _pnode != s._pnode;
		}

		//++it 前置++,后置++形参多个int用来区分
		sef& operator++()
		{
			_pnode = _pnode->next;
			return *this;
		}
		
	};

迭代器的模拟

```cppiterator begin()
		{
			return iterator(_head->next);
		}

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

		const_iterator begin() const
		{
			return iterator(_head->next);
		}

		const_iterator end()  const
		{
			return iterator(_head);
		}

任意位置的插入insert()和 删除erase()

首先,list插入后,迭代器是不会失效的,因为迭代器模拟的是节点的指针,我们插入的时候,节点的指针是不做修改的。
list删除后,迭代器肯定是失效了,因为节点都销毁了,已经没有意义了。

void push_bcak(const T& val)
		{
			//node* newnode = new node(val);
			//node* tail = _head->pre;

			//tail->next = newnode; //链接newnode和tail
			//newnode->pre = tail;

			//newnode->next = _head; //链接newnode 和_head
			//_head->pre = newnode;

			insert(end(), val);
		}

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

		//在pos的前面位置插入val
		void insert(iterator pos, const T& val)
		{
			node* newnode = new node(val);
			node* prenode = pos._pnode->pre;

			prenode->next = newnode; 
			newnode->pre = prenode;

			newnode->next = pos._pnode;
			pos._pnode->pre = newnode;
		}


		iterator erase(iterator pos)
		{
			node* cur = pos._pnode;
			node* save = cur->next;
			
			save->pre = cur->pre;
			cur->pre->next = save;
			delete[] cur;

			return iterator(save);
		}

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

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

构造函数,拷贝构造,赋值重载,析构

list()
		{
			_head = new node;
			_head->next = _head;
			_head->pre = _head;
		}

		//lt1(lt2)
		list(const list<T>& lt2)
		{
			_head = new node;
			_head->next = _head;
			_head->pre = _head;

			//取出lt2的每个节点赋值给e,
			//而迭代器是一个类对象,这样的赋值就内置类型的赋值
			for (auto e : lt2)
			{
				push_bcak(e);
			}
		}

		list& operator=(list<T> lt)
		{
			swap(_head,lt._head);
			return *this;
		}

		~list()
		{
			clear();
			delete _head;
		}
  • 8
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

通过全部用例

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

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

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

打赏作者

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

抵扣说明:

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

余额充值