【C++杂货铺】详解 stack 和 queue

这篇具有很好参考价值的文章主要介绍了【C++杂货铺】详解 stack 和 queue。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

【C++杂货铺】详解 stack 和 queue,C++杂货铺,c++,开发语言,学习,笔记,、STL


🌈前言🌈

        欢迎收看本期【C++杂货铺】,本期内容将讲解C++STL中stack和queue的内容,其中包含了stack , queue,priority_queue是什么,怎么使用以及模拟实现这些容器。

        此外,还将将讲解设计模式中的适配器模式,以及STL中stack,queue的底层deque。

【C++杂货铺】详解 stack 和 queue,C++杂货铺,c++,开发语言,学习,笔记,、STL

📁 stack 介绍和使用

 📂 介绍

        stack是一种容器适配器,专门用于具有先进后出的上下文环境,只能从容器的一端进行元素的插入和提取操作。

        stack是作为容器适配器被实现的,容器适配器即是对特定类封装作为其底层的容器,并提供一组特定的成员函数来访问其元素,将特定类作为其底层,元素特定容器的尾部被压入和弹出。

        stack的底层容器可以是任何标准的容器类模板或者一些其他特定的容器类,这些容器类应该支持一下操作:

        ● empty : 判空操作。

        ● back:获取尾部元素操作。

        ● push_back:尾部插入元素操作。

        ● pop_back:尾部删除元素操作。

        标准容器vector,deque,list均符合这些需求,默认情况下,如果没有stack指定特定的底层容器,默认情况下使用deque。

【C++杂货铺】详解 stack 和 queue,C++杂货铺,c++,开发语言,学习,笔记,、STL

📂 使用

stack - C++ Reference (cplusplus.com)

【C++杂货铺】详解 stack 和 queue,C++杂货铺,c++,开发语言,学习,笔记,、STL

#include <iostream>
#include <stack>

using namespace std;

int main()
{
    stack<int> st;

    st.push(1);
    st.push(2);
    st.push(3);

    while(!st.empty())
    {
        cout<<st.top()<<" ";
        st.pop();    
    }
    cout<<endl;
}

 📂 模拟实现

#include<deque>
namespace exercise
{
 template<class T, class Con = deque<T>>
 class stack
 {
 public:
     stack() {}
     void push(const T& x) {_c.push_back(x);}
     void pop() {_c.pop_back();}
     T& top() {return _c.back();}
     const T& top()const {return _c.back();}
     size_t size()const {return _c.size();}
     bool empty()const {return _c.empty();}
 private:
     Con _c;
 };
}

📁 queue 介绍和使用

 📂 介绍

        队列也是一种容器适配器,专门用于先进先出的操作,其中从容器一端插入元素,另一端提取元素。

        队列作为容器适配器实现,容器适配器将特定容器类封装作为其底层容器类,queue提供一组特定的成员函数来访问其元素,元素从队尾入队列,从队头出队列。

        底层容器可以是变化尊模板容器类模板之一,也可以是其他专门设计的容器类,该底层容器应该支持一下操作:

        ● empty : 检测队列是否为空。

        ● size : 返回队列中有效元素的个数。

        ● front : 返回队头元素的引用。

        ● back:返回队尾元素的引用。

        ● push_back:在队列尾部入队列。

        ● pop_back:在队列头部出队列。

        标准容器类deque和list满足这些要求,默认情况下,如果没有为queue实例化指定容器类,则使用标准容器deque。【C++杂货铺】详解 stack 和 queue,C++杂货铺,c++,开发语言,学习,笔记,、STL

 📂 使用

queue - C++ Reference (cplusplus.com)

【C++杂货铺】详解 stack 和 queue,C++杂货铺,c++,开发语言,学习,笔记,、STL

#include <iostream>
#include <queue>

using namespace std;

int main()
{
    queue<int> q;

    q.push(1);
    q.push(2);
    q.push(3);

    while(!q.empty())
    {
        cout<<q.front()<<" ";
        q.pop();
    }
    cout<<endl;
    
    return 0;
}

 📂 模拟实现

#include <deque>
#include <list>
namespace exercise
{
 template<class T, class Con = deque<T>>
 //template<class T, class Con = list<T>>
 class queue
 {
 public:
     queue() {}
     void push(const T& x) {_c.push_back(x);}
     void pop() {_c.pop_front();}
     T& back() {return _c.back();}
     const T& back()const {return _c.back();}
     T& front() {return _c.front();}
     const T& front()const {return _c.front();}
     size_t size()const {return _c.size();}
     bool empty()const {return _c.empty();}
 private:
     Con _c;
 };
}

📁 priority_queue 介绍和使用

 📂 介绍

        优先队列也是一种容器适配器,根据严格的若排序标准,它的第一个元素总是它所包含元中最大的。

        本质上优先队列就是堆,在堆中可以随时插入元素,并且只能检索最大/小元素(优先队列中位于顶部的元素)。

        容器适配器将特定容器类封装为底层容器类,priority_queue提供一组特定的成员函数来访问其元素。元素从特定容器的尾部弹出,其称为优先队列的顶部。

        底层容器可以是任何标准容器类模板,也可以是其他特定设计的容器类,容器应该是可以通过随机访问迭代器访问,支持以下操作:

        ● empty : 检测容器是否为空。

        ● size : 返回容器中有效元素的个数。

        ● front : 返回容器第一个元素的引用。

        ● push_back:在容器尾部插入元素。

        ● pop_back:删除容器尾部元素。

        标准容器类vector和deque满足这些需求。默认情况下,使用vector作为底层容器类。

        需要支持随机访问迭代器,以便始终在内部保持堆结构。容器适配器通过在需要时自动调用算法函数来自动完成操作。

 📂 使用

【C++杂货铺】详解 stack 和 queue,C++杂货铺,c++,开发语言,学习,笔记,、STL

#include <iostream>
#include <queue>

using namespace std;

int main()
{
    //默认建大堆
    //等价于 priority_queue<int,vector<int>,less<int>>
    priority_queue<int> p1;    

    //传递仿函数 , 建小堆
    priority_queue<int,vector<int>,greater<int>> p2;

    p1.push(1);
    p1.push(2);
    p1.push(3);

    p2.push(3);
    p2.push(2);
    p2.push(1);

    //p1 : 3,2,1
    //p2 : 1,2,3
}

 📂 仿函数

        仿函数(Functor)是一种行为类似于函数的对象。在C++中,仿函数可以被当作函数使用,可以执行函数调用操作,并且可以具有自己的状态。

        通常情况下,仿函数是一个类,它重载了函数调用运算符operator()。通过重载该运算符,仿函数可以像函数一样被调用,接受参数并返回结果。重载了operator[]的类,就是仿函数。

        仿函数的对象可以像函数一样调用。

        仿函数可以控制比较逻辑,控制如何比较。

 📂 模拟实现

namespace exercise
{
	template <class T>
	struct less
	{
		bool operator()(const T& x, const T& y)
		{
			return x < y;
		}
	};

	template<class T>
	struct greater
	{
		bool operator()(const T& x, const T& y)
		{
			return  x > y;
		}
	};

	template<class T,class Container = vector<T>,class Compare = less<T>>
	class priority_queue
	{
	public:

		void AdjustUp(int child)
		{
			Compare com;
			int parent = (child - 1) / 2;
			while (child > 0)
			{
				//if (_con[child] > _con[parent])
				if(com(_con[parent],_con[child]))
				{
					std::swap(_con[child], _con[parent]);
					child = parent;
					parent = (child - 1) / 2;
				}
				else
				{
					break;
				}
			}
		}

		void push(const T& val)
		{
			_con.push_back(val);
			AdjustUp(_con.size() - 1);
		}

		void AdjustDown(int parent)
		{
			Compare com;

			int child = parent * 2 + 1;
			while (child < _con.size())
			{
				if (child + 1 < _con.size() && com(_con[child], _con[child + 1]))
				{
					child++;
				}

				if (com(_con[parent], _con[child]))
				{
					std::swap(_con[child],_con[parent]);
					parent = child;
					child = parent * 2 + 1;
				}
				else
				{
					break;
				}
			}
		}

		void pop()
		{
			std::swap(_con[0], _con[_con.size() - 1]);
			_con.pop_back();
			AdjustDown(0);
		}

		size_t size()
		{
			return _con.size();
		}

		bool empty()
		{
			return _con.empty();
		}

		const T& top()
		{
			return _con[0];
		}

	private:
		Container _con;
	};

}

📁 容器适配器

 📂 概念

        适配器是一种设计模式(设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结),该种模式是将一个类的接口转换成客户希望的另外一个接口。

【C++杂货铺】详解 stack 和 queue,C++杂货铺,c++,开发语言,学习,笔记,、STL

 📂 STL库中stack和queue的底层结构

        虽然stack和queue中也可以存放元素,但在STL中并没有讲其划分为容器行列,而是将其称为容器适配器,这是因为stack和queue只是堆其他容器的接口进行包装,STL中stack和queue默认使用deque。

 📂 deque介绍

        deqeue(双端队列):是一种双开口“连续空间的数据结构”。双开口的含义是:可以再头尾两端进行插入和删除操作,且时间复杂度为O(1);和vector比较,头插效率高,不需要搬移元素;和list比,空间利用率较高。

【C++杂货铺】详解 stack 和 queue,C++杂货铺,c++,开发语言,学习,笔记,、STL

        deque并不是真正连续的空间,而是由一端连续的小空间拼接而成的,实际deque类似于一个动态的二维数组,底层结构如下:【C++杂货铺】详解 stack 和 queue,C++杂货铺,c++,开发语言,学习,笔记,、STL

        双端队列底层是一段假象的连续空间,实际是分段连续的,为了维护其“整体连续”以及随机访问的假象,落在deque的迭代器上,因此deque的迭代器的设计比较复杂。如图所示:【C++杂货铺】详解 stack 和 queue,C++杂货铺,c++,开发语言,学习,笔记,、STL

【C++杂货铺】详解 stack 和 queue,C++杂货铺,c++,开发语言,学习,笔记,、STL

        deque的缺陷:

        和vector比较,deque的优势是:头部插入和删除时,不需要搬移元素,效率特别高,而且在扩容时,也不需要搬移大量的元素,因此效率比vector高。

        和list比较,其底层空间时连续的,空间利用率特别高,不需要存储额外字段。

        但是deque有一个致命缺陷,不适合遍历,因为在遍历时,deque的迭代器要频繁的区间所是否移动到某段小空间的边界,导致效率低下,在序列式场合中,肯呢个需要经常遍历,因此在实际中,需要线性结构时,大多数有限考虑vector和list,deque的应用不多,目前的一个应用就是.STL用其为stack和queue的底层容器类。

为什么选择人deque作为stack和queue的底层默认容器:

       stack是一种后进先出的特殊线性数据结构,因此只要具有push_back()和pop_back()操作的线性结构,都可 以作为stack的底层容器,比如vector和list都可以;queue是先进先出的特殊线性数据结构,只要具有 push_back和pop_front操作的线性结构,都可以作为queue的底层容器,比如list。但是STL中对stack和 queue默认选择deque作为其底层容器,主要是因为:

        1. stack和queue不需要遍历(因此stack和queue没有迭代器),只需要在固定的一端或者两端进行操作。

         2. 在stack中元素增长时,deque比vector的效率高(扩容时不需要搬移大量数据);queue中的元素增长 时,deque不仅效率高,而且内存使用率高。

        结合了deque的优点,而完美的避开了其缺陷。

📁 总结

        以上,就是本期【C++杂货铺】stack和queue的主要内容了,包含了它stack,queue,priority_queue的介绍和使用方法,以及他们模拟实现他们的底层。

        此外,还介绍了仿函数是什么,就是一个冲在了operator()的类,使用它的对象就像使用函数一样。

        如果感觉本期内容对你有帮助,欢迎点赞,收藏,关注。Thanks♪(・ω・)ノ

【C++杂货铺】详解 stack 和 queue,C++杂货铺,c++,开发语言,学习,笔记,、STL文章来源地址https://www.toymoban.com/news/detail-849315.html

到了这里,关于【C++杂货铺】详解 stack 和 queue的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【C++杂货铺】引用

    前言:  相信大家在学习C语言的时候,最头疼的就是指针,经常会碰到一级指针、二级指针,这些指针使用起来,稍有不慎就会等导致程序崩溃,为了让广大程序员少掉点头发,C++中提出了 引用 这一概念。当然,在C++的代码中,仍然可以兼容C语言的指针。  在语法上 引用

    2024年02月16日
    浏览(48)
  • 【C++杂货铺】内存管理

    从用途和存储的角度来看,在C/C++程序中有 局部数据、静态数据、全局数据、常量数据、动态申请的数据 五种主要的数据,各种数据的特点如下: 局部数据 :随用随创建,存储在栈区,作用域只在局部,生命周期在局部,出了作用域就销毁。 静态数据 :存储在数据段,作

    2024年02月16日
    浏览(42)
  • 【C++杂货铺】内管管理

    目录 🌈前言🌈 📁 C/C++中内存分布 📁 new 和 delete的使用 📁 new 和 delete的优点 📁 new 和 delete的原理  📂 operator new 和 operator delete函数  📂 内置类型  📂 自定义类型 📁 内存泄漏 📁 总结         欢迎收看本期【C++杂货铺】,本期内容讲解C++内存管理。包含了C++中内存

    2024年04月14日
    浏览(48)
  • 【C++杂货铺】拷贝构造函数

    📖 定义 拷贝构造函数 是构造函数的一个重载 ,它的本质还是 构造函数 ,那就意味着,只有在创建对象的时候,编译器才会自动调用它,那他和普通的构造函数有什么区别呢? 拷贝构造函数,是创建对象的时候,用一个已存在的对象,去初始化待创建的对象 。简单来说,

    2024年02月16日
    浏览(52)
  • 【C++杂货铺】运算符重载

    本文将以日期类为基础,去探寻运算符重载的特性与使用方法,下面先给出日期类的基础定义: 备注 :拷贝构造函数和析构函数,均可以不写,因为当前日期类的三个成员变量都是内置类型,没有动态申请空间,使用浅拷贝就可以。 📖 如何比较两个日期的大小? 现如今,

    2024年02月16日
    浏览(74)
  • 【C++杂货铺】缺省参数、函数重载

     缺省参数是 声明或定义函数时为函数的参数指定一个缺省值 。在调用该函数时,如果没有指定实参则采用该形参的缺省值,否则使用指定的实参。  上面代码在 fun 函数的形参部分给了缺省值10,这意味着在调用 fun 函数的时候可以传参,也可以不传参,如果传参了那形参

    2024年02月16日
    浏览(38)
  • 【C++杂货铺】C++介绍、命名空间、输入输出

     C语言是 结构化 和 模块化 的语言,适合处理 较小规模 的程序。对于复杂的问题,规模较大的程序,需要高度的抽象和建模时,C语言则不合适。为了解决软件危机,20世纪80年代,计算机界提出了 OOP (object oriented programming: 面向对象 )思想,支持面向对象的程序设计语言应

    2024年02月16日
    浏览(42)
  • 【C++杂货铺】再谈类和对象

    在创建对象的时候,编译器通过调用构造函数,在构造函数体中,给对象中的各个成员变量一个合适的初值。 虽然上述构造函数调用之后,对象中已经有了一个初始值,但是不能将其称为对对象中成员变量的初始化, 构造函数体中的语句只能将其称为赋初值,而不能称作初

    2024年02月16日
    浏览(40)
  • 【C++杂货铺】string使用指南

    2024年02月14日
    浏览(45)
  • 【C++杂货铺】初识类和对象

    📖 面向过程 C语言是 面向过程的 ,关注的是过程,分析出求解问题的步骤,通过函数调用逐步解决问题。以洗衣服这件事为例,下图是C语言完成洗衣服这件事的过程。 📖 面向对象 C++是 基于面向对象的 ,关注的是对象,将一件事情拆分成不同的对象,靠对象之间的交互完

    2024年02月16日
    浏览(52)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包