C++初阶——简单实现list

news/2025/2/24 11:15:32

目录

1、前言

2、List.h

3、Test.cpp


1、前言

1. 简单实现std::list,重点:迭代器,模板类,运算符重载。

2. 并不是,所有的类,都需要深拷贝,像迭代器类模板,只是用别的类的资源,不需要深拷贝。

3. 高度相似 -> 模板。

4. 迭代器的种类

功能:iterator,reverse_iterator,const_iterator,const_reverse_iterator。

按结构(性质):决定可以使用什么算法

单向(Forward):forward_list/unordered_map/unordered_set    ++

双向(Bidirectional):list/map/set    ++/--

随机(Random Access):vector/string/deque    ++/--/+/-

2、List.h

#pragma once

#include <iostream>
#include <list>
#include <assert.h>

using namespace std;

namespace Lzc
{
	template<class T>
	struct list_node
	{
		typedef list_node<T> Node;
		T _data;
		Node* _next;
		Node* _prev;
		list_node(const T& data = T())
			:_data(data)
			, _next(nullptr)
			, _prev(nullptr)
		{}
	};

	//template<class T>
	//struct list_iterator
	//{
	//	typedef list_node<T> Node;
	//	typedef list_iterator<T> iterator;
	//	Node* _node;
	//	list_iterator(Node* node)
	//		:_node(node)
	//	{}
	//	T& operator*() const
	//	{
	//		return _node->_data;
	//	}
	//	T* operator->() const
	//	{
	//		return &_node->_data;
	//	}
	//	iterator& operator++() // 前置++
	//	{
	//		_node = _node->_next;
	//		return *this;
	//	}
	//	iterator operator++(int) // 后置++
	//	{
	//		iterator tmp(_node);
	//		_node = _node->_next;
	//		return tmp;
	//	}
	//	iterator& operator--() // 前置--
	//	{
	//		_node = _node->_prev;
	//		return *this;
	//	}
	//	iterator operator--(int) // 后置--
	//	{
	//		iterator tmp(_node);
	//		_node = _node->_prev;
	//		return tmp;
	//	}
	//	bool operator!=(const iterator& it) const
	//	{
	//		return _node != it._node;
	//	}
	//  bool operator==(const iterator& it) const
	//	{
	//		return _node == it._node;
	//	}
	//};

	//template<class T>
	//struct list_const_iterator
	//{
	//	typedef list_node<T> Node;
	//	typedef list_const_iterator<T> const_iterator;
	//	Node* _node;
	//	list_const_iterator(Node* node)
	//		:_node(node)
	//	{
	//	}
	//	const T& operator*() const
	//	{
	//		return _node->_data;
	//	}
	//	const T* operator->() const
	//	{
	//		return &_node->_data;
	//	}
	//	const_iterator& operator++() // 前置++
	//	{
	//		_node = _node->_next;
	//		return *this;
	//	}
	//	const_iterator operator++(int) // 后置++
	//	{
	//		iterator tmp(_node);
	//		_node = _node->_next;
	//		return tmp;
	//	}
	//	const_iterator& operator--() // 前置--
	//	{
	//		_node = _node->_prev;
	//		return *this;
	//	}
	//	const_iterator operator--(int) // 后置--
	//	{
	//		iterator tmp(_node);
	//		_node = _node->_prev;
	//		return tmp;
	//	}
	//	bool operator!=(const const_iterator& it) const
	//	{
	//		return _node != it._node;
	//	}
	// 	bool operator==(const const_iterator& it) const
	//	{
	//		return _node == it._node;
	//	}
	//};

	// 高度相似->模板
	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*() const
		{
			return _node->_data;
		}
		Ptr operator->() const
		{
			return &_node->_data;
		}
		Self& operator++() // 前置++
		{
			_node = _node->_next;
			return *this;
		}
		Self operator++(int) // 后置++
		{
			Self tmp(_node);
			_node = _node->_next;
			return tmp;
		}
		Self& operator--() // 前置--
		{
			_node = _node->_prev;
			return *this;
		}
		Self operator--(int) // 后置--
		{
			Self tmp(_node);
			_node = _node->_prev;
			return tmp;
		}
		bool operator!=(const Self& it) const
		{
			return _node != it._node;
		}
		bool operator==(const Self& it) const
		{
			return _node == it._node;
		}
	};

	template<class T>
	class list
	{
		typedef list_node<T> Node; // 只有list类的成员函数或者友元才能使用这个类型别名
	public:
		typedef list_iterator<T, T&, T*> iterator;
		typedef list_iterator<T, const T&, const T*> const_iterator;
		//typedef list_iterator<T> iterator;
		//typedef list_const_iterator<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_initialize()
		{
			_head = new Node;
			_head->_next = _head->_prev = _head;
			_size = 0;
		}
		list()
		{
			empty_initialize();
		}
		list(initializer_list<T> lt)
		{
			empty_initialize();
			for (auto& e : lt)
			{
				push_back(e);
			}
		}
		list(const list& lt)
		{
			// list();构造函数不能被直接调用
			empty_initialize();
			for (auto& e : lt)
			{
				push_back(e);
			}
		}

		void swap(list& tmp)
		{
			std::swap(_head, tmp._head);
			std::swap(_size, tmp._size);
		}
		list& operator=(const list& lt)
		{
			list tmp(lt);
			swap(tmp);
			return *this;
		}

		void clear()
		{
			while (!empty())
			{
				pop_front();
			}
		}

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

		size_t size() const
		{
			return _size;
		}

		bool empty() const
		{
			return _size == 0;
		}

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

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

		iterator insert(iterator pos, const T& val);

		void pop_front()
		{
			erase(begin());
		}
		void pop_back()
		{
			erase(_head->_prev);
		}

		iterator erase(iterator pos);

	private:
		Node* _head;
		size_t _size;
	};

	template<class T>
	typename list<T>::iterator list<T>::insert(iterator pos, const T& val)
	{
		Node* newNode = new Node(val);
		Node* cur = pos._node;
		Node* prev = cur->_prev;

		prev->_next = newNode;
		newNode->_prev = prev;
		newNode->_next = cur;
		cur->_prev = newNode;

		++_size;

		return newNode;

	}

	template<class T>
	typename list<T>::iterator list<T>::erase(iterator pos)
	{
		assert(pos != _head);
		Node* cur = pos._node;
		Node* next = cur->_next;
		Node* prev = cur->_prev;

		prev->_next = next;
		next->_prev = prev;
		delete cur;

		--_size;

		return next;
	}

	template<class Container>
	void print_Container(const Container& con)
	{
		for (auto& e : con)
		{
			cout << e << " ";
		}
		cout << endl;
	}
}

3、Test.cpp

#include "List.h"

namespace Lzc
{
	struct AA
	{
		int _a1 = 1;
		int _a2 = 1;
	};
	void test_list1()
	{
		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())
		{
			*it += 10;

			cout << *it << " ";
			++it;
		}
		cout << endl;

		for (auto e : lt)
		{
			cout << e << " ";
		}
		cout << endl;
		print_Container(lt);

		list<AA> lta;
		lta.push_back(AA());
		lta.push_back(AA());
		lta.push_back(AA());
		lta.push_back(AA());
		list<AA>::iterator ita = lta.begin();
		while (ita != lta.end())
		{
			//cout << (*ita)._a1 << ":" << (*ita)._a2 << endl;
			cout << ita->_a1 << ":" << ita->_a2 << endl;

			// 特殊处理,本来应该是两个->才合理,为了可读性,省略了一个->
			// cout << ita.operator->()->_a1 << ":" << ita.operator->()->_a2 << endl;
			
			++ita;
		}
		cout << endl;
	}

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

		// insert后,it还指向begin(),没有扩容的概念,不失效
		list<int>::iterator it = lt.begin();
		lt.insert(it, 10); 
		*it += 100;

		print_Container(lt);

		// erase后,it为野指针,及时更新
		// 删除所有的偶数
		it = lt.begin();
		while (it != lt.end())
		{
			if (*it % 2 == 0)
			{
				it = lt.erase(it);
			}
			else
			{
				++it;
			}
		}

		print_Container(lt);
	}

	void test_list3()
	{
		list<int> lt1;
		lt1.push_back(1);
		lt1.push_back(2);
		lt1.push_back(3);
		lt1.push_back(4);

		list<int> lt2(lt1);

		print_Container(lt1);
		print_Container(lt2);

		list<int> lt3;
		lt3.push_back(10);
		lt3.push_back(20);
		lt3.push_back(30);
		lt3.push_back(40);

		lt1 = lt3;
		print_Container(lt1);
		print_Container(lt3);
	}

	void func(const list<int>& lt)
	{
		print_Container(lt);
	}

	void test_list4()
	{
		// 直接构造
		list<int> lt0({ 1,2,3,4,5,6 });
		// 隐式类型转换
		list<int> lt1 = { 1,2,3,4,5,6,7,8 };
		const list<int>& lt3 = { 1,2,3,4,5,6,7,8 };

		func(lt0);
		func({ 1,2,3,4,5,6 });

		print_Container(lt1);

		// template<class T> class initializer_list;
		// { 10, 20, 30 }是一种initializer_list<int>类型
		//auto il = { 10, 20, 30 };
		//initializer_list<int> il = { 10, 20, 30 };
		//cout << typeid(il).name() << endl;
		//cout << sizeof(il) << endl;
	}
}

int main()
{
	Lzc::test_list1();
	Lzc::test_list2();
	Lzc::test_list3();
	Lzc::test_list4();
	return 0;
}

注意:声明和定义分离时,为什么定义时,是list<T>::iterator,不是iterator,因为iterator在list<T>中typedef了,就属于list<T>的成员变量了。


http://www.niftyadmin.cn/n/5864252.html

相关文章

leetcode day20 滑动窗口209+904

209 长度最小的子数组 给定一个含有 n 个正整数的数组和一个正整数 target 。 找出该数组中满足其总和大于等于 target 的长度最小的 子数组 [numsl, numsl1, ..., numsr-1, numsr] &#xff0c;并返回其长度。如果不存在符合条件的子数组&#xff0c;返回 0 。 示例 1&#…

【Python量化金融实战】-第1章:Python量化金融概述:1.4 开发环境搭建:Jupyter Notebook、VS Code、PyCharm

在量化金融开发中&#xff0c;选择合适的开发环境至关重要。本章介绍三种主流工具&#xff1a;Jupyter Notebook&#xff08;交互式分析&#xff09;、VS Code&#xff08;轻量级编辑器&#xff09;、PyCharm&#xff08;专业IDE&#xff09;&#xff0c;并通过实战案例展示其应…

UniApp SelectorQuery 讲解

一、SelectorQuery简介 在UniApp中&#xff0c;SelectorQuery是一个非常强大的工具&#xff0c;它允许开发者查询节点信息。通过这个API&#xff0c;我们可以获取到页面元素的尺寸、位置、滚动条位置等信息。这在处理动态布局、动画效果或是用户交互时尤为重要。 二、基本使用…

【Git 学习笔记_27】DIY 实战篇:利用 DeepSeek 实现 GitHub 的 GPG 密钥创建与配置

文章目录 1 前言2 准备工作3 具体配置过程3.1. 本地生成 GPG 密钥3.2. 导出 GPG 密钥3.3. 将密钥配置到 Git 中3.4. 测试提交 4 问题排查记录5 小结与复盘 1 前言 昨天在更新我的第二个 Vim 专栏《Mastering Vim (2nd Ed.)》时遇到一个经典的 Git 操作问题&#xff1a;如何在 …

亚马逊云科技MySQL托管服务:Amazon RDS for MySQL的技术优势与成本优化实践

引言&#xff1a; 在数字化转型的浪潮中&#xff0c;数据库作为企业核心业务的“中枢神经”&#xff0c;其稳定性、性能及成本直接影响企业的运营效率和竞争力。然而&#xff0c;自建MySQL数据库的复杂性、运维成本高企、扩展性不足等问题&#xff0c;始终是开发者与…

【人工智能】蓝耘智算平台盛大发布DeepSeek满血版:开创AI推理体验新纪元

&#x1f4dd;个人主页&#x1f339;&#xff1a;Eternity._ &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; ❀ 蓝耘智算平台 蓝耘智算平台核心技术与突破元生代推理引擎快速入门&#xff1a;三步调用大模型接口&#xff0c;OpenAI SDK无缝兼容实战用例文…

编程技巧/算法

1、在strings中查找key的位置 来源&#xff1a; BusyBox-1.37.0 index_in_strings()数据结构&#xff1a; static const char keywords[] __attribute__((aligned(1))) "bs\0""count\0""seek\0""skip\0""if\0""…

DeepSeek+Kimi生成高质量PPT

DeepSeek与Kimi生成PPT全流程解析 一、工具分工原理 DeepSeek核心作用&#xff1a;生成结构化PPT大纲&#xff08;擅长逻辑构建与内容优化&#xff09;Kimi核心作用&#xff1a;将文本转换为视觉化PPT&#xff08;提供模板库与排版引擎&#xff09; 二、操作步骤详解 1. 通…