STL-stack、queue和priority_queue的模拟实现

news2024/12/23 22:52:40

目录

一、容器适配器

(一)什么是适配器

(二)stack和queue的底层结构

二、Stack

三、queue

四、deque双端队列

(一)优点

(二)缺陷

五、优先级队列

(一)介绍

(二)仿函数

(三)模拟实现一

(四)模拟实现(带compare)


一、容器适配器

(一)什么是适配器

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

(二)stack和queue的底层结构

  • stack和queue没有迭代器

Container 也是一个模板参数,它用于指定在 stack 内部使用的容器类型。默认情况下,它使用了一个 deque(双端队列)作为内部容器,但你也可以自定义一个不同类型的容器来替代它 。

二、Stack

  • 模拟实现stack,stack是先进后出
#pragma once
#include<iostream>
#include<deque>
using namespace std;
namespace Imitate_stack
{
	template <class T, class Container = deque<T> >
	class stack
	{
	public:
		void push(const T& x)//插入数据
		{
			_con.push_back(x);
		}

		void pop()//删除数据
		{
			_con.pop_back();//用于移除并返回双端队列的最右端(尾部)元素
		}

		const T& top()
		{
			return _con.back();//用于返回双端队列的最右端(尾部)元素,但不会从队列中删除该元素
		}

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

		size_t size()
		{
			return _con.size();
		}
	private:
		Container _con;
	};
}

三、queue

  • queue是先进先出
#pragma once
#include<iostream>
#include<deque>
using namespace std;
namespace Imitate_stack
{
	template <class T, class Container = deque<T> >
	class queue
	{
	public:
		void push(const T& x)//尾插
		{
			_con.push_back(x);
		}

		void pop()//头删
		{
			_con.pop_front();
		}

		const T& back()//得到尾部数据
		{
			return _con.back();
		}

		const T& front()//得到头部数据
		{
			return _con.front();
		}

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

		size_t size()
		{
			return _con.size();
		}
	private:
		Container _con;
	};
}

四、deque双端队列

(一)优点

是一种双开口的"连续"空间的数据结构,双开口的含义是:可以在头尾两端进行插入和删除操作,且时间复杂度为O(1)

  • 与vector比较,头插效率高,不需要搬移元素
  • 与list比较,空间利用率比较高

(二)缺陷

  • 下标的随机访问不如vector
  • 中间插入、删除速度不如list
  • 不适合遍历,因为在遍历时,deque的迭代器要频繁的去检测其是否移动到
    某段小空间的边界,导致效率低下

五、优先级队列

(一)介绍

priority_queue<int> first;//建立大根堆
priority_queue<int> first(data.begin(), data.end());//建立大根堆
priority_queue<int, vector<int>, greater<int>> second;//建立小根堆
#include<iostream>
#include<queue>
using namespace std;
int main()
{
	priority_queue<int> first;//建立大根堆
	first.push(56);
	first.push(12);
	first.push(67);
	first.push(1);
	first.push(78);
	first.push(6);
	while (!first.empty())//78 67 56 12 6 1
	{
		cout << first.top() << " ";
		first.pop();
	}
	return 0;
}
#include<iostream>
#include<vector>
#include<queue>
using namespace std;
int main()
{
	vector<int>data = {56,12,67,1,78,6};
	priority_queue<int> first(data.begin(), data.end());//建立大根堆

	while (!first.empty())//78 67 56 12 6 1
	{
		cout << first.top() << " ";
		first.pop();
	}
	return 0;
}
#include<iostream>
#include<queue>
using namespace std;
int main()
{
	priority_queue<int, vector<int>, greater<int>> second;//建立小根堆
	second.push(56);
	second.push(12);
	second.push(67);
	second.push(1);
	second.push(78);
	second.push(6);
	while (!second.empty())//1 6 12 56 67 78
	{
		cout << second.top() << " ";
		second.pop();
	}
	return 0;
}

(二)仿函数

#include<iostream>
using namespace std;
template<class T>
class Less
{
public:
	bool operator()(const T& x, const T& y)
	{
		return x < y;
	}
};
template<class T>
class greater
{
public:
	bool operator()(const T& x, const T& y)
	{
		return x > y;
	}
};
int main()
{
	Less<int> less1;//函数对象
	cout << less1(1, 3) << endl;

	Less<double> less2;
	cout << less1(4.5, 3.5) << endl;
	return 0;
}

(三)模拟实现一

PriorityQueue.h
#pragma once
#include<iostream>
#include<vector>
using namespace std;
namespace Imitate_priorityQueue
{
	template<class T, class Container = vector<T>>
	class priority_queue
	{
	public:
		void adjust_up(int child)//向上调整
		{
			int parent = (child - 1) / 2;
			while (child >0 )
			{
				if (_con[child] > _con[parent])//建立大根堆
				{
					swap(_con[child], _con[parent]);
					child = parent;
					parent = (child - 1) / 2;
				}
				else
				{
					break;
				}
			}
		}

		void adjust_down(int parent)//向下调整
		{
			int child = parent * 2 + 1;
			while (child < _con.size())
			{
				if (child + 1 < _con.size() && _con[child] < _con[child + 1])//开始默认右孩子大
				{
					++child;
				}
				if (_con[child] > _con[parent])
				{
					swap(_con[child], _con[parent]);
					parent=child;
					child = parent * 2 + 1;
				}
				else
				{
					break;
				}
			}
		}

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

		void pop()
		{
			swap(_con[0], _con[_con.size() - 1]);
			_con.pop_back();
			adjust_down(0);
		}
		const T& top()const
		{
			return _con.front();
		}

		bool empty()const
		{
			return _con.empty();
		}
	private:
		Container _con;
	};

}
test.h
#include"PriorityQueue.h"
int main()
{
	Imitate_priorityQueue::priority_queue<int, vector<int>> q;
	q.push(89);
	q.push(1);
	q.push(45);
	q.push(14);
	q.push(11);
	q.push(19);
	while (!q.empty())//89 45 19 14 11 1
	{
		cout << q.top() << " ";
		q.pop();
	}
	return 0;

}

(四)模拟实现(带compare)

 

PriorityQueue.h

#pragma once
#include<iostream>
#include<vector>
using namespace std;
namespace Imitate_priorityQueue
{
	比较方式
	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 adjust_up(int child)//向上调整
		{
			int parent = (child - 1) / 2;
			while (child >0 )
			{
				if (_com(_con[parent],_con[child]))
				{
					swap(_con[child], _con[parent]);
					child = parent;
					parent = (child - 1) / 2;
				}
				else
				{
					break;
				}
			}
		}

		void adjust_down(int parent)//向下调整
		{
			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]))
				{
					swap(_con[child], _con[parent]);
					parent=child;
					child = parent * 2 + 1;
				}
				else
				{
					break;
				}
			}
		}

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

		void pop()
		{
			swap(_con[0], _con[_con.size() - 1]);
			_con.pop_back();
			adjust_down(0);
		}
		const T& top()const
		{
			return _con.front();
		}

		bool empty()const
		{
			return _con.empty();
		}
	private:
		Container _con;
		Compare _com;
	};

}
#include"PriorityQueue.h"
int main()
{
	Imitate_priorityQueue::priority_queue<int, vector<int>, greater<int>> q;
	q.push(89);
	q.push(1);
	q.push(45);
	q.push(14);
	q.push(11);
	q.push(19);
	while (!q.empty())
	{
		cout << q.top() << " ";
		q.pop();
	}
	return 0;

}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何在终端输出颜色

效果演示: 【看 welcome to here 部分】 环境&#xff1a; Node.js 18.16.0 正文部分 我们可以通过 console.log() 在终端打印字符串。 只要在我们的字符串前面加上转义字符即可。 差不多就是下面这样的结构&#xff1a; 用代码就是&#xff1a; console.log("\x1B…

学习记忆——宫殿篇——记忆宫殿——地点桩——演讲稿定位记忆

其实在演讲的时候有很多人会遇到这样的情况&#xff0c;演讲内容准备的滚瓜烂熟&#xff0c;但是当自己在台上十分紧张的时候&#xff0c;突然忘记要说的内容。 今天在这里就用记忆宫殿的方法为大家解决这样一个问题。 注意&#xff1a;我们在运用这种记忆方法的前提是你已经对…

python笔记:pandas/geopandas DataFrame逐行遍历

在Pandas和GeoPandas中&#xff0c;可以使用几种不同的方法来遍历DataFrame的每一行 0 数据 import pandas as pddata {column1: range(1, 1001),column2: range(1001, 2001) } df pd.DataFrame(data) df 1 iterrows for index, row in df.iterrows():print(index)print(r…

SRT服务器SLS

目前互联网上的视频直播有两种&#xff0c;一种是基于RTMP协议的直播&#xff0c;这种直播方式上行推流使用RTMP协议&#xff0c;下行播放使用RTMP&#xff0c;HTTPFLV或者HLS&#xff0c;直播延时一般大于3秒&#xff0c;广泛应用秀场、游戏、赛事和事件直播&#xff0c;满足了…

MySQL的复合查询

文章目录 1. 多表查询2. 自连接3. 子查询3.1 单行子查询3.2 多行单列子查询3.3 单行多列子查询3.4 在from子句中使用子查询 4. 合并查询4.1 union all4.2 union 5. 内连接6. 外连接6.1 左外连接6.2 右外连接 1. 多表查询 前面我们讲解的mysql表的查询都是对一张表进行查询&…

[架构之路-230]:计算机硬件与体系结构 - 可靠性、可用性、稳定性;MTTF、MTTR、MTBF

目录 一、软件质量属性 二、可靠性、可用性、稳定性区别 2.1 比较 2.2 公式比较 2.3 "正常工作时间"和"正常运行时间" 2.4 比较案例 2.5 可用性好但可靠性较差的示例 三、MTTF、MTTR、MTBF 3.1 图示 3.2 定义 &#xff08;1&#xff09;MTTF&am…

【uniapp+vue3+ts】请求函数封装,请求和上传文件拦截器

1、uniapp 拦截器 uni.addInterceptor(STRING,OBJECT) 拦截器中包括基础地址、超时时间、添加请求头标识、添加token utils文件夹下新建http.ts 拦截uploadFile文件上传&#xff0c;rquest请求接口 cosnt baseUrl xxxx// 添加拦截器 const httpInterceptor {//拦截前触发i…

Python逐日填补Excel中的日期并用0值填充缺失日期的数据

本文介绍基于Python语言&#xff0c;读取一个不同的列表示不同的日期的.csv格式文件&#xff0c;将其中缺失的日期数值加以填补&#xff1b;并用0值对这些缺失日期对应的数据加以填充的方法。 首先&#xff0c;我们明确一下本文的需求。现在有一个.csv格式文件&#xff0c;其第…

几种开源协议的区别(Apache、MIT、BSD、MPL、GPL、LGPL)

作为一名软件开发人员&#xff0c;你一定也是经常接触到开源软件&#xff0c;但你真的就了解这些开源软件使用的开源许可协议吗&#xff1f; 你不会真的认为&#xff0c;开源就是完全免费吧&#xff1f;那么让我们通过本文来寻找答案。 一、开源许可协议简述 开源许可协议是指开…

CI/CD工具中的CI和CD的含义

CI/CD工具中的CI和CD的含义&#xff1f; CI/CD 是现代软件开发方法中广泛使用的一种方法。其中&#xff0c;CI 代表持续集成&#xff08;Continuous Integration&#xff09;&#xff0c;CD 则有两层含义&#xff0c;一是持续交付&#xff08;Continuous Delivery&#xff09;…

Linux CentOS7 vim寄存器

计算机中通常所说的寄存器Register一般指的是CPU中的寄存器&#xff0c;用来暂存CPU处理所需要的指令、数据等。 vim中同样也有寄存器&#xff0c;使用的方式和CPU非常类似。 vim中的寄存器(register)作用和windows中的剪切板类似&#xff0c;不过vim中的寄存器不止一个&…

前后端协议后端统一返回格式Result

/*** 后端统一返回结果* param <T>*/ Data public class Result<T> implements Serializable {private Integer code; //编码&#xff1a;1成功&#xff0c;0和其它数字为失败private String msg; //错误信息private T data; //数据public static <T> Result…

STM32芯片为什么有那么多组VDD?

对于一般的IC元器件通常只有两个电源引脚&#xff0c;一个是Vcc或Vdd&#xff0c;和GND或Vss。学习过32单片机的小伙伴肯定都会有这个发现&#xff0c;32单片机有多组VDD&#xff0c;单片机的引脚资源那么珍贵&#xff0c;为什么要在这里浪费那么多引脚呢&#xff1f;还有就是引…

十三、Django之添加用户(原始方法实现)

修改urls.py path("user/add/", views.user_add),添加user_add.html {% extends layout.html %} {% block content %}<div class"container"><div class"panel panel-default"><div class"panel-heading"><h3 c…

c语言练习78:执⾏操作后的变量值

字符串函数汇总 1. strlen &#xff1a;计算字符串的⻓度。 2. strcpy &#xff1a;将⼀个字符串复制到另⼀个字符串中。 3. strcat &#xff1a;将⼀个字符串连接到另⼀个字符串的末尾。 4. strcmp &#xff1a;⽐较两个字符串是否相等。 5. strncmp &#xff1a;⽐较两个…

Electron.js入门-构建第一个聊天应用程序

什么是electron 电子是一个开源框架&#xff0c;用于使用web技术构建跨平台桌面应用程序&#xff1b;即&#xff1a; HTML、CSS和JavaScript&#xff1b;被集成为节点模块&#xff0c;我们可以为我们的应用程序使用节点的所有功能&#xff1b;组件&#xff0c;如数据库、Api休…

口袋参谋:深度解析淘人群画像的两种方法!

​一直以来&#xff0c;有不少人问我&#xff0c;关于流量的问题。如若店铺流量不精准会怎么样&#xff1f;这可想而知&#xff0c;不精准的流量会导致店铺销售下降&#xff0c;店铺宝贝的表现力差了&#xff0c;淘宝自然会缩减你的免费流量。 不少新手卖家在开店初期&#xff…

WebGL 响应上下文丢失解决方案

目录 响应上下文丢失 如何响应上下文丢失 上下文事件 示例程序&#xff08;RotatingTriangle_contextLost.js&#xff09; 响应上下文丢失 WebGL使用了计算机的图形硬件&#xff0c;而这部分资源是被操作系统管理&#xff0c;由包括浏览器在内的多个应用程序共享。在某些特…

BIT-5-操作符详解(C语言初阶学习)

1. 各种操作符的介绍。 2. 表达式求值 1. 操作符分类&#xff1a; 算术操作符 移位操作符 位操作符 赋值操作符 单目操作符 关系操作符 逻辑操作符 条件操作符 逗号表达式 下标引用、函数调用和结构成员 2. 算术操作符 - * / % 除了 % 操作符…

【实战】流动的箭头 —— 线性流动组件(repeating-linear-gradient,@keyFrames)

文章目录 一、引子二、组件思路三、效果图四、源代码src\components\flow-arrow\index.jssrc\components\flow-arrow\keyFrames.jssrc\components\flow-arrow\constant.js组件调用 五、拓展学习1.repeating-linear-gradient2.animation3.keyFrames 组件源码获取&#xff1a;⭐️…