当前位置: 首页 > news >正文

【C++】list容器的入门及其模拟实现

介绍

在导入头文件<list>之后,我们就可以使用C++内置的list库来使用链表

#include<list>

特点

1.双向迭代:<list> 在有头节点的情况下提供了双向迭代器,可以向前或者向后遍历元素

2.动态大小:<list> 的大小可以动态变化,不需要预先分配固定大小的内存

3.快速插入和删除:可以在列表的任何位置快速插入或删除元素,而不需要像向量那样移动大量元素

 声明和初始化

#include <iostream>
#include <list>

int main() {
    std::list<int> lst1;                  // 空的list
    std::list<int> lst2(5);               // 包含5个默认初始化元素的list
    std::list<int> lst3(5, 10);           // 包含5个元素,每个元素为10
    std::list<int> lst4 = {1, 2, 3, 4};   // 使用初始化列表

    return 0;
}

常用函数

push_back(const T& val)	//在链表末尾添加元素
push_front(const T& val) //在链表头部添加元素
pop_back()	//删除链表末尾的元素
pop_front()	//删除链表头部的元素
insert(iterator pos, val)	//在指定位置插入元素
erase(iterator pos)	//删除指定位置的元素
clear()	//清空所有元素
size()	//返回链表中的元素数量
empty()	//检查链表是否为空
front()	//返回链表第一个元素
back()	//返回链表最后一个元素
remove(const T& val)	//删除所有等于指定值的元素
sort()	 //对链表中的元素进行排序
merge(list& other)	/ /合并另一个已排序的链表
reverse()	//反转链表
begin()    //返回链表的起始迭代器
end()    //返回链表的终点迭代器

模拟实现

 首先我们要用模板函数先定义一个节点的结构和构造函数

template<class T>
struct list_node
{
	T _data;
	list_node<T>* _next;
	list_node<T>* _prev;

    list_node(const T& data = T())
	:_data(data)
	, _next(nullptr)
	, _prev(nullptr)
    {}
};

之后我们使用模板函数定义链表的迭代器

要实现++,--,==等运算符的重载

template<class T, class Ref, class Ptr>
struct list_iterator
{
	typedef list_node<T> Node;
	typedef list_iterator<T, Ref, Ptr> 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)
	{
		Self tmp(*this);
		_node = _node->_next;

		return tmp;
	}

	Self& operator--(int)
	{
		Self tmp(*this);
		_node = _node->_prev;

		return tmp;
	}

	bool operator!=(const Self& s) const
	{
		return _node != s._node;
	}

	bool operator==(const Self& s) const
	{
		return _node == s._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;

	iterator begin()
	{
		return _head->_next;
	}

	iterator end()
	{
		return _head;
	}

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

	const_iterator end() const
	{
		return _head;
	}

	void empty_init()
	{
		_head = new Node;
		_head->_next = _head;
		_head->_prev = _head;
		_size = 0;
	}

	list()
	{
		empty_init();
	}

	list(initializer_list<T> il)
	{
		empty_init();
		for (auto& e : il)
		{
			push_back(e);
		}
	}

	// lt2(lt1)
	list(const list<T>& lt)
	{
		empty_init();

		for (auto& e : lt)
		{
			push_back(e);
		}
	}

	// lt1 = lt3
	list<T>& operator=(list<T> lt)
	{
		swap(lt);
		return *this;
	}

	~list()
	{
		clear();
		delete _head;
		_head = nullptr;
	}

	void clear()
	{
		auto it = begin();
		while (it != end())
		{
			it = erase(it);
		}
	}

	void swap(list<T>& lt)
	{
		std::swap(_head, lt._head);
		std::swap(_size, lt._size);
	}

	void push_back(const T& x)
	{
		insert(end(), x);
	}

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

	iterator insert(iterator pos, const T& x)
	{
		Node* cur = pos._node;
		Node* prev = cur->_prev;
		Node* newnode = new Node(x);

		//结构为prev newnode cur
		newnode->_next = cur;
		cur->_prev = newnode;
		newnode->_prev = prev;
		prev->_next = newnode;

		++_size;

		return newnode;
	}

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

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

	iterator erase(iterator pos)
	{
		assert(pos != end());

		Node* prev = pos._node->_prev;
		Node* next = pos._node->_next;

		prev->_next = next;
		next->_prev = prev;
		delete pos._node;

		--_size;

		return next;
	}

	size_t size() const
	{
		return _size;
	}

	bool empty() const
	{
		return _size == 0;
	}
private:
	Node* _head;
	size_t _size;
};

相关文章:

  • c++为什么支持simd,而java不支持
  • valgrind 检测多线程 bug,检测 并发 bug concurrent bug parallel bug
  • 【gc】家电行业研发部门的阿米巴经营方案
  • DeepSeek 开源周回顾「GitHub 热点速览」
  • 在虚拟机上安装 Hadoop 全攻略
  • LeetCode:1328. 破坏回文串(贪心 Java)
  • 嵌入式硬件发展历程
  • 本地YARN集群部署
  • 【AI论文】Difix3D+: 利用单步扩散模型改进3D重建
  • 【JavaSE-5】程序逻辑控制相关练习题
  • XS9935 ,4通道模拟复合视频解码芯片,双向音频数据同轴共缆传输
  • 如何远程访问svn中的URL
  • 【After Effects AE 动画特效制作笔记】
  • 使用AD画PCB时解决焊盘无法出线的问题
  • CASAIM与承光电子达成深度合作,三维扫描逆向建模技术助力车灯设计与制造向数字化与智能化转型
  • //定义一个方法,实现字符串反转//键盘输入一个字符串,调用该方法后,在控制台输出结果
  • 十一、Redis Sentinel(哨兵)—— 高可用架构与配置指南
  • .keystore文件转成pkcs1.pem文件记录
  • 【GStreamer】基于gst和gtk的简单videoplayer
  • 风虎云龙R87与RH87八卡服务器震撼首发
  • 新疆建设兵团职称查询官方网站/网络推广代理平台
  • 如何注册www 网站/广西关键词优化公司
  • pc建站/软文广告营销
  • 手机网站导航栏特效/锦州网站seo
  • 武汉网站设计制作公司/网盘搜索神器
  • 电子商务网站建设下载/公司网站设计制作