c++初阶-----STL---list

作者前言

✨✨✨✨✨✨
​ 作者介绍:

作者id:老秦包你会,
简单介绍:
喜欢学习C语言、C++和python等编程语言,是一位爱分享的博主,有兴趣的小可爱可以来互讨
个人主页::小小页面
gitee页面:秦大大

一个爱分享的小博主 欢迎小可爱们前来借鉴


list

  • **作者前言**
  • list的介绍
  • list的简单使用
    • reverse
    • merge
    • unique
    • splice
  • list的模拟实现
    • 迭代器的模拟
      • **普通的迭代器**
      • const迭代器
      • 反向迭代器
      • 重载->

list的介绍

list页面
list是可以在常数范围内在任意位置进行插入和删除的序列式容器,并且该容器可以前后双向迭代。
2. list的底层是双向链表结构,双向链表中每个元素存储在互不相关的独立节点中,在节点中通过指针指向
其前一个元素和后一个元素。
3. list与forward_list非常相似:最主要的不同在于forward_list是单链表,只能朝前迭代,已让其更简单高
效。
4. 与其他的序列式容器相比(array,vector,deque),list通常在任意位置进行插入、移除元素的执行效率
更好。
5. 与其他序列式容器相比,list和forward_list最大的缺陷是不支持任意位置的随机访问,比如:要访问list
的第6个元素,必须从已知的位置(比如头部或者尾部)迭代到该位置,在这段位置上迭代需要线性的时间
开销;list还需要一些额外的空间,以保存每个节点的相关联信息(对于存储类型较小元素的大list来说这
可能是一个重要的因素)
c++初阶-----STL---list_第1张图片

#include
#include
#include
using namespace std;
int main()
{
   
	list lt;
	lt.push_back(10);
	lt.push_back(11);
	lt.push_back(12);
	lt.push_back(13);
	lt.push_back(14);
	lt.push_back(15);
	list::iterator it = lt.begin();
	while (it != lt.end())
	{
   
		cout << *it;
		it++;
	}
	cout << endl;
	for (auto& e:lt)
	{
   
		cout << e;
	}
	return  0;
}

前面我们知道,string和vector的遍历方式有迭代器,下标和 地址
但是在list中没有下标,通过地址去访问困难,只能通过迭代器去访问,这个时候就会很方便,不用再和之前的C语言那样,获取到对应的地址进行方位,我们只需获取到对应的迭代器就可以快速,迭代器的优势也慢慢的体现出来了

list的简单使用

经过前面的string和vector我们可以使用一些简单 的成员函数,begin、end等相关的成员函数,我这里不详细的去介绍了,下面我简单的介绍一些不经常讲过的,

reverse

需要注意的是这个名称,在string和vector中是reserve()成员函数,是一个进行空间扩大的函数,这两者是不一样的,而reverse是list中特有的成员函数
进行翻转,把元素从头到尾进行翻转

	list lt;
	lt.push_back(10);
	lt.push_back(11);
	lt.push_back(12);
	lt.push_back(13);
	lt.push_back(14);
	lt.push_back(15);
	list::iterator it = lt.begin();
	while (it != lt.end())
	{
		cout << *it << " ";
		it++;
	}
	cout << endl;
	lt.reverse();
	for (auto& e:lt)
	{
		cout << e << " ";
	}

在这里插入图片描述

merge

合并列表
该算法将一个有序list容器加入另一个有序list容器中,且两个list容器必须都为逆序或顺序

unique

去重
前提条件就是: 相同的元素要站在一堆,最好的方式就是有序

splice

连接
把一个list容器的一些内容或者整个连接到另外一个list容器上面去,右边的list容器就变空了
c++初阶-----STL---list_第2张图片

list的模拟实现

前面我们实现过单链表和双向链表,这次我们模拟实现list和前面的类似
节点的类以及list的类,有两个
我们可以写一个命名空间里面进行
下面我们以这个图为例子
c++初阶-----STL---list_第3张图片
所以我们要创建一个节点类, list里面是一个链表,
节点类:

	//节点类
	template<class T>
	struct ListNode
	{
   
	public:
		ListNode* left;
		ListNode* rigth;
		T val;
	
		ListNode(const T& num = T())
			:left(nullptr)
			,rigth(nullptr)
			,val(num)
		{
   
	
		
		}
		bool operator==(const ListNode n)
		{
   
			return this == &n;
		}
	};

跟我们刚开始 的C语言的节点写法一样,

迭代器的模拟

普通的迭代器

//迭代器
	template<class T>
	class _list_iterator
	{
   
	public:
		typedef ListNode Node;
		typedef _list_iterator Self;
		Node* node;

		_list_iterator(ListNode* n)//需要注意的是这里尽量不要用引用
			:node(n)
		{
   
			
		}
		_list_iterator(const Self& n)
			:node(n.node)
		{
   
			
		}
		Self& operator++()//前置++
		{
   
			node = node->rigth;
			return *this;
		}
		Self operator++(int)//后置++
		{
   
			Self newnode(*this);
			node = node->rigth;
			return newnode;
		}
		Self& operator--()//前置--
		{
   
			node = node->left;
			return *this;
		}
			Self operator--(int)//后置--
		{
   
			Self newnode(*this);
			node = node->left;
			return newnode;
		}

		T& operator*()
		{
   
			return this->node->val;
		}
		bool operator!=(const Self& n)
		{
   
			return !(*this == n);
		}
		bool operator==(const Self& n)
		{
   
			return node == n.node;
		}
	};

在迭代器类的那里,我们不能使用地址来typedef,因为地址不连续,所以需要写一个迭代器类,迭代器类里面要进行运算符重载,必须重载* 、 != 、前后置++和–, 这里的迭代器只是一个普通的迭代器,如果要实现一个const迭代器就需要另外写法

const迭代器

我们明白const迭代器防止的是指向的内容不能修改不是迭代器本身不能修改,所以不能在普通迭代器使用const关键字修饰

// const 迭代器
	template
	class _list_const_iterator
	{
   
	public:
		typedef ListNode Node;
		typedef _list_const_iterator const_self;
		typedef const_self  Self;
		Node const* node;//这里可以不添加const修饰
		_list_const_iterator( const Node* n)
			:node(n)
		{
   

		}
		Self& operator++() //前置++
		{
   
			node = node->rigth;
			return *this;
		}
		Self operator++(int) //后置++
		{
   
			Self newnode(*this);
			node = node->rigth;
			return newnode;
		}
		Self& operator--()//前置--
		{
   
			node = node->left;
			return *this;
		}
		Self operator--(int)//后置--
		{
   
			Self newnode(*this);
			node = node->left;
			return newnode;
		}
		const T& operator*() const
		{
   
			return this->node->val;
		}
		bool operator!=(const Self& n) const
		{
   
			return !(*this == n);
		}
		bool operator==(const Self& n) const
		{
   
			return node == n.node;
		}
	};

这是和普通类相似很多的写法,唯一不同的就是operator那里返回值不同,但是这种写法冗余了,图中的很多函数都加了const修饰this,让起不能修改this的成员,需要注意的就是使用const修饰this, 要知道this的成员是否要修改,根据情况来定,
我们要清楚: const迭代器有两个作用一个是迭代器本身可以修改,一个是其指向的内容不能被修改,如果简单理解为 const iterator就是const迭代器,是错误的,因为这样写只能说明 该值不能被修改,违背了const迭代器的第一个作用.
方法2:
在普通迭代器上再增加一个类型,用来控制operator
的返回值

template<class T, class Ref>
	class _list_iterator
	{
   
	public:
		typedef ListNode Node;

你可能感兴趣的:(c++,c++,list,开发语言)