从C++开始的编程生活(13)——list和浅谈stack、queue

前言

本系列文章承接C语言的学习,需要++有C语言的基础++ 才能学会哦~

第13篇主要讲的是有关于C++的++list++ 和++浅谈stack、queue++ 。
C++才起步,都很简单!!

目录

list

基本用法

push_back()

emplace_back()

[reverse( )](#reverse( ))

[merge( )](#merge( ))

[unique( )](#unique( ))

[remove( )](#remove( ))

[splice( )](#splice( ))

sort()

迭代器分类

list的模拟实现

stack和queue


list

底层结构是带头双向循环链表,也是一种顺序容器

因为是带头双向循环,所以其迭代器++end()指向的是哨兵位++ ,++begin()是哨兵位下一个++。

基本用法

push_back()

cpp 复制代码
list<pos> lt;
pos p1(1,1);
lt.push_back(p1);
lt.push_back(pos(2,2);
lt.push_back({3,3});

push_back的++参数必须是对应的类型++,这里是pos,传入的必须为pos,第三个push_back为隐式类型转换。

emplace_back()

cpp 复制代码
lt.emplace_back(p1);
lt.emplace_back(pos(2, 2));
lt.emplace_back(3, 3);

和push_back用法类似,但是++第三行情况下emplace_back更高效(看编译器怎么优化)++。

reverse( )

反转链表。

merge( )

合并++已经排序的++链表,括号内的链表会变为空。

unique( )

去重,只能对++已经排序的链表++使用。

remove( )

移除,相当于find()再erase(),但是++find不到也不会报错++。

splice( )

接合,取一链表或者该链表的一段或者该链表中的一项,粘贴到另一个链表或者改链表的其他位置中,粘贴源被删除。

sort()

排序,list特有的,vector排序可以调用std库的sort,但是list不能用标准库里的sort。这里涉及了迭代器类别的问题。但是**++list.sort()排序的性能比较低++**,数据少或者排序情况少的时候可以用一下。

迭代器分类

|-------|-----------|--------------------------|
| 分类 | 功能 | 常见于容器 |
| 单向迭代器 | ++ | forward_list,unorder_xxx |
| 双向迭代器 | ++/-- | list |
| 随机迭代器 | ++/--/+/- | string/vector |

不同的容器,其迭代器有所不同,功能也有所不同,如果让函数中的迭代器执行功能之外的操作,就会报错。

三者的根据功能,++具有包含与被包含关系++。

list的模拟实现

cpp 复制代码
#pragma once
#include<assert.h>
#include<iostream>
namespace bit
{
	template<class T>
	struct listNode
	{
		//都是公有public,因为各种操作需要访问这些指针
		T _data;
		listNode<T>* _next;
		listNode<T>* _prev;

		list_node(const T& x = T())
			:_data(x)
			, _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;
		}
		//前置
		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;
		}

		Ptr operator->()
		{
			return &_node->_data;
		}

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

	//template<class T>
	//struct list_const_iterator
	//{
	//	typedef list_node<T> Node;
	//	typedef list_const_iterator<T> Self;
	//	Node* _node;

	//	list_const_iterator(Node* node)
	//		:_node(node)
	//	{}

	//	const T& 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;
	//	}

	//	const T& operator->()
	//	{
	//		return &_node->_data;
	//	}

	//	bool operator!=(const Self& s)
	//	{
	//		return _node != s._node;
	//	}
	//};
	//一个用class,一个用struct,是因为一个类既有公有又有私有,我们就用class,反之用struct。
	// 这是一个惯例,不这样做效果也一样
	template<class T>
	class list
	{
		typedef listNode<T> Node;
	public:
		typedef list_iterator<T, T&, T*> iterator;
		typedef const list_iterator<T, const T&, const T*> const_iterator;

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

		iterator end()
		{
			return iterator(_head);
		}

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

		const_iterator end() const
		{
			return iterator(_head);
		}

		~list()
		{
			clear();

			delete _head;
			_head = nullptr;
		}

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

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

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

		list()
		{
			empty_init();
		}

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

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

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

		list(size_t n, cosnt T& val = T())
		{
			empty_init();
			for (size_t i = 0; i < n; i++)
			{
				push_back({ 3,3 });
			}
		}

		void push_back(const T& x)
		{
			//Node* new_node = new Node(x);
			//Node* tail = _head->prex;

			//_tail->_next = new_node;
			//new_node->prec = tail;

			//new_node->_next = _head;
			//_head->_prev = new_node;

			insert(end(), x);
		}

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

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

			prev->_next = newnode;
			newnode->prev = prev;

			newnode->_next = cur;
			cur->_prev = newnode;

			_size++;

			return iterator(newnode);
		}

		iterator erase()
		{
			Node* del = pos._node;
			Node* prev = del->_prev;
			Node* next = del->_next;

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

			--_size;
		}

	private:
		Node* _head;
		size_t _size;
	};
}

stack和queue

栈和队列,是++容器适配器++(之后会深入讲)。

其成员函数与其他的STL容器都十分类似。++特别的是,这两者没有迭代器++。

❤~~本文完结!!感谢观看!!接下来更精彩!!欢迎来我博客做客~~❤

相关推荐
香蕉卜拿拿拿20 小时前
软件解耦与扩展的利器:基于C++与C#的插件式开发实践
c++
知远同学21 小时前
Anaconda的安装使用(为python管理虚拟环境)
开发语言·python
小徐Chao努力21 小时前
【Langchain4j-Java AI开发】09-Agent智能体工作流
java·开发语言·人工智能
CoderCodingNo21 小时前
【GESP】C++五级真题(贪心和剪枝思想) luogu-B3930 [GESP202312 五级] 烹饪问题
开发语言·c++·剪枝
kylezhao201921 小时前
第1章:第一节 开发环境搭建(工控场景最优配置)
开发语言·c#
啃火龙果的兔子21 小时前
JavaScript 中的 Symbol 特性详解
开发语言·javascript·ecmascript
热爱专研AI的学妹1 天前
数眼搜索API与博查技术特性深度对比:实时性与数据完整性的核心差异
大数据·开发语言·数据库·人工智能·python
Mr_Chenph1 天前
Miniconda3在Windows11上和本地Python共生
开发语言·python·miniconda3
阿狸远翔1 天前
Protobuf 和 protoc-gen-go 详解
开发语言·后端·golang
永远前进不waiting1 天前
C复习——1
c语言·开发语言