栈和队列模拟实现(C++)

news2024/11/15 8:25:08

文章目录

  • 1.deque的认识
    • 1.1介绍
    • 2.图析
  • 2.stack模拟实现
  • 3.queue模拟实现
  • 4.优先级队列模拟实现
  • 4.1介绍
    • 4.2例题
    • 4.3模拟实现
  • 5.测试函数

1.deque的认识

1.1介绍

双端队列
Deque(通常读作“deck”)是double-ended queue的不规则首字母缩写。双端队列是动态长度的序列容器,可以在两端(前端或后端)伸缩。
特定的库可能以不同的方式实现deque,通常是某种形式的动态数组。但在任何情况下,它们都允许通过随机访问迭代器直接访问各个元素,存储空间通过根据需要扩展和收缩容器来自动处理。
因此,它们提供了类似于向量的功能,但可以高效地在序列的开头和末尾插入和删除元素。但是,与向量不同的是,deque不能保证将其所有元素存储在连续的存储位置上:通过偏移指向另一个元素的指针来访问deque中的元素会导致未定义的行为。
vector和deque提供了非常相似的接口,也可以用于类似的目的,但两者的内部工作方式却完全不同:vector使用单一数组,需要偶尔重新分配空间以适应增长,而deque中的元素可能分散在不同的存储块中,容器在内部保存了必要的信息,以便以常量时间和统一的顺序接口(通过迭代器)直接访问其中的任何元素。因此,deque的内部结构比vector稍微复杂一些,但这使得它们在某些情况下可以更高效地增长,特别是在序列很长时,重分配的开销会变得更大。
对于频繁地在非起始或结束位置插入或删除元素的操作,deque的性能更差,迭代器和引用的一致性也不如列表和前向列表。

Double ended queue
deque (usually pronounced like "deck") is an irregular acronym of double-ended queue.  Double-ended queues are sequence containers with dynamic sizes that can be expanded or contracted on both ends (either its front or its back).

Specific libraries may implement deques in different ways, generally as some form of dynamic array.  But in any case, they allow for the individual elements to be accessed directly through random access iterators, with storage handled automatically by expanding and contracting the container as needed.

Therefore, they provide a functionality similar to vectors, but with efficient insertion and deletion of elements also at the beginning of the sequence, and not only at its end.  But, unlike vectors, deques are not guaranteed to store all its elements in contiguous storage locations: accessing elements in a deque by offsetting a pointer to another element causes undefined behavior.

Both vectors and deques provide a very similar interface and can be used for similar purposes, but internally both work in quite different ways: While vectors use a single array that needs to be occasionally reallocated for growth, the elements of a deque can be scattered in different chunks of storage, with the container keeping the necessary information internally to provide direct access to any of its elements in constant time and with a uniform sequential interface (through iterators).  Therefore, deques are a little more complex internally than vectors, but this allows them to grow more efficiently under certain circumstances, especially with very long sequences, where reallocations become more expensive.

For operations that involve frequent insertion or removals of elements at positions other than the beginning or the end, deques perform worse and have less consistent iterators and references than lists and forward lists.

2.图析

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

2.stack模拟实现

#pragma once
#include <iostream>
#include <assert.h>
#include <deque>
using namespace std;

namespace apex
{                                // Double-ended queue  双端队列
	template<class T, class Container = deque<T>>
	class stack
	{
	public:
		
		//压栈 -- 栈顶入数据 -- 尾插
		void push(const T& x)
		{
			_con.push_back(x);
		}

		//出栈 -- 栈顶出数据 -- 尾插
		void pop()
		{
			_con.pop_back();
		}

		//取栈顶 -- 数据的尾部 -- back()函数
		T& top()
		{
			return _con.back();
		}
		const T& top() const
		{
			return _con.back();
		}

		//判空 -- 对象的empty函数
		bool empty()  const
		{
			return _con.empty();
		}

		//栈大小 -- size函数
		size_t size() const
		{
			return _con.size();
		}

	private:
		Container _con; 
	};
}

3.queue模拟实现

#pragma once
#include <deque>

namespace apex
{
	template<class T, class Container = deque<T>>
	class queue
	{
	public:
		//入队列 -- 尾插
		void push(const T& x)
		{
			_con.push_back(x);
		}
		
		//出队列 --  头删
		void pop()
		{
			_con.pop_front();
		}

		//取队尾 -- back函数
		T& back()
		{
			return _con.back();
		}
		const T& back() const
		{
			return _con.back();
		}

		//取队头 -- front函数
		T& front()
		{
			return _con.front();
		}
		const T& front() const
		{
			return _con.front();
		}

	    //判空 -- empty函数
		bool empty()  const
		{
			return _con.empty();
		}

		//队列大小 -- size函数
		size_t size() const
		{
			return _con.size();
		}

	private:

		Container _con;
	};
}

4.优先级队列模拟实现

4.1介绍

优先队列
优先级队列是一种容器适配器,根据某种严格的弱排序标准,特别设计为它的第一个元素总是它所包含的元素中的最大元素。
这个上下文类似于堆(heap),在堆中可以随时插入元素,但只能取得堆中最大的元素(优先队列中最上面的那个)。
优先队列是作为容器适配器实现的,容器适配器是使用特定容器类的封装对象作为其底层容器的类,提供一组特定的成员函数来访问其元素。元素从特定容器的“后面”弹出,也就是优先队列的顶部。
底层容器可以是任何标准容器类模板,也可以是其他专门设计的容器类。该容器应可通过随机访问迭代器访问
标准容器类vector和deque可以满足这些需求。默认情况下,如果没有为特定的priority_queue类实例化指定容器类,则使用标准容器向量。
支持随机访问迭代器需要始终在内部保持堆结构。这是由容器适配器自动完成的,在需要时自动调用算法函数make_heap、push_heap和pop_heap。

Priority queue
Priority queues are a type of container adaptors, specifically designed such that its first element is always the greatest of the elements it contains, according to some strict weak ordering criterion.

This context is similar to a heap, where elements can be inserted at any moment, and only the max heap element can be retrieved (the one at the top in the priority queue).

Priority queues are implemented as container adaptors, which are classes that use an encapsulated object of a specific container class as its underlying container, providing a specific set of member functions to access its elements.  Elements are popped from the "back" of the specific container, which is known as the top of the priority queue.

The underlying container may be any of the standard container class templates or some other specifically designed container class.  The container shall be accessible through random access iterators and support the following operations:
empty()
size()
front()
push_back()
pop_back()

The standard container classes vector and deque fulfill these requirements.  By default, if no container class is specified for a particular priority_queue class instantiation, the standard container vector is used.

Support of random access iterators is required to keep a heap structure internally at all times.  This is done automatically by the container adaptor by automatically calling the algorithm functions make_heap, push_heap and pop_heap when needed.

4.2例题

在这里插入图片描述

class solution
{
public:
	int findKthLargest(vector<int>& nums, int k)
	{
	//创建堆 -- O(N)
		priority_queue<int> maxHeap(nums.begin(), nums.end());
	//pop k-1 个数据 -- O(k * logN)
		while (--k)
			maxHeap.pop();
		return maxHeap.top();
	}
};

4.3模拟实现

5.测试函数

#include <iostream>
#include <stack>
#include <queue>
#include <vector>
#include <list>
#include <algorithm>
#include <functional>
#include <time.h>
using namespace std;
 
#include "Stack.h"
#include "Queue.h"
#include "PriorityQueue.h"

//栈的测试
void test_stack()
{
	stack<int> st;
	//stack<int, vector<int>> st;
	//stack<int, list<int>> st;

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

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

//队列的测试
void test_queue()
{
	queue<int> q;
	//queue<int, list<int>> q;
    //queue<int, vector<int>> q;

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

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


void test_priority_queue()
{
	// 默认大的优先级高
	priority_queue<int> pq;
	pq.push(1);
	pq.push(2);
	pq.push(3);
	pq.push(4);
	pq.push(5);
	pq.push(0);

	while (!pq.empty())
	{
		cout << pq.top() << " ";
		pq.pop();
	}
	cout << endl;
	//5 4 3 2 1 0

	int a[] = { 1,2,3,4,5,0 };
	priority_queue<int> i_pq1(a, a + sizeof(a) / sizeof(int));//迭代器区间构造

	//优先级队列原型
	//template <class T, class Container = vector<T>, class Compare = less<typename Container::value_type> > 
	priority_queue<int, vector<int>, greater<int>> i_pq2(a, a + sizeof(a) / sizeof(int));

	while (!i_pq2.empty())
	{
		cout << i_pq2.top() << " ";
		i_pq2.pop();
	}
	cout << endl;
	//0 1 2 3 4 5
}

//vector比deque快大约2倍
void test_op()
{
	srand(time(0));
	const int N = 100000;

	vector<int> v;
	v.reserve(N);

	deque<int> dp;

	for (int i = 0; i < N; ++i)
	{
		auto e = rand();
		v.push_back(e);
		dp.push_back(e);
	}

    int begin1 = clock();
	sort(v.begin(), v.end());
	int end1 = clock();

	int begin2 = clock();
	sort(dp.begin(), dp.end());
	int end2 = clock();

	printf("vector sort:%d\n", end1 - begin1);
	printf("deque sort:%d\n", end2 - begin2);
}

int main()
{
	test_priority_queue();

	return 0;
}

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

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

相关文章

MySQL多表查询(联合查询、连接查询、子查询)

目录 多表联合查询 联合查询类型 多表连接查询 多表查询的分类 交叉查询&#xff08;笛卡尔积&#xff09; 内连接查询 外连接查询 自连接查询 子查询规则 子查询的分类 子查询的不同结果 EXISTS和NOT EXISTS 子查询应用的不同位置 不同外部语句的子查询应用情况…

spring boot--自动化注入组件原理、内嵌tomcat-1

前言 我们知道开发spring boot项目&#xff0c;在启动类上添加注解SpringBootApplication &#xff0c;然后引入要自动注入的组件依赖&#xff0c;然后现application.properties中加上相应配置就可以自动注入这个组件&#xff0c;那么下面看看自动注入组件是如何实现的 一、S…

Idea 结合docker-compose 发布项目

Idea 结合docker-compose 发布项目 这里写目录标题 Idea 结合docker-compose 发布项目Docker 开启远程访问功能 添加相应端口配置IDEA 链接Docker配置项目 docker-compose.yml本地还需要安装 dockerwin11 安装本地Docker 可能存在问题 Linux内核不是最新 Docker 开启远程访问功…

回文链表——力扣234

文章目录 题目描述法一 将值复制到数组中后用双指针法法二 快慢指针 题目描述 法一 将值复制到数组中后用双指针法 class Solution { public:bool isPalindrome(ListNode* head) {vector<int> v;while(head!NULL){v.emplace_back(head->val);head head->next;}for…

同步、异步、阻塞、非阻塞

一、概念 同步与异步&#xff08;线程间调用&#xff09;的区别&#xff1a;关注的是调用方与被调用方之间的交互方式。同步调用会等待被调用方的结果返回&#xff0c;而异步调用则不会等待结果立即返回&#xff0c;可以通过回调或其他方式获取结果。 阻塞非阻塞&#xff08;…

Nautilus Chain 即将治理通证 NAUT ,生态发展进程加速

独特且优势明显的Nautilus Chain 目前&#xff0c;行业内首个模块化底层Nautilus Chain已经上线主网&#xff0c;并且即将有超过70个应用原生部署在Nautilus Chain上。Nautilus Chain本身是一个以Layer3为定位的区块链系统&#xff0c;其通过Celestia模块化底层来获得DA支持以…

网络安全 HVV蓝队实战之溯源

一、前言 对于攻防演练蓝军的伙伴们来说&#xff0c;最难的技术难题可能就是溯源&#xff0c;尤其在今天代理横行的时代更加难以去溯源攻击者。这里我就举两个溯源来帮助大家梳理溯源过程&#xff0c;一个是只溯源到公司&#xff0c;一个是溯源到个人。 二、溯源实例 2.1IP …

逻辑运算符和短路求值

要了解短路求值就必须先了解什么是逻辑运算符。 逻辑运算符 在了解运算符之前我们必须先知道再JAVA中逻辑运算符的结果是Boolean类型的值 逻辑与“&&” 表达式1 && 表达式2 逻辑与就是只有运算符两边的表达式都为真&#xff0c;结果才为真。 表达式1表达式…

2023潮玩盲盒小程序盲盒商城源码(开源+微信登录+支付对接)

潮玩盲盒星尘潮玩盲盒小程序2023潮玩盲盒小程序盲盒商城源码(开源微信登录支付对接)

209. 长度最小的子数组 中等 1.8K

209. 长度最小的子数组 原题链接&#xff1a;完成情况&#xff1a;解题思路&#xff1a;参考代码&#xff1a; 原题链接&#xff1a; 209. 长度最小的子数组 https://leetcode.cn/problems/minimum-size-subarray-sum/description/ 完成情况&#xff1a; 解题思路&#xff1…

单表操作、查询

十四、单表的增删改查&#xff08;DML语句&#xff09; CRUD&#xff08;增删改查&#xff09; 为空要用is null is not null &#xff0c;不能写null <>为等于&#xff0c;也可以为is <>不等于 十五、单表复杂查询 select语句及关系运算符 除了数字&#x…

ROS学习篇之传感器(三)激光雷达

文章目录 一.确定雷达的型号二.安装驱动1.新建一个工作空间"lidar_ws"&#xff08;随便一个你存放代码的地方&#xff09;2.clone下驱动的源代码&#xff08;在lidar_ws/src目录下&#xff09;3.尝试编译一下&#xff08;在lidar_ws目录下&#xff09; 四.在RVIZ中的…

redis的四种模式优缺点

redis简介 Redis是一个完全开源的内存数据结构存储工具&#xff0c;它支持多种数据结构&#xff0c;以及多种功能。Redis还提供了持久化功能&#xff0c;可以将数据存储到磁盘上&#xff0c;以便在重启后恢复数据。由于其高性能、可靠性和灵活性&#xff0c;Redis被广泛应用于…

JavaSwing+MySQL的医药销售管理系统

点击以下链接获取源码&#xff1a; https://download.csdn.net/download/qq_64505944/88108217?spm1001.2014.3001.5503 JDK1.8 MySQL5.7 功能&#xff1a;用户管理&#xff0c;药品库存管理&#xff0c;进销管理&#xff0c;营销管理

产品解读|有了JMeter,为什么还需要MeterSphere?

提起JMeter&#xff0c;相信大部分的测试人员应该都很熟悉。JMeter因其小巧轻量、开源&#xff0c;加上支持多种协议的接口和性能测试&#xff0c;在测试领域拥有广泛的用户群体。一方面&#xff0c;测试人员会将其安装在个人的PC上&#xff0c;用以满足日常测试工作的需要&…

【Claude2体验】继ChatGPT,文心一言,Bing等大模型后,初次对话Claude2的体验

文章目录 &#x1f33a;注意事项&#x1f916;什么是Claude2⭐与之前版本的进步&#x1f6f8;官网的讲解&#x1f354;功能介绍&#x1f384;使用体验&#x1f386;查看不知道如何才能打开的文档 的内容&#x1f386;日常需求✨Claude✨ChatGPT3.5 &#x1f916;总结 &#x1f…

CC1310F128系列 超低功耗低于1GHz射频 微控制器芯片

CC1310F128 是一款经济高效型超低功耗低于1GHz射频器件&#xff0c;凭借极低的有源射频和MCU电流消耗以及灵活的低功耗模式&#xff0c;CC1310F128可确保卓越的电池寿命&#xff0c;并能够在小型纽扣电池供电的情况下以及在能量采集应用中实现远距离工作。 改芯片有三个后缀&am…

redis-cluster 创建及监控

集群命令 cluster info&#xff1a;打印集群的信息。 cluster nodes&#xff1a;列出集群当前已知的所有节点&#xff08;node&#xff09;的相关信息。 cluster meet <ip> <port>&#xff1a;将ip和port所指定的节点添加到集群当中。 cluster addslots <slot…

小程序商城免费搭建之java商城 java电子商务Spring Cloud+Spring Boot+mybatis+MQ+VR全景+b2b2c

1. 涉及平台 平台管理、商家端&#xff08;PC端、手机端&#xff09;、买家平台&#xff08;H5/公众号、小程序、APP端&#xff08;IOS/Android&#xff09;、微服务平台&#xff08;业务服务&#xff09; 2. 核心架构 Spring Cloud、Spring Boot、Mybatis、Redis 3. 前端框架…

libhv之hloop_process_ios源码分析

上一篇文章对hloop源码大概逻辑和思想进行了一个简单的分析&#xff0c;其中主要涉及三类&#xff08;timer>io>idles&#xff09;事件处理。下面将对hloop_process_ios事件做一下简单的分析。 int hloop_process_ios(hloop_t* loop, int timeout) {// That is to call …