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

目录

一、容器适配器

(一)什么是适配器

(二)stack和queue的底层结构

二、Stack

三、queue

四、deque双端队列

(一)优点

(二)缺陷

五、优先级队列

(一)介绍

(二)仿函数

(三)模拟实现一

(四)模拟实现(带compare)


一、容器适配器

(一)什么是适配器

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

(二)stack和queue的底层结构

  • stack和queue没有迭代器

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

二、Stack

  • 模拟实现stack,stack是先进后出
cpp 复制代码
#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是先进先出
cpp 复制代码
#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的迭代器要频繁的去检测其是否移动到
    某段小空间的边界,导致效率低下

五、优先级队列

(一)介绍

cpp 复制代码
priority_queue<int> first;//建立大根堆
priority_queue<int> first(data.begin(), data.end());//建立大根堆
priority_queue<int, vector<int>, greater<int>> second;//建立小根堆
cpp 复制代码
#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;
}
cpp 复制代码
#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;
}
cpp 复制代码
#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;
}

(二)仿函数

cpp 复制代码
#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;
}

(三)模拟实现一

cpp 复制代码
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;
	};

}
cpp 复制代码
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)

cpp 复制代码
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;
	};

}
cpp 复制代码
#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;

}
相关推荐
我命由我123452 小时前
Python Flask 开发 - Flask 快速上手(Flask 最简单的案例、Flask 处理跨域、Flask 基础接口)
服务器·开发语言·后端·python·学习·flask·学习方法
大飞记Python2 小时前
从零配置Python测试环境:详解路径、依赖与虚拟环境最佳实践
开发语言·python·环境配置·安装目录
zhougl9963 小时前
区分__proto__和prototype
开发语言·javascript·原型模式
weixin_420947643 小时前
php composer update 指定包的分支非tag
开发语言·php·composer
一水鉴天3 小时前
整体设计 定稿 之6 完整设计文档讨论及定稿 之4 整体设计数据库设计规范(含两个版本)
开发语言·人工智能·架构
XFF不秃头3 小时前
【力扣刷题笔记-在排序数组中查找元素的第一个和最后一个位置】
c++·笔记·算法·leetcode
Evand J3 小时前
【EKF定位滤波例程】三维空间(XYZ)速度与位置观测与滤波(使用扩展卡尔曼滤波EKF),状态量和观测量都是非线性的。附MATLAB例程下载链接
开发语言·matlab
AM越.3 小时前
Java设计模式超详解--观察者设计模式
java·开发语言·设计模式
云上漫步者3 小时前
深度实战:Rust交叉编译适配OpenHarmony PC——sys_locale完整适配案例
开发语言·后端·rust
guygg883 小时前
基于MATLAB的精密星历内插实现方案
开发语言·matlab