list模拟实现【引入反向迭代器】

文章目录

  • 1.适配器
    • 1.1传统意义上的适配器
    • 1.2语言里的适配器
    • 1.3理解
  • 2.list模拟实现【注意看反向迭代器】
    • 2.1 list_frame.h
    • 2.2riterator.h
    • 2.3list.h
    • 2.4 vector.h
    • 2.5test.cpp
  • 3.反向迭代器的应用
    • 1.使用要求
    • 2.迭代器的分类

1.适配器

1.1传统意义上的适配器

在这里插入图片描述
在这里插入图片描述

1.2语言里的适配器

  1. 容器适配器,如下:
    在这里插入图片描述在这里插入图片描述
    在这里插入图片描述
  2. 迭代器适配器【以下会讲】
  3. 函数适配器【以后会讲】

1.3理解

所谓适配器,其实就是通过C++STL泛型编程的特性,使用模板参数实例化出不同的实体供调用者使用。根据传参实例化出不同实体的过程类似实际生活中的适配器【电源适配器可以转换不同伏特的电流供接收者使用】
例如:程序员实现了一个反向迭代器 在使用vector、list、map时可以将本身的正向迭代器传给模板参数
这样不用在每次用一个新的容器时 重复写反向迭代器 通过模板实例化 增强代码复用性

2.list模拟实现【注意看反向迭代器】

在这里插入图片描述

2.1 list_frame.h

namespace Apex
{
	//结点类
	template<class T>
	struct list_node
	{
		//成员变量
		T _data;
		list_node<T>* _next;
		list_node<T>* _prev;

		//成员函数

		//构造函数
		list_node(const T& data = T());
	};

	//迭代器类
	template<class T, class Ref, class Ptr>
	struct __list_iterator
	{
		typedef list_node<T> Node;
		typedef __list_iterator<T, Ref, Ptr> iterator;

		typedef T value_type;
		typedef Ref reference;
		typedef Ptr pointer;

		//成员变量
		Node* _node;

		//成员函数

		//构造函数
		__list_iterator(Node* node);

		//解引用运算符重载
		Ref operator*();
		//成员访问符重载
		Ptr operator->();

		//前置++
		iterator& operator++();
		//后置++
		iterator operator++(int);
		//前置--
		iterator& operator--();
		//后置--
		iterator operator--(int);

		//关系运算符
		bool operator==(const iterator& it);
		bool operator!=(const iterator& it);
	};

	//链表类
	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;
		typedef __reverse_iterator<iterator, T&, T*> riterator;
		typedef __reverse_iterator<const_iterator, const T&, const T*> const_riterator;

		//成员函数

		//迭代器函数
		iterator begin();
		const_iterator begin() const;
		iterator end();
		const_iterator end() const;
		
		riterator rbegin();
		const_riterator rbegin() const;
		riterator rend();
		const_riterator rend() const;

		//无参构造函数
		list();
		//有参构造函数(初始化n个结点)
		list(size_t n, const T& val = T());
		//迭代器构造函数
		template<class InputIterator>
		list(InputIterator first, InputIterator last);

		//清空链表数据
		void clear();
		//析构函数
		~list();

		//拷贝构造
		list(const list<T>& lt);
		//赋值重载
		list<T>& operator=(list<T> lt);

		//pos前插入
		void insert(iterator pos, const T& x);
		//删除pos处数据
		iterator erase(iterator pos);

		//尾插
		void push_back(const T& x);
		//头插
		void push_front(const T& x);

		//尾删
		void pop_back();
		//头删
		void pop_front();

	private:
		Node* _head;
	};
}


2.2riterator.h

#pragma once

namespace apex
{
	template<class Iterator, class Ref, class Ptr>
	struct __reverse_iterator
	{
		Iterator _cp;
		typedef __reverse_iterator<Iterator, Ref, Ptr> riterator;
		
		typedef Iterator value_type;
		typedef Ref reference;
		typedef Ptr pointer;

		//构造函数
		__reverse_iterator(Iterator it)
			:_cp(it)
		{
		
		}

		//解引用运算符重载
		Ref operator*()
		{
			auto tmp = _cp;
			return *--tmp;
		}
		//成员访问符重载
		Ptr operator->()
		{
			return &(operator*());  //return --_cp.operator->();
		}

		//前置++
		riterator operator++()
		{
			--_cp;
			return *this;
		}
		//后置++
		riterator operator++(int) 
		{
			riterator tmp(*this);
			--_cp;
			return tmp;
		}
		//前置--
		riterator operator--()
		{
			++_cp;
			return *this;
		}
		//后置--
		riterator operator--(int)
		{
			riterator tmp(*this);
			++_cp;
			return tmp;
		}
		//关系运算符
		bool operator==(const riterator& it)
		{
			return _cp == it._cp;
		}
		bool operator!=(const riterator& it)
		{
			return _cp != it._cp;
		}

	};
}

2.3list.h

#include <iostream>
#include <assert.h>
#include "riterator.h"
using namespace std;

namespace apex
{
	//公有类--结点
	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> iterator;

		typedef T value_type;
		typedef Ref reference;
		typedef Ptr pointer;

		//成员属性 _node
		Node* _node;

		//成员函数 

		//构造函数
		__list_iterator(Node* node)
			: _node(node)
		{

		}

		//解引用运算符重载
		Ref operator*()
		{
			return _node->_data;
		}
		//成员访问符重载
		Ptr operator->()
		{
			return &(operator*());
			//return &_node->_data;
		}

		//前置++
		iterator& operator++()   //__list_iterator<T, Ref, Ptr>& operator++() { } 
		{
			_node = _node->_next;
			return *this;
		}
		//后置++
		iterator operator++(int) //__list_iterator<T, Ref, Ptr> operator++(int) { }
		{
			iterator tmp(*this);
			_node = _node->_next;
			return tmp;
		}
		//前置--
		iterator& operator--()
		{
			_node = _node->_prev;
			return *this;
		}
		//后置--
		iterator operator--(int)
		{
			iterator tmp(*this);
			_node = _node->_prev;
			return tmp;
		}
		//关系运算符
		bool operator==(const iterator& it)
		{
			return _node == it._node;
		}
		bool operator!=(const iterator& it)
		{
			return _node != it._node;
		}

	};

	//class类--链表
	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;
		typedef __reverse_iterator<iterator, T&, T*> riterator;
		typedef __reverse_iterator<const_iterator, const T&, const T*> const_riterator;

		//迭代器函数
		iterator begin()
		{
			return iterator(_head->_next);
		}
		iterator end()
		{
			return iterator(_head);
		}
		const_iterator begin() const
		{
			return const_iterator(_head->_next);
		}
		const_iterator end() const
		{
			return const_iterator(_head);
		}
		//反向迭代器函数
		riterator rbegin()
		{
			return riterator(end());
		}
		riterator rend()
		{
			return riterator(begin());
		}
		const_riterator rbegin() const
		{
			return const_riterator(end());
		}
		const_riterator rend() const
		{
			return const_riterator(begin());
		}

		//无参构造函数
		list()
		{
			_head = new Node();
			_head->_next = _head;
			_head->_prev = _head;
		}
		//有参构造函数(初始化n个结点)
		list(size_t n, const T& val = T())
		{
			_head = new Node();
			_head->_next = _head;
			_head->_prev = _head;
			for (size_t i = 0; i < n; i++)
			{
				push_back(val);
			}
		}
		//迭代器构造函数
		template<class InputIterator>
		list(InputIterator first, InputIterator last)
		{
			_head = new Node();
			_head->_next = _head;
			_head->_prev = _head;

			while (first != last)
			{
				push_back(*first);
				first++;
			}
		}

		//清空链表数据
		void clear()
		{
			/*
			iterator it = begin();
			while (it != end())
			{
				iterator del = it++;
				delete del._node;
			}
			//更新哨兵位
			_head->_next = _head;
			_head->_prev = _head;
			*/

			iterator it = begin();
			while (it != end())
			{
				erase(it++);
			}
		}
		//析构函数
		~list()
		{
			clear();
			delete _head;
			_head = nullptr;
		}

		//拷贝构造
		/*
		list(const list<T>& lt)
		{
			_head = new Node();
			_head->_next = _head;
			_head->_prev = _head;
			for (auto e : lt)
			{
				push_back(e);
			}
		}*/
		//拷贝构造plus
		list(const list<T>& lt)
		{
			_head = new Node();
			_head->_next = _head;
			_head->_prev = _head;

			list<T> tmp(lt.begin(), lt.end());
			swap(_head, tmp._head);
		}

		//赋值
		/*
		list<T>& operator=(list<T> lt)
		{
			if (this != &lt)
			{
				clear();
				for (auto e : lt)
				{
					push_back(e);
				}
			}
			return *this;
		}
		*/
		//赋值plus
		list<T>& operator=(list<T> lt)
		{
			swap(_head, lt._head);
			return *this;
		}

		//pos前插入
		void insert(iterator pos, const T& x)
		{
			//prv new cur/pos next
			Node* cur = pos._node;
			Node* prv = cur->_prev;

			Node* newnode = new Node(x);
			//prv连接new
			prv->_next = newnode;
			newnode->_prev = prv;
			//new连接cur
			newnode->_next = cur;
			cur->_prev = newnode;
		}

		//删除pos处数据
		iterator erase(iterator pos)
		{
			assert(pos != end());
			//prv cur/pos next
			Node* cur = pos._node;
			Node* prv = cur->_prev;
			Node* next = cur->_next;

			delete cur;
			//prv连接next
			prv->_next = next;
			next->_prev = prv;

			return iterator(next);
		}

		// 尾插
		void push_back(const T& x)
		{
			/*
			//创建新结点
			Node* newnode = new Node(x);
			//定位尾结点
			Node* tail = _head->_prev;
			//tail连接new
			tail->_next = newnode;
			newnode->_prev = tail;
			//new连接head
			newnode->_next = _head;
			_head->_prev = newnode;
			*/

			insert(end(), x);
		}

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

		//尾删
		void pop_back()
		{
			erase(--end());
		}

		//头删
		void pop_front()
		{
			erase(begin());
		}

	private:
		Node* _head;
	};
	///

		//打印链表(使用const迭代器)
	void print_list(const list<int>& lt)
	{
		list<int>::const_iterator it = lt.begin();
		while (it != lt.end())
		{
			cout << *it << " ";
			it++;
		}
		cout << endl;
	}

	// 无参构造  尾插  迭代器 
	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 *= 2;
			cout << *it << " ";
			it++;
		}
		cout << endl;
		//反向迭代器
		list<int>::riterator rit = lt.rbegin();
		while (rit != lt.rend())
		{
			*rit *= 2;
			cout << *rit << " ";
			rit++;
		}
		cout << endl;
	}

	//打印函数
	void test_list2()
	{
		list<int> lt;
		lt.push_back(2);
		lt.push_back(4);
		lt.push_back(6);
		lt.push_back(8);

		print_list(lt);
	}

	//创建日期类 测试成员访问运算符
	struct Date
	{
		int _year;
		int _month;
		int _day;

		Date(int year = 1, int month = 1, int day = 1)
			: _year(year)
			, _month(month)
			, _day(day)
		{

		}
	};
	void test_list3()
	{
		list<Date> lt;
		lt.push_back(Date(2023, 7, 21));
		lt.push_back(Date(2023, 7, 22));
		lt.push_back(Date(2023, 7, 23));

		list<Date>::iterator it = lt.begin();
		while (it != lt.end())
		{
			cout << it->_year << "-" << it->_month << "-" << it->_day << endl;
			it++;
		}
		cout << endl;
	}

	//拷贝构造函数
	void test_list4()
	{
		list<int> lt1;
		lt1.push_back(1);
		lt1.push_back(2);
		lt1.push_back(3);

		list<int> lt2(lt1);
		for (auto e : lt2)
			cout << e << " ";
	}

	//清空函数
	void test_list5()
	{
		list<int> lt;
		lt.push_back(1);
		lt.push_back(2);
		lt.push_back(3);

		print_list(lt);
		lt.clear();
		print_list(lt);
	}
}


2.4 vector.h

#pragma once
#include <assert.h>
#include <iostream>
#include "riterator.h"
using namespace std;
namespace apex
{
	template<class T>
	//一、vector类
	class vector
	{
	public:
		//迭代器 
		typedef T* iterator;
		typedef const T* const_iterator;
		typedef __reverse_iterator<iterator, T&, T*> riterator;
		typedef __reverse_iterator<const_iterator, const T&, const T*> const_riterator;

		//正向迭代器函数
		iterator begin()
		{
			return _start;
		}
		const_iterator begin() const
		{
			return _start;
		}
		iterator end()
		{
			return _finish;
		}
		const_iterator end() const
		{
			return _finish;
		}

		//正向迭代器函数
		riterator rbegin()
		{
			return riterator(end());
		}
		const_riterator rbegin() const
		{
			return const_riterator(end());
		}
		riterator rend()
		{
			return riterator(begin());
		}
		const_riterator rend() const
		{
			return  const_riterator(begin());
		}

		// 无参构造
		vector()
			:_start(nullptr)
			, _finish(nullptr)
			, _end_of_storage(nullptr)
		{

		}

		// 有参构造
		//T():匿名对象
		vector(size_t n, const T& val = T())
			:_start(nullptr)
			, _finish(nullptr)
			, _end_of_storage(nullptr)
		{
			reserve(n);
			for (size_t i = 0; i < n; ++i)
			{
				push_back(val);
			}
		}

		// 迭代器构造
		//为什么不直接用iterator?
		//iterator只能使用vector 
		//再定义一个模板:可以使用多种类型的迭代器
		template <class InputIterator>
		vector(InputIterator first, InputIterator last)
			:_start(nullptr)
			, _finish(nullptr)
			, _end_of_storage(nullptr)
		{
			while (first != last)
			{
				push_back(*first);
				++first;
			}
		}

		//拷贝构造传统写法1.0
		/*
		vector(const vector<T>& v)
		{
			size_t sz = v.size();
			_start = new T[sz];
			//0.size capacity都行:拷贝内容即可 有可能不对拷贝对象操作
			//1.拷贝的空间是size        对拷贝对象操作  -- 扩容
			//2.拷贝的空间是capacity  不对拷贝对象操作  -- 空间浪费

			//memcpy(_start, v._start, sizeof(T) * sz); ==》无法解决vector<vector<int>>
			//以及下方reserve的问题 使用赋值 -- 自定义类型调用它们各自的赋值重载 -- 实现二层深拷贝

			for (size_t i = 0; i < sz; ++i)
			{
				_start[i] = v._start[i];
			}

			_finish = _start + sz;
			_end_of_storage = _start + sz;
		}
		*/

		//拷贝构造传统写法1.1
		/*
		vector(const vector<T>& v)
			:_start(nullptr)
			, _finish(nullptr)
			, _end_of_storage(nullptr)
		{
			reserve(v.size());       //reserve开空间
			for (const auto& e : v)  //const:防止v被改变
			{
				push_back(e);
			}
		}
		*/

		// 拷贝构造高级写法
		void swap(vector<T>& v)
		{
			std::swap(_start, v._start);
			std::swap(_finish, v._finish);
			std::swap(_end_of_storage, v._end_of_storage);
		}
		vector(const vector<T>& v)
			:_start(nullptr)
			, _finish(nullptr)
			, _end_of_storage(nullptr)
		{
			vector<T> tmp(v.begin(), v.end());//迭代器 -- push_back -- reserve -- 二层深拷贝
			swap(tmp);
		}

		// 赋值重载
		vector<T>& operator=(vector<T> v)
		{
			swap(v);
			return *this;
		}

		//析构函数
		~vector()
		{
			delete[] _start;
			_start = _finish = _end_of_storage = nullptr;
		}

		//获取capacity的大小(vector没有此变量)
		size_t capacity() const
		{
			return _end_of_storage - _start;
		}

		//获取size的大小(vector没有此变量)
		size_t size() const
		{
			return _finish - _start;
		}

		// [] 重载
		T& operator[](size_t pos)
		{
			assert(pos < size());

			return _start[pos];
		}
		const T& operator[](size_t pos) const
		{
			assert(pos < size());

			return _start[pos];
		}

		//扩容 -- 涉及到开新空间 -- 拷贝内容 -- 拷贝的可能是自定义类型
		void reserve(size_t n)
		{
			if (n > capacity())
			{
				size_t sz = size();
				T* tmp = new T[n];

				if (_start != nullptr)
				{
					//memcpy(tmp, _start, sizeof(T) * sz);

					for (size_t i = 0; i < sz; ++i)
					{
						tmp[i] = _start[i];
					}
					delete[] _start;
				}

				_start = tmp;
				_finish = _start + sz;
				_end_of_storage = _start + n;
			}
		}

		//扩容 + 初始化
		void resize(size_t n, const T& val = T())
		{
			//1. n > capacity         -- 扩容 + 初始化
			if (n > capacity())
			{
				reserve(n);
			}
			//2. size < n < capacity  -- 初始化
			if (n > size())
			{
				while (_finish < _start + n)
				{
					*_finish = val;
					++_finish;         //finish移到新的"end"==>_start + n
				}
			}
			//3. n < size              -- 删除数据
			else
			{
				_finish = _start + n;  //直接更新finish即可
			}
		}

		//增加数据                                        (可修改)
		//const:匿名对象  隐式转换(临时变量【具有常性】)  左值 + 右值  
		void push_back(const T& x)
		{
			/*
				if (_finish == _end_of_storage)
				{
					reserve(capacity() == 0 ? 4 : capacity() * 2);
				}

				*_finish = x;
				++_finish;
			*/

			insert(end(), x);
		}

		// pop_back
		void pop_back()
		{
			assert(_finish > _start);
			--_finish;
		}

		// insert
		iterator insert(iterator pos, const T& x)
		{
			assert(pos >= _start && pos <= _finish);

			if (_finish == _end_of_storage)
			{
				size_t len = pos - _start;

				reserve(capacity() == 0 ? 4 : capacity() * 2); //扩容后 空间地址更新 pos仍指向原空间pos处
				//走下面的while时 访问pos --> error
				pos = _start + len;                            //为防止pos失效 连带更新pos
			}

			// 挪动数据
			iterator end = _finish - 1;
			while (end >= pos)
			{
				*(end + 1) = *end;
				--end;
			}
			*pos = x;

			++_finish;

			return pos;
		}

		// erase
		iterator erase(iterator pos)
		{
			assert(pos >= _start);
			assert(pos < _finish);

			iterator begin = pos + 1;
			while (begin < _finish)
			{
				*(begin - 1) = *begin;
				++begin;
			}

			--_finish;

			if (size() < capacity() / 2)
			{
				// 缩容 -- 以时间换空间
				//缩容--空间更新--pos失效--更新pos--只能解决形参作用域内的pos失效
				//当再次erase--访问pos :error
			}

			return pos; // 删除数据之后 返回pos --> pos指向被删除的值 
			// 目标值被删除后 数据前移 pos指向空间不变 只不过pos指向的值是 目标值后的值
		}

		//front
		T& front()
		{
			assert(size() > 0);

			return *_start;
		}

		//back
		T& back()
		{
			assert(size() > 0);

			return *(_finish - 1);
		}

	private:
		iterator _start;
		iterator _finish;
		iterator _end_of_storage;
	};

	//二、命名空间内的函数

	// 增 删 [] size() 迭代器 范围for
	void test_vector1()
	{
		vector<int> v;

		//push_back
		v.push_back(1);
		v.push_back(2);
		v.push_back(3);
		v.push_back(4);
		v.push_back(5);

		// []  size()
		for (size_t i = 0; i < v.size(); ++i)
		{
			cout << v[i] << " ";
		}
		cout << endl;

		//正向迭代器
		vector<int>::iterator it = v.begin();
		while (it != v.end())
		{
			cout << *it << " ";
			++it;
		}
		cout << endl;
		
		//反向迭代器
		vector<int>::riterator rit = v.rbegin();
		while (rit != v.rend())
		{
			cout << *rit << " ";
			++rit;
		}
		cout << endl;

		//pop_back
		v.pop_back();
		v.pop_back();

		//范围for
		for (auto e : v)
		{
			cout << e << " ";
		}
		cout << endl;
	}

	// 迭代器失效问题(1) -- insert(野指针问题)
	void test_vector2()
	{
		vector<int> v;
		v.push_back(1);
		v.push_back(2);
		v.push_back(3);
		v.push_back(4);
		v.push_back(5);

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

		auto p = find(v.begin(), v.end(), 3);
		if (p != v.end())
		{
			v.insert(p, 30);
			//在p位置插入数据后不要访问p-->p可能失效:
			//插入需要扩容 扩容会更新空间地址 pos仍指向源空间的pos处 pos失效
			//即便改进了insert代码 更新了pos -->解决了insert中while循环内访问pos的问题 
			//但是形参改变不影响实参  在作用外pos仍失效 
			//为什么不使用引用?
			//v.insert(v.begin(), 1); -->
			//iterator begin()
			//{
			//	 return _start;
			//}
			//返回临时拷贝--具有常性--与引用可以修改的特性不匹配
			//那改成:const iterator& pos -->
			//内部无法对_start修改
			//

			/*
			* cout << *p << endl;
			v.insert(p, 40);
			*/
		}

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

	// erase
	void test_vector3()
	{
		vector<int> v;
		v.push_back(1);
		v.push_back(2);
		v.push_back(3);
		v.push_back(4);
		for (auto e : v)
		{
			cout << e << " ";
		}
		cout << endl;

		auto p = find(v.begin(), v.end(), 3);
		if (p != v.end())
		{
			v.erase(p);
		}

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

		v.erase(v.begin());

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

	// 迭代器失效问题(2) -- erase 删除所有的偶数 (迭代器位置问题)
	void test_vector4()
	{
		// 正常运行--lucky
		// 1 2 3 4 5 --> 1 3 5 -- it == end 循环结束
		vector<int> v;
		v.push_back(1);
		v.push_back(2);
		v.push_back(3);
		v.push_back(4);
		v.push_back(5);
		// 崩溃
		// 1 2 3 4 --> 1 4 -- end在4后一个 it在4后两个 it != end 循环无法结束
		v.push_back(1);
		v.push_back(2);
		v.push_back(3);
		v.push_back(4);
		// 结果不对
		// 1 2 4 3 4 5 -- erase 2 --> 1 4 3 4 5  it再++ 直接跳过4
		v.push_back(1);
		v.push_back(2);
		v.push_back(4);
		v.push_back(3);
		v.push_back(4);
		v.push_back(5);

		auto it = v.begin();

		//错误
		/*
		while (it != v.end())
		{
			if (*it % 2 == 0)
			{
				v.erase(it);
			}

			++it;
		}
		*/

		//正确
		while (it != v.end())
		{
			if (*it % 2 == 0)
			{
				it = v.erase(it); //it不在++ 而是停留在此处
			}
			else                  //是奇数才++
			{
				++it;
			}
		}

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

	// 迭代器失效问题(3) -- insert (扩容野指针 + 迭代器位置问题)
	void test_vector5()
	{
		vector<int> v;
		v.push_back(1);
		v.push_back(2);
		v.push_back(3);
		v.push_back(4);

		// 在所有偶数前插入该数2倍的值
		auto it = v.begin();
		while (it != v.end())
		{
			if (*it % 2 == 0)
			{
				it = v.insert(it, *it * 2); //1.it重新赋值:插入大概率回扩容 一旦扩容 空间更新 it成为野指针
				//  insert函数返回新的指向原位置的迭代器 it重新赋值 成功解决问题
				//2.插入后不再 ++ :使it停留在此处

// 下面两次++是按题意 1 2 3 ——> 1 4 2 3 
// --> it指向4  ++两次指向3(即进行下一次寻找)
				++it;
				++it;
			}
			else
			{
				++it;
			}
		}

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

	// 迭代器失效问题(4) -- erase (缩容野指针 + 迭代器位置问题)
	/*
	待实现
	*/

	//总结:迭代器失效问题 
	//1.扩容导致的野指针问题
	//2.插入或删除导致的迭代器位置错误问题

		//拷贝构造 
	void test_vector6()
	{
		vector<int> v;
		v.push_back(1);
		v.push_back(2);
		v.push_back(3);
		v.push_back(4);
		v.push_back(5);
		// 1 2 3 4 5
		for (auto e : v)
		{
			cout << e << " ";
		}
		cout << endl;
		//拷贝构造
		vector<int> v1(v);
		v[0] *= 10;        //深拷贝
		// 10 2 3 4 5
		for (auto e : v)
		{
			cout << e << " ";
		}
		cout << endl;
		// 1 2 3 4 5
		for (auto e : v1)
		{
			cout << e << " ";
		}
		cout << endl;
	}

	//迭代器构造
	void test_vector7()
	{
		string s("hello world");
		vector<int> vs(s.begin(), s.end());
		for (auto e : vs)
		{
			cout << e << " ";
		}
		cout << endl;

		vector<int> v;
		v.push_back(1);
		v.push_back(2);
		v.push_back(3);
		v.push_back(4);
		v.push_back(5);

		vs = v;               // 赋值重载:针对两个已经存在的对象
		vector<int> copy = v; // 拷贝构造 ==》copy(v); 
		//copy不存在 用一个已有的对象去初始化一个新对象

		vs[0] *= 10;
		for (auto e : vs)
		{
			cout << e << " ";
		}
		cout << endl;

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

	// 有参构造
	void test_vector8()
	{
		//C++引入了模板 ==》内置类型也可以有构造
		/*
		int i = 0;
		int j = int();
		int k = int(10);
		*/

		//正常运行
		vector<int> v1(10);
		for (auto e : v1)
		{
			cout << e << " ";
		}
		cout << endl;

		//正常运行
		vector<char> v3(10, 'a');
		for (auto e : v3)
		{
			cout << e << " ";
		}
		cout << endl;

		// 编译错误:参数匹配
		//<int> v2(10, 1);
		//1.vector(size_t n, const T & val = T()) ;            
		//2.vector(InputIterator first, InputIterator last);
		//1.int-->u_int int-->T    匹配程度低
		//2.int-->T     int-->T 【有解引用操作】

		//修正1.0:
		vector<int> v2(10u, 1); //第一种匹配程度变高 -- ok
		//修正2.0:
		//vector(int n, const T & val = T()) ; 
		for (auto e : v2)
		{
			cout << e << " ";
		}
		cout << endl;

	}

	// resize
	void test_vector9()
	{
		vector<int> v1;
		v1.resize(10, 0);
		for (auto e : v1)
		{
			cout << e << " ";
		}
		cout << endl;

		vector<int> v2;
		v2.reserve(10);
		v2.push_back(1);
		v2.push_back(2);
		v2.push_back(3);
		v2.push_back(4);
		v2.push_back(5);

		v2.resize(8, 8);
		for (auto e : v2)
		{
			cout << e << " ";
		}
		cout << endl;

		v2.resize(20, 20);
		for (auto e : v2)
		{
			cout << e << " ";
		}
		cout << endl;

		v2.resize(3);
		for (auto e : v2)
		{
			cout << e << " ";
		}
		cout << endl;
	}

	//vv的深拷贝天坑
	void test_vector10()
	{
		class Solution
		{
		public:
			vector<vector<int>> generate(int n)
			{
				vector<vector<int>> Vv;
				Vv.resize(n);
				for (size_t i = 0; i < Vv.size(); ++i)
				{
					Vv[i].resize(i + 1, 0);
					Vv[i].front() = Vv[i].back() = 1;
				}

				for (size_t i = 0; i < Vv.size(); ++i)
				{
					for (size_t j = 0; j < Vv[i].size(); ++j)
					{
						if (Vv[i][j] == 0)
						{
							Vv[i][j] = Vv[i - 1][j] + Vv[i - 1][j - 1];
						}
					}
				}
				//打印查看
				for (size_t i = 0; i < Vv.size(); ++i)
				{
					for (size_t j = 0; j < Vv[i].size(); ++j)
					{
						cout << Vv[i][j] << " ";
					}
					cout << endl;
				}

				return Vv;
			}
		};
		vector<vector<int>> ret = Solution().generate(5);
	}
}





2.5test.cpp

#define _CRT_SECURE_NO_WARNINGS 
#include <iostream>
#include <list>
#include <vector>
#include <algorithm>
#include <array>
#include <time.h>
#include <queue>
using namespace std;


#include "list.h"
#include "vector.h"

int main()
{
	apex::test_vector1();
	return 0;
}

3.反向迭代器的应用

1.使用要求

该容器要能够实现++、–操作,如单向链表或单向map不可使用。

2.迭代器的分类

单向迭代器forward_iterator_tag:支持++:forward_list、unordered_map、unordered_set、
双向迭代器bidirectional_iterator_tag:支持++ --:list 、map、set、
随机迭代器random_access_iterator_tag:支持++ – + -:deque、vector
只读迭代器
只写迭代器

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/66991.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

linux下绑定进程到指定CPU的操作方法

taskset简介 # taskset Usage: taskset [options] [mask | cpu-list] [pid|cmd [args...]] Show or change the CPU affinity of a process. Options: -a, --all-tasks operate on all the tasks (threads) for a given pid -p, --pid operate on ex…

Linux知识点 -- 进程信号(一)

Linux知识点 – 进程信号&#xff08;一&#xff09; 文章目录 Linux知识点 -- 进程信号&#xff08;一&#xff09;一、理解信号1.理解Linux信号2.信号的产生与处理3.常见的信号4.如何理解组合键变成信号5.如何理解信号被进程保存 二、信号的产生1.键盘产生2.核心转储3.系统调…

go-zero 是如何实现计数器限流的?

原文链接&#xff1a; 如何实现计数器限流&#xff1f; 上一篇文章 go-zero 是如何做路由管理的&#xff1f; 介绍了路由管理&#xff0c;这篇文章来说说限流&#xff0c;主要介绍计数器限流算法&#xff0c;具体的代码实现&#xff0c;我们还是来分析微服务框架 go-zero 的源…

LinearAlgebraMIT_7_Ax=0

上节课讲了向量子空间中的列空间和零空间&#xff0c;这节课来讲零空间的(Special solutions)特解&#xff0c;也就是Ax0的特解。在求解特解的核心便是使用消元法求得(row echelon form)阶梯矩阵或者(reduced row echelon form/RREF)最简矩阵。 我们接下来举一个例子&#xff…

【sonar】安装sonarQube免费社区版9.9【Linux】【docker】

文章目录 ⛺sonarQube 镜像容器⛺Linux 安装镜像&#x1f341;出现 Permission denied的异常&#x1f341;安装sonarQube 中文包&#x1f341;重启服务 ⛺代码上传到sonarQube扫描&#x1f341;java语言配置&#x1f341;配置 JS TS Php Go Python⛏️出现异常sonar-scanner.ba…

【设计模式】观察者模式

什么是观察者模式&#xff1f; 观察者模式&#xff08;又被称为发布-订阅&#xff08;Publish/Subscribe&#xff09;模式&#xff0c;属于行为型模式的一种&#xff0c;它定义了一种一对多的依赖关系&#xff0c;让多个观察者对象同时监听某一个主题对象。这个主题对象在状态…

现代C++中的从头开始深度学习:【5/8】卷积

一、说明 在上一个故事中&#xff0c;我们介绍了机器学习的一些最相关的编码方面&#xff0c;例如 functional 规划、矢量化和线性代数规划。 现在&#xff0c;让我们通过使用 2D 卷积实现实际编码深度学习模型来开始我们的道路。让我们开始吧。 二、关于本系列 我们将学习如何…

VS+Qt+C++旅游景区地图导航源码实例

程序示例精选 VSQtC旅游景区地图导航 如需安装运行环境或远程调试&#xff0c;见文章底部个人QQ名片&#xff0c;由专业技术人员远程协助&#xff01; 前言 这篇博客针对<<VSQtC旅游景区地图导航>>编写代码&#xff0c;代码整洁&#xff0c;规则&#xff0c;易读。…

服务器数据恢复-RAID5上层Hyper-V虚拟机数据恢复案例

服务器数据恢复环境&#xff1a; 一台Windows Server服务器&#xff0c;部署Hyper-V虚拟化环境&#xff0c;虚拟机的硬盘文件和配置文件存放在一台DELL存储中。该存储中有一组由4块硬盘组建的RAID5阵列&#xff0c;用来存放虚拟机的数据文件&#xff0c;另外还有一块大容量硬盘…

Android Studio实现Spinner下拉列表

效果图 点击下拉列表 点击某一个下拉列表 MainActivity package com.example.spinneradapterpro;import androidx.appcompat.app.AppCompatActivity;import android.os.Bundle; import android.view.View; import android.widget.AdapterView; import android.widget.Spinn…

原型模式与享元模式:提升系统性能的利器

原型模式和享元模式&#xff0c;前者是在创建多个实例时&#xff0c;对创建过程的性能进行调优&#xff1b;后者是用减 少创建实例的方式&#xff0c;来调优系统性能。这么看&#xff0c;你会不会觉得两个模式有点相互矛盾呢&#xff1f; 在有些场景下&#xff0c;我们需要重复…

Java # Spring(2)

一、Spring事物 一、分类 编程式事物&#xff1a;代码中硬编码&#xff08;不推荐使用&#xff09; 声明式事物&#xff1a;配置文件中配置&#xff08;推荐使用&#xff09; 分类&#xff1a; 基于xml的声明式事物基于注解的声明式事物 二、隔离级别 ISOLATION_DEFAULT&…

Android 视频播放器dkplayer

列表播放如图所示&#xff1a; 一、依赖 //添加RecyclerView的依赖包implementation androidx.recyclerview:recyclerview:1.2.1// 异步加载图片依赖implementation com.squareup.picasso:picasso:2.5.2// 上拉刷新、下来加载依赖implementation com.scwang.smartrefresh:Smart…

mysql之存储过程

目录 一、mysql之存储过程的相关知识 1&#xff09;存储过程的概念 2&#xff09;存储过程的优点 二、存储过程的管理 1&#xff09;创建存储过程 基本格式&#xff1a; 2&#xff09;调用存储过程 格式&#xff1a; call 存储过程名称 3&#xff09;查看存储过程 查…

Leetcode-每日一题【剑指 Offer 13. 机器人的运动范围】

题目 地上有一个m行n列的方格&#xff0c;从坐标 [0,0] 到坐标 [m-1,n-1] 。一个机器人从坐标 [0, 0] 的格子开始移动&#xff0c;它每次可以向左、右、上、下移动一格&#xff08;不能移动到方格外&#xff09;&#xff0c;也不能进入行坐标和列坐标的数位之和大于k的格子。例…

51单片机学习--红外遥控(外部中断)

需要利用下面这个红外接收头&#xff0c;OUT口会发出红外信号对应的高低电平&#xff0c;由于发送的速度很快&#xff0c;所以需要把OUT引脚接在外部中断引脚上&#xff0c;当OUT一旦产生下降沿&#xff0c;马上进中断&#xff0c;这样响应会更及时。 外部中断引脚位于P3_2和P…

【云原生】kubernetes控制器deployment的使用

目录 ​编辑 1 Controller 控制器 1.1 什么是 Controller 1.2 常见的 Controller 控制器 1.3 Controller 如何管理 Pod 2 Deployment 2.1 创建 deployment 2.2 查看 deployment 2.3 扩缩 deployment 2.4 回滚 deployment 2.5 删除 deployment 1 Controller 控制器 …

条条大路通罗马系列—— 使用 Hiredis-cluster 连接 Amazon ElastiCache for Redis 集群

前言 Amazon ElastiCache for Redis 是速度超快的内存数据存储&#xff0c;能够提供亚毫秒级延迟来支持 实时应用程序。适用于 Redis 的 ElastiCache 基于开源 Redis 构建&#xff0c;可与 Redis API 兼容&#xff0c;能够与 Redis 客户端配合工作&#xff0c;并使用开放的 Re…

【算法篇C++实现】五大常规算法

文章目录 &#x1f680;一、分治法⛳&#xff08;一&#xff09;算法思想⛳&#xff08;二&#xff09;相关代码 &#x1f680;二、动态规划算法⛳&#xff08;一&#xff09;算法思想⛳&#xff08;二&#xff09;相关代码 &#x1f680;三、回溯算法⛳&#xff08;一&#xf…

数据挖掘具体步骤

数据挖掘具体步骤 1、理解业务与数据 2、准备数据 数据清洗&#xff1a; 缺失值处理&#xff1a; 异常值: 数据标准化&#xff1a; 特征选择&#xff1a; 数据采样处理&#xff1a; 3、数据建模 分类问题&#xff1a; 聚类问题&#xff1a; 回归问题 关联分析 集成学习 image B…
最新文章