C++ 标准库类型List

C/C++总述:Study C/C++-CSDN博客

目录

定义和初始化list对象

list中元素的访问

list的大小与容量

list的增

list的删

list的改

list的模拟实现


C++ 标准库中的 list 是一种双向链表容器,它支持快速的插入和删除操作。

list 容器中各个元素的前后顺序是靠指针来维系的,每个元素都配备了 2 个指针,分别指向它的前一个元素和后一个元素。其中第一个元素的前向指针总为 null,因为它前面没有元素;同样,尾部元素的后向指针也总为 null。

cpp 复制代码
#include <list>
using std::list;

定义和初始化list对象

  1. 创建一个没有任何元素的空 list 容器:

    cpp 复制代码
    list<int> lt;
  2. 创建一个包含 n 个元素的 list 容器:

    cpp 复制代码
    list<int> lt(10);//创建lt容器,其中包含10个元素,每个元素的值都为相应类型的默认值(int类型的默认值为0)
  3. 创建一个包含 n 个元素的 list 容器,并为每个元素指定初始值:

    cpp 复制代码
    list<int> lt(10, 5);//创建了一个包含10个元素并且值都为5个lt容器。
  4. 在已有 list 容器的情况下,通过拷贝该容器可以创建新的 list 容器:

    cpp 复制代码
    list<int> lt1(10);
    list<int> lt2(lt1);//注意:采用此方式,必须保证新旧容器存储的元素类型一致。
  5. 通过拷贝其他类型容器(或者普通数组)中指定区域内的元素,可以创建新的 list 容器:

    cpp 复制代码
    //拷贝普通数组,创建list容器
    int a[] = { 1,2,3,4,5 };
    list<int> lt1(a, a+5);
    //拷贝其它类型的容器,创建 list 容器
    vector<int, 5>ve{ 11,12,13,14,15 };
    list<int>lt(ve.begin()+2, ve.end());//拷贝ve容器中的{13,14,15}

list中元素的访问

成员函数 功能
front() 返回第一个元素的引用。
back() 返回最后一个元素的引用。
begin() 返回指向容器中第一个元素的双向迭代器。
end() 返回指向容器中最后一个元素所在位置的下一个位置的双向迭代器。
rbegin() 返回指向最后一个元素的反向双向迭代器。
rend() 返回指向第一个元素所在位置前一个位置的反向双向迭代器。
cbegin() 和 begin() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改元素。
cend() 和 end() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改元素。
crbegin() 和 rbegin() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改元素。
crend() 和 rend() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改元素。

list的大小与容量

成员函数 功能
empty() 判断容器中是否有元素,若无元素,则返回 true;反之,返回 false。
size() 返回当前容器实际包含的元素个数。
max_size() 返回容器所能包含元素个数的最大值。这通常是一个很大的值,一般是 232-1,所以我们很少会用到这个函数。
front() 返回第一个元素的引用。
back() 返回最后一个元素的引用。

list的增

成员函数 功能
push_front() 在容器头部插入一个元素。
push_back() 在容器尾部插入一个元素。
emplace() 在容器中的指定位置插入元素。该函数和 insert() 功能相同,但效率更高。
insert() 在容器中的指定位置插入元素。
splice() 将一个 list 容器中的元素插入到另一个容器的指定位置。

list的删

|-------------|---------------------|
| pop_front() | 删除容器头部的一个元素。 |
| pop_back() | 删除容器尾部的一个元素。 |
| erase() | 删除容器中一个或某区域内的元素。 |
| clear() | 删除容器存储的所有元素。 |
| remove(val) | 删除容器中所有等于 val 的元素。 |
| remove_if() | 删除容器中满足条件的元素。 |
| unique() | 删除容器中相邻的重复元素,只保留一个。 |

list的改

成员函数 功能
assign() 用新元素替换容器中原有内容。
swap() 交换两个容器中的元素,必须保证这两个容器中存储的元素类型是相同的。
resize() 调整容器的大小。
merge() 合并两个事先已排好序的 list 容器,并且合并之后的 list 容器依然是有序的。
sort() 通过更改容器中元素的位置,将它们进行排序。
reverse() 反转容器中元素的顺序。

list的模拟实现

cpp 复制代码
#include<string>
#include<vector>
#include<iostream>
 
using namespace std;
namespace mylist 
{
	template<class T>
    //链表的每个结点的结构
	struct list_node 
	{
		T _data;            //存放数据
		list_node<T>* _prev;//指向前一个结点的指针
		list_node<T>* _next;//指向后一个结点的指针
 
		list_node(const T& val = T())  //构造一个结点对象
			:_data(val)
			, _prev(nullptr)
			, _next(nullptr)
		{ }
	};
 
	// T T& T*
	// T cosnt T& const T*
	template<class T,class Ref,class Ptr>
	struct __list_iterator                   //list的迭代器结构
	{
		typedef list_node<T> Node;             //结点
		typedef __list_iterator<T,Ref,Ptr> _self; //_self就是一个实例化的迭代器
		Node* _node;                          //结点的指针
 
		__list_iterator(Node* node)
			:_node(node)
		{
 
		}
 
		Ref operator*()                //重载运算符* 通过*能够访问结点里面的数据
		{
			return _node->_data;
		}
        
		Ptr operator->()         //重载-> , 结构体指针访问成员可以用结构体对象->结构体成员
		{
			return &_node->_data;
		}
 
		_self& operator++()   //重载运算符前置++,返回下一个结点的迭代器
		{
			_node = _node->_next;
			return (*this);
		}
 
		_self& operator--()  //重载运算符前置--,返回前一个结点的迭代器
		{
			_node = _node->_prev;
			return (*this);
		}
 
		_self operator++(int)  //重载运算符后置++,返回当前结点的迭代器的拷贝再++
		{
			Node* tmp(_node);
			_node = _node->_next;
 
			return tmp;
		}
 
		_self operator--(int) //重载运算符前置--,返回当前一个结点迭代器的拷贝再--
		{
			Node* tmp(_node);
			_node = _node->_prev;
 
			return tmp;
		}
 
		bool operator!=(const _self& n)  //重载迭代器的比较运算符!=
		{
			return this->_node != n._node;
		}
 
		bool operator==(const _self& n)  //重载迭代器的比较运算符==
		{
			return this->_node == n._node;
		}
 
	};
 
	template<class T>
	class list
	{
		typedef list_node<T> Node;
	public:
		typedef __list_iterator<T, T&, T*> iterator;
		typedef __list_iterator<T, const T&, const T*> const_iterator;
 
		const_iterator begin() const
		{
			return const_iterator(_head->_next);
		}
			
		const_iterator end() const
		{
			return const_iterator(_head);
		}
 
		iterator begin()
		{
			return (_head->_next);
		}
 
		iterator end()
		{
			return _head;
		}
 
		void empty_init()
		{
			_head = new Node;
			_head->_next = _head;
			_head->_prev = _head;
			_size = 0;
		}
 
		void clear()
		{
			iterator it = begin();
			while (it != end())
			{
				it = erase(it);
			}
 
		}
 
		void swap(list<T>& lt)
		{
			std::swap(_head, lt._head);
			std::swap(_size, lt._size);
		}
 
		list()
		{
			empty_init();
		}
 
		//lt1(lt2)
		list(const list<T>& lt)
		{
 
			empty_init();
			for (auto e : lt)
			{
				push_back(e);
			}
		}
 
		~list()
		{
			clear();
			delete _head;
			_head = nullptr;
		}
 
		list<int>& operator=(list<int>lt)
		{
			swap(lt);
			return *this;
		}
 
		void push_back(const T& x)
		{
			insert(end(), x);
		}
 
		void push_front(const T& x)
		{
			insert(begin(), x);
		}
 
		void pop_back(const T& x)
		{
			erase(--end());
		}
 
		void pop_front(const T& x)
		{
			erase(begin());
		}
 
		iterator insert(iterator pos, const T& x)
		{
			Node* newnode = new Node(x);
			Node* cur = pos._node;
			Node* prev = cur->_prev;
 
			prev->_next = newnode;
			newnode->_prev = prev;
 
			newnode->_next = cur;
			cur->_prev = newnode;
 
			++_size;
			return iterator(newnode);
 
		}
 
		iterator erase(iterator pos)
		{
			Node* cur = pos._node;
			Node* prev = cur->_prev;
			Node* next = cur->_next;
 
			delete cur;
			prev->_next = next;
			next->_prev = prev;
			--_size;
			return iterator(next);
		}
 
		size_t size()
		{
			return _size;
		}
 
	private:
		Node* _head; //list的头结点
		size_t _size;//list的大小
 
	};
}
相关推荐
以后不吃煲仔饭8 分钟前
Java基础夯实——2.7 线程上下文切换
java·开发语言
进阶的架构师9 分钟前
2024年Java面试题及答案整理(1000+面试题附答案解析)
java·开发语言
前端拾光者13 分钟前
利用D3.js实现数据可视化的简单示例
开发语言·javascript·信息可视化
程序猿阿伟15 分钟前
《C++ 实现区块链:区块时间戳的存储与验证机制解析》
开发语言·c++·区块链
傻啦嘿哟33 分钟前
如何使用 Python 开发一个简单的文本数据转换为 Excel 工具
开发语言·python·excel
大数据编程之光37 分钟前
Flink Standalone集群模式安装部署全攻略
java·大数据·开发语言·面试·flink
初九之潜龙勿用37 分钟前
C#校验画布签名图片是否为空白
开发语言·ui·c#·.net
爱摸鱼的孔乙己1 小时前
【数据结构】链表(leetcode)
c语言·数据结构·c++·链表·csdn
Dola_Pan1 小时前
C语言:数组转换指针的时机
c语言·开发语言·算法
ExiFengs1 小时前
实际项目Java1.8流处理, Optional常见用法
java·开发语言·spring