【C++】stack/queue/优先级队列的模拟实现

目录

  • 1. stack/queue
    • 1.1 模拟实现
  • 2. 优先级队列
    • 2.1 模拟实现
    • 2.2 仿函数

1. stack/queue

stack文档说明

queue文档说明

stack和queue被称为容器适配器。

容器适配器是什么?
它是一种特殊的容器类型,通过封装已有的容器类型来提供特定功能的接口函数,以满足不同的需求。

而stack和queue底层封装的是deque容器。

deque(双端队列)容器不仅支持头部和尾部数据的插入和删除,也支持随机存取、访问和修改(迭代器),但是每个方面的功能又不是特别突出,尤其是随机存取和中间位置插入删除数据,效率比较低,因此很少单独使用deque,而且将其作为某个容器的适配器。

stack和queue的结构特性都是只能在两端进行数据的操作,无需随机存取和中间位置插入删除,因此用deque来适配就非常合适。

1.1 模拟实现

#include <iostream>
#include <deque>
using namespace std;
namespace lzh {//stack//第二个模板参数默认使用dequetemplate<class T, class Container = deque<T>>class stack {public:void push(const T& x) {_con.push_back(x);}void pop() {_con.pop_back();}T& top() {return _con.back();}const T& top() const {return _con.back();}size_t size()const {return _con.size();}bool empty()const {return _con.empty();}private:Container _con;};//queuetemplate<class T, class Container = deque<T>>class queue {public:void push(const T& x) {_con.push_back(x);}void pop() {_con.pop_front();}T& front() {return _con.front();}T& back() {return _con.back();}const T& front() const {return _con.front();}const T& back()	const {return _con.back();}size_t size()const {return _con.size();}bool empty()const {return _con.empty();}private:Container _con;};
}

2. 优先级队列

priority_queue文档说明

priority_queue是一种特殊的队列,它可以根据元素的优先级(或者大小)自动进行排序,并且优先级最高的先出队

本质是二叉堆结构

在这里插入图片描述
它也是一个容器适配器,底层封装了vector容器,并且元素的优先级是通过第三个模板参数仿函数来控制的

在这里插入图片描述默认是大堆 - less<T>,若想实现小堆则要显式传递三个参数封装的容器类型和仿函数:

在这里插入图片描述

2.1 模拟实现

#pragma once
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
namespace lzh {template<class T, class Container = vector<T>>class priority_queue {void adjustDown(int fatherIdx) {int childIdx = fatherIdx * 2 + 1;while (childIdx < (int)_con.size()) {if (childIdx + 1 < (int)_con.size() && _con[childIdx + 1] > _con[childIdx]) {++childIdx;}if (_con[childIdx] > _con[fatherIdx]) {swap(_con[childIdx], _con[fatherIdx]);fatherIdx = childIdx;childIdx = fatherIdx * 2 + 1;}else {break;}}}void adjustUp(int childIdx) {int fatherIdx = (childIdx - 1) / 2;while (childIdx > 0 && _con[childIdx] > _con[fatherIdx]) {swap(_con[childIdx], _con[fatherIdx]);childIdx = fatherIdx;fatherIdx = (childIdx - 1) / 2;}}public:priority_queue() { }template <class InputIterator>priority_queue(InputIterator first, InputIterator last) {while (first != last) {_con.push_back(*first);++first;}for (int i = (_con.size() - 2) / 2; i >= 0; --i) {adjustDown(i);}}bool empty() const {return _con.empty();}size_t size() const {return _con.size();}// 堆顶元素不允许修改,因为:堆顶元素修改可以会破坏堆的特性const T& top() const {return _con.front();}void push(const T& x) {_con.push_back(x);adjustUp(_con.size() - 1);}void pop() {swap(_con.front(), _con.back());_con.pop_back();adjustDown(0);}private:Container _con;};
}

2.2 仿函数

默认实现的是大堆,因为比较那里写死了,若要实现小堆结构则需要修改向下和向上调整算法的比较逻辑,但实际上库里实现的优先级队列是没办法修改的,所以真正的做法是使用仿函数作为第三个模板参数传递给容器,来实现大小堆的切换。

仿函数本质是一个类类型,类中重载了()运算符:

//仿函数且类模板
template<class T>
class Less {
public://若为自定义类型则该类中实现了小于运算符重载bool operator()(const T& x, const T& y) {return x < y;}
};void test_less() {//函数对象Less lessFunc;cout << lessFunc(1, 2) << endl;//显式调用//cout << lessFunc.operator()(1, 2) << endl;
}

可以发现该对象可以像函数一样来使用。

类似于C语言中的函数指针

用仿函数来灵活调整调整算法的逻辑,控制是大堆还是小堆:

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;}
};namespace lzh {template<class T, class Container = vector<T>, class Compare = less<T>>class priority_queue {void adjustDown(int fatherIdx) {//定义仿函数对象Compare cmp;int childIdx = fatherIdx * 2 + 1;while (childIdx < (int)_con.size()) {//通过函数对象进行比较if (childIdx + 1 < (int)_con.size() &&cmp(_con[childIdx], _con[childIdx + 1])) {++childIdx;}//通过函数对象进行比较if (cmp(_con[fatherIdx], _con[childIdx])) {swap(_con[fatherIdx], _con[childIdx]);fatherIdx = childIdx;childIdx = fatherIdx * 2 + 1;}else {break;}}}void adjustUp(int childIdx) {//定义仿函数对象Compare cmp;int fatherIdx = (childIdx - 1) / 2;while (childIdx > 0 && cmp(_con[fatherIdx], _con[childIdx])) {swap(_con[fatherIdx], _con[childIdx]);childIdx = fatherIdx;fatherIdx = (childIdx - 1) / 2;}}//...其他成员}
}
int main() {//第三个模板参数//Less默认是建大堆//而Greater是建小堆//和库里的实现一致//第二和第三个模板参数有缺省值//若要大堆,可以只传第一个元素类型//而要小堆则三个都需要传递lzh::priority_queue<int, vector<int>, Less<int>> pq;pq.push(3);pq.push(5);pq.push(1);pq.push(4);while (!pq.empty()) {cout << pq.top() << ' ';pq.pop();}cout << endl;return 0;
}

通过传递不同的仿函数类型,便可以控制是建大堆还是小堆。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用Nginx调用网关,然后网关调用其他微服务

问题前提&#xff1a;目前我的项目是已经搭建了网关根据访问路径路由到微服务&#xff0c;然后现在我使用了Nginx将静态资源都放在了Nginx中&#xff0c;然后我后端定义了一个接口访问一个html页面&#xff0c;但是html页面要用到静态资源&#xff0c;这个静态资源在我的后端是…

关于es中索引,倒排索引的理解

下面是我查询进行理解的东西 也就是说我们ES中的索引就相当于我们mysql中的数据库表&#xff0c;索引库就相当于我们的数据库&#xff0c;我们按照mapping规则会根据相应的字段&#xff08;index为true默认&#xff09;来创建倒排索引&#xff0c;这个倒排索引就相当于我们索引…

QT-Mysql数据库图形化接口

QT sql mysqloper.h qsqlrelationaltablemodelview.h /************************************************************************* 接口描述&#xff1a;Mysql数据库图形化接口 拟制&#xff1a; 接口版本&#xff1a;V1.0 时间&#xff1a;20230727 说明&#xff1a;支…

【ARM Linux 系统稳定性分析入门及渐进12 -- GDB内存查看命令 “x“(examine)】

文章目录 gdb 内存查看命令 examine 上篇文章&#xff1a;ARM Linux 系统稳定性分析入门及渐进11 – GDB( print 和 p 的使用| 和 &#xff1a;&#xff1a;的使用|ptype|{&#xff1c;type&#xff1e;} &#xff1c;addr&#xff1e; ) gdb 内存查看命令 examine examine是…

【数据结构】如何用队列实现栈?图文详解(LeetCode)

LeetCode链接&#xff1a;225. 用队列实现栈 - 力扣&#xff08;LeetCode&#xff09; 本文默认读者已经掌握栈与队列的基本知识 或者先看我的另一篇博客&#xff1a;【数据结构】栈与队列_字节连结的博客-CSDN博客 做题思路 由于我们使用的是C语言&#xff0c;不能直接使用队…

​Kubernetes的演变:从etcd到分布式SQL的过渡

DevRel领域专家Denis Magda表示&#xff0c;他偶然发现了一篇解释如何用PostgreSQL无缝替换etcd的文章。该文章指出&#xff0c;Kine项目作为外部etcd端点&#xff0c;可以将Kubernetes etcd请求转换为底层关系数据库的SQL查询。 受到这种方法的启发&#xff0c;Magda决定进一步…

react-native-webview RN和html双向通信

rn登录后得到的token需要传递给网页&#xff0c;js获取到的浏览器信息需要传递给rn RN Index.js: import React from react import { WebView } from react-native-webview import useList from ./useListexport default function Index(props) {const { uri, jsCode, webVie…

【MySQL系列】--初识数据库

&#x1f490; &#x1f338; &#x1f337; &#x1f340; &#x1f339; &#x1f33b; &#x1f33a; &#x1f341; &#x1f343; &#x1f342; &#x1f33f; &#x1f344;&#x1f35d; &#x1f35b; &#x1f364; &#x1f4c3;个人主页 &#xff1a;阿然成长日记 …

在ubuntu中将dict.txt导入到数据库sqlite3

将dict.txt导入到数据库 #include <head.h> #include <sqlite3.h> int do_insert(int i,char *str,sqlite3 *db); int main(int argc, const char *argv[]) {//创建泵打开一个数据库sqlite3 *db NULL;if(sqlite3_open("./my.db",&db) ! SQLITE_OK){…

使用IDM下载视频出现“由于法律原因,IDM无法下载...

一、问题描述 由于法律原因,IDM无法下载..,如图: 二、原因分析 下载该IDM抓取的M3U8文件,查看其中的内容发现 : #EXT-X-KEY 字段已经写明了加密方式是AES-128,包含一个URI和IV值 #EXTM3U #EXT-X-VERSION:3 #EXT-X-TARGETDURATION:8 #EXT-X-MEDIA-SEQUENCE:0 #EXT-X-KEY:…

Cpp学习——list的模拟实现

目录 一&#xff0c;实现list所需要包含的三个类 二&#xff0c;三个类的实现 1.list_node 2.list类 3.iterator_list类 三&#xff0c;功能实现 1.list类里的push_back() 2.iterator类里的运算符重载 3&#xff0c;list类里面的功能函数 1.insert&#xff08;&#xff…

2023国赛数学建模思路 - 案例:FPTree-频繁模式树算法

文章目录 算法介绍FP树表示法构建FP树实现代码 建模资料 ## 赛题思路 &#xff08;赛题出来以后第一时间在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 算法介绍 FP-Tree算法全称是FrequentPattern Tree算法&#xff0c;就是频繁模式树算法&#xff0c…

Linux常用命令——dig命令

在线Linux命令查询工具 dig 域名查询工具 补充说明 dig命令是常用的域名查询工具&#xff0c;可以用来测试域名系统工作是否正常。 语法 dig(选项)(参数)选项 <服务器地址>&#xff1a;指定进行域名解析的域名服务器&#xff1b; -b<ip地址>&#xff1a;当主…

Log4net在.Net Winform项目中的使用

引言&#xff1a; Log4net是一个流行的日志记录工具&#xff0c;可以帮助开发人员在应用程序中实现高效的日志记录。本文将提供一个详细的分步骤示例&#xff0c;来帮助您在.Net Winform项目中使用Log4net。 目录 一、安装Log4net二、配置Log4net三、在项目中使用Log4net四、初…

深入探索:Kali Linux 网络安全之旅

目录 前言 访问官方网站 导航到下载页面 启动后界面操作 前言 "Kali" 可能指的是 Kali Linux&#xff0c;它是一种基于 Debian 的 Linux 发行版&#xff0c;专门用于渗透测试、网络安全评估、数字取证和相关的安全任务。Kali Linux 旨在提供一系列用于测试网络和…

uniapp的uview-plus组件库的导入

uniapp的vue3中使用uview-plus组件库。在插件市场中找到该组件并点击如下所示绿色按钮&#xff0c;弹出弹窗选择要导入的项目后&#xff0c;就会在uni_modules文件中生成如下文件内容 关于插件的下载区别&#xff0c;可参考&#xff1a;https://uniapp.dcloud.net.cn/compone…

回归预测 | MATLAB实现SSA-SVM麻雀搜索算法优化支持向量机多输入单输出回归预测(多指标,多图)

回归预测 | MATLAB实现SSA-SVM麻雀搜索算法优化支持向量机多输入单输出回归预测&#xff08;多指标&#xff0c;多图&#xff09; 目录 回归预测 | MATLAB实现SSA-SVM麻雀搜索算法优化支持向量机多输入单输出回归预测&#xff08;多指标&#xff0c;多图&#xff09;效果一览基…

(三)行为型模式:3、解释器模式(Interpreter Pattern)(C++示例)

目录 1、解释器模式&#xff08;Interpreter Pattern&#xff09;含义 2、解释器模式的UML图学习 3、解释器模式的应用场景 4、解释器模式的优缺点 5、C实现解释器模式的实例 1、解释器模式&#xff08;Interpreter Pattern&#xff09;含义 解释器模式&#xff08;Interp…

《TCP IP网络编程》第二十四章

第 24 章 制作 HTTP 服务器端 24.1 HTTP 概要 本章将编写 HTTP&#xff08;HyperText Transfer Protocol&#xff0c;超文本传输协议&#xff09;服务器端&#xff0c;即 Web 服务器端。 理解 Web 服务器端&#xff1a; web服务器端就是要基于 HTTP 协议&#xff0c;将网页对…