[C++13]:stack queue priority_queue 模拟实现

stack && queue && priority_queue 模拟实现

  • 一.stack
    • 1.概念:
    • 2.使用:
    • 3.模拟实现:
    • 一些题目:
      • 1.最小栈:
      • 2.栈的压入弹出序列:
      • 3.逆波兰表达式求值:
  • 二.queue
    • 1.概念:
    • 2.使用:
    • 3.模拟实现:
    • 一个题目:
      • 1.层序遍历:
      • GIF解析
  • 三.priority_queue
    • 1.概念:
    • 2.一个题目:
      • 思路一:建堆+堆元素删除
      • 思路二:优化
    • 3.模拟实现:
    • 4.仿函数的应用:
      • 1.priority_queue()
      • 2.sort

一.stack

1.概念:

在这里插入图片描述

1.我们从stack的模板参数中看到第一个是stack中元素的类型。
2.第二个参数是一个有缺省值的参数类型,类型是一个deque类型。
3.deque是一个双端队列的一个容器(有list和vector的所有优点)
4.总结:stack其实不是一个容器,它叫做容器适配器,底层是对他使用的一个容器的接口的再封装。
5.底层的容器要满足以下接口:
push_back()
pop_back()
size()
empty()
back()

2.使用:

在这里插入图片描述

void test_1()
{stack<int> s_1;stack<int> s_2;s_1.push(1);s_1.push(2);s_1.push(3);s_1.push(4);s_1.pop();cout << s_1.top() <<endl;//3if (s_1.empty())cout << "当前栈为空!" << endl;//当前栈不为空elsecout << "当前栈不为空!" << endl;s_2 = s_1;s_2.pop();s_1.swap(s_2);while (!s_1.empty()){cout << s_1.top() << " ";s_1.pop();}//2 1cout << endl;while (!s_2.empty()){cout << s_2.top() << " ";s_2.pop();}//3 2 1cout << endl;
}

1.容器适配器是没有迭代器的,容器适配器不是容器,容器才有迭代器。
2.遍历容器适配器的元素有自己对应的方法。
3.没有给模板传第二个参数所以使用默认的双端队列作为底层容器。
4.使用vector作为底层的容器也是可以的!

在这里插入图片描述

3.模拟实现:

1.有了上面的stack基本概念和使用的介绍,我们想要去模拟实现一个stack。
2.有了底层的容器在底层容器的基础之上进行封装是非常方便的。

#include<iostream>
#include<vector>
using namespace std;namespace sfpy {//1.默认使用的vector作为我们的底层容器:template<class T , class Container = vector<T>>class stack {//1.需要提供构造函数?//回答:不需要没有提供构造函数自定义类型回去调用它的默认构造。public:size_t size(){return vessel.size();}bool empty(){return vessel.empty();}void push(T x){vessel.push_back(x);}void pop(){vessel.pop_back();}T top(){return vessel.back();}private:Container vessel;};
}

一些题目:

在这里插入图片描述

最小栈

1.最小栈:

思路一:
1.定义两个栈第一个栈(Stack)用来正常保存数据,第二个栈(StackMin)用来保存较小的数据值。
2.特殊情况:
2-1:马上要push的数据小于等于StackMIn栈顶的值就两个栈都push。
2-1:pop数据需要判断Stack.top()和StackMIn.top()值相等就都pop.
2-1: 不这样处理的话出现连续相同的较小值对于pop来说,如果StackMin只记录较小值一次的话。Stack还有这个数据但是StackMIn中这个值就没有了getmin方法就不对了。

class MinStack {
public:MinStack() {}void push(int val) {Stack.push(val);if(StackMin.empty() )StackMin.push(val);else{int top = StackMin.top();if(val <= top){StackMin.push(val);}} }void pop() {if(Stack.top() == StackMin.top())StackMin.pop();Stack.pop();}int top() {return Stack.top();}int getMin() {return StackMin.top();}stack<int> Stack;stack<int> StackMin;
};

2.栈的压入弹出序列:

请添加图片描述
栈的压入弹出序列

思路一:双指针模拟

在这里插入图片描述

class Solution {
public:/*** 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可*** @param pushV int整型vector* @param popV int整型vector* @return bool布尔型*/bool IsPopOrder(vector<int>& pushV, vector<int>& popV) {int pushi = 0, popi = 0;stack<int> st;while (popi < popV.size()){//2 1 0//1 2 0int tmp = popV[popi];while (pushi < pushV.size()){//1.出栈判断:if (!st.empty() && st.top() == tmp){st.pop();popi++;break;}else{st.push(pushV[pushi++]);continue;}//2.进入数据:st.push(pushV[pushi++]);popi++;}if (!st.empty() && pushi == pushV.size()){while (!st.empty() && st.top() == popV[popi]){st.pop();popi++;}break;}}return st.empty();}
};

3.逆波兰表达式求值:

在这里插入图片描述

逆波兰表达式求值

class Solution {
public:int evalRPN(vector<string>& tokens) {stack<int> s1;for(auto& tmp:tokens){//1.字符栈:if(tmp=="+" || tmp=="-" || tmp=="*" || tmp=="/"){int right = s1.top();s1.pop();int left = s1.top();s1.pop();char ch = tmp[0];switch(ch){case '+':s1.push(left+right);break;case '-':s1.push(left-right);break;case '*':s1.push(left*right);break;case '/':s1.push(left/right);break;}}//2.数值栈:else{s1.push(stoi(tmp));}}return s1.top();}   
};

二.queue

1.概念:

在这里插入图片描述

1.我们从queue的模板参数中看到第一个是queue中元素的类型。
2.第二个参数是一个有缺省值的参数类型,类型是一个deque类型。
3.deque是一个双端队列的一个容器(有list和vector的所有优点)
4.总结:queue其实不是一个容器,它叫做容器适配器,底层是对他使用的一个容器的接口的再封装。
5.底层的容器要满足以下接口:
push_back()
pop_front()
size()
empty()
back()
front()

2.使用:

void test_3()
{queue<int> q_1;//1.入数据并且获取队尾数据:for (int i = 0; i < 6; i++){q_1.push(i);cout << q_1.back() << " ";}//0 1 2 3 4 5cout << endl;cout << "queue size:" << q_1.size() << endl;//queue size 5//2.提取队头数据并且出数据:while (!q_1.empty()){cout << q_1.front() << " ";q_1.pop();}//0 1 2 3 4 5 cout << endl;
}

3.模拟实现:

1.有了上面的stack基本概念和使用的介绍,我们想要去模拟实现一个stack。
2.有了底层的容器在底层容器的基础之上进行封装是非常方便的。

#include<iostream>
#include<list>using namespace std;namespace sfpy {template<class T , class Container = list<T>>class queue {public://1.不需要实现构造函数,自定义类型会去调用自己的默认构造:bool empty(){return vessel.empty();}size_t size(){return vessel.size();}T front(){return vessel.front();}T back(){return vessel.back();}void push(T x){vessel.push_back(x);}void pop(){vessel.pop_front();}private:Container vessel;};
}

在这里插入图片描述

一个题目:

1.层序遍历:

在这里插入图片描述

二叉树的层序遍历

思路一:使用队列模拟每一层数据的遍历:

在这里插入图片描述

class Solution {
public:vector<vector<int>> levelOrder(TreeNode* root) {vector<vector<int>> vv;if(root == nullptr)return vv;queue<TreeNode*> s;s.push(root);int num = s.size();vector<int> tmp;while(!s.empty()){TreeNode* top = s.front();tmp.push_back(top->val);s.pop();num--;if(top->left!=nullptr)s.push(top->left);if(top->right!=nullptr)s.push(top->right);if(num==0){num = s.size();vv.push_back(tmp);tmp.resize(0);}}return vv;}
};

GIF解析

在这里插入图片描述

三.priority_queue

1.概念:

在这里插入图片描述

1,priority_queue是一个容器适配器。
2.priority_queue底层是一个顺序表容器,并且同时使用了堆的算法实现了一个堆的结构。
3.默认情况下priority_queue是一个大堆。

2.一个题目:

在这里插入图片描述

数组中第k大的元素

思路一:建堆+堆元素删除

1.用所有的元素进行建堆。
2.删除k-1个元素当前的堆顶就是第k大的元素。

class Solution {
public:int findKthLargest(vector<int>& nums, int k) {priority_queue<int> heap(nums.begin() , nums.end());while(--k){heap.pop();}return heap.top();}
};

在这里插入图片描述

思路二:优化

1.如果N(nums这个顺序表中的总元素的个数)和k的数值比较接近的话那么时间复杂度度是比较高的。
2.使用topk算法的思路衍生。
3.开始建立k个元素的一个小堆遍历剩下所有数据到小堆中遍历完成后堆顶就是第k大的元素。

class Solution {
public:int findKthLargest(vector<int>& nums, int k) {//1.建立一个小堆:最后一个模板参数换成greater比较方法priority_queue<int,vector<int>,greater<int>> heap(nums.begin() , nums.begin()+k);//2.遍历剩下的数据:for(int i = k ; i<nums.size() ; i++){int n = nums[i];if(heap.top() < n){heap.pop();heap.push(n);}}//3.返回堆顶数据:return heap.top();}
};

在这里插入图片描述

3.模拟实现:

1.priority_queue的底层是一个顺序表。
2.提供了堆的算法实现了一个堆结构。
3.提供两个比较类类中实现对operator()的定义,实现比较函数,提供不同的比较函数,创造不同的堆类型。
4.模板参数提供了一个仿函数的东西,仿函数不是函数是一个模板参数,是一个自定义类型的模板参数,并且类型中重载了operator(),这样在方法中实例化一个对象之后就可以使用通过重载()实现的一个方法。

#include<iostream>
#include<vector>
using namespace std;namespace sfpy {template<class T>class less{public:bool operator()(T x , T b){return x > b;}};template<class T>class greater{public:bool operator()(T x, T b){return x < b;}};template<class T , class Container = vector<T> , class Compare = less<int>>class priority_queue {private:void adjust_up(int n){Compare com;int child = n;int parent = (n - 1) / 2;while (child > 0){if(com(heap[child], heap[parent]))swap(heap[child], heap[parent]);child = parent;parent = (child - 1) / 2;}}void adjust_down(){Compare com;//1.使用假设法:int parent = 0;int child = (parent * 2) + 1;while (child < heap.size()){if (child + 1 < heap.size() && com(heap[child + 1], heap[child]))child++;if (com(heap[child], heap[parent]))swap(heap[child], heap[parent]);elsebreak;parent = child;child = (parent * 2) + 1;}}public://1.pushvoid push(T x){//1.插入数据到顺序表中:heap.push_back(x);//2.走向上调整算法:adjust_up(heap.size() - 1);}//2.popvoid pop(){//1.首位交换:swap(heap[0], heap[heap.size() - 1]);//2.删除尾数据:heap.pop_back();//3.向下调整算法把交换好的值调整到合适的位置。adjust_down();}bool empty() { return heap.empty(); }size_t size() { return heap.size(); }T top() { return heap.front(); }private:Container heap;};
}

4.仿函数的应用:

1.仿函数顾名思义不是一个函数仿照函数实现的一个类。
2.这个类提供一个operator()的成员方法去控制大小比较等内容。
3.对于模板参数来说传递类型。
4.对于函数参数来说传递对象。

1.priority_queue()

template<class T>class less{public:bool operator()(T x , T b){return x > b;}};template<class T>class greater{public:bool operator()(T x, T b){return x < b;}};template<class T , class Container = vector<T> , class Compare = less<int>>class priority_queue {private:void adjust_up(int n){Compare com;int child = n;int parent = (n - 1) / 2;while (child > 0){if(com(heap[child], heap[parent]))swap(heap[child], heap[parent]);child = parent;parent = (child - 1) / 2;}}void adjust_down(){Compare com;//1.使用假设法:int parent = 0;int child = (parent * 2) + 1;while (child < heap.size()){if (child + 1 < heap.size() && com(heap[child + 1], heap[child]))child++;if (com(heap[child], heap[parent]))swap(heap[child], heap[parent]);elsebreak;parent = child;child = (parent * 2) + 1;}}
……………………………………
……………………………………………………

1.通过函数模板参数传递类类型进来,类型有一个默认的类类型实现了堆默认是大堆的一个情况。
2.通过传递模板参数的类型可以实现大小堆的转换。
3.在类中通过实例化一个对象,调用对象方法可以实现不同的比较逻辑。
4.通过不同的比较逻辑实现不同类型的堆。

2.sort

1.这个地方是直接通过函数参数传递一个实参:类对象。
2.在sort函数里面调用类中的operator()方法实现对数据的比较。
3.从而达到一个排升序和降序的效果。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

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

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

相关文章

Vue服务器端渲染(SSR)是不是技术的倒退?

一、什么是服务器端渲染&#xff0c;是不是技术退步&#xff1f; Vue服务器端渲染&#xff08;Vue Server-Side Rendering&#xff0c;简称SSR&#xff09;是一种将Vue组件在服务器端进行渲染&#xff0c;生成最终的HTML页面&#xff0c;然后将其发送给客户端的技术。 传统的V…

VBA快速智能拆分日期

实例需求&#xff1a; A列为待处理数据&#xff0c;日期有多种格式 单个日期&#xff1a;6.16同月简写时间段&#xff1a;7.7-8&#xff0c;其含为7.7-7.8跨月时间段&#xff1a;5.29-6.2 现在需要将A列日期&#xff0c;按照如下规则筛选&#xff0c;并提取开始日期和结束日…

【docker】linux系统docker的安装及使用

一、docker应用的安装 1.1 安装方式 Docker的自动化安装&#xff0c;即使用提供的一键安装的脚本&#xff0c;进行安装。 官方的一键安装方式&#xff1a;curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun 国内 daocloud一键安装命令&#xff1a;curl -s…

springboot133在线课程管理系统

简介 【毕设源码推荐 javaweb 项目】基于springbootvue 的 适用于计算机类毕业设计&#xff0c;课程设计参考与学习用途。仅供学习参考&#xff0c; 不得用于商业或者非法用途&#xff0c;否则&#xff0c;一切后果请用户自负。 看运行截图看 第五章 第四章 获取资料方式 **项…

精品基于Uniapp+ssm学生成绩管理系统App

《[含文档PPT源码等]精品基于Uniappssm学生成绩管理系统App》该项目含有源码、文档、PPT、配套开发软件、软件安装教程、项目发布教程、包运行成功&#xff01; 软件开发环境及开发工具&#xff1a; 开发语言&#xff1a;Java 后台框架&#xff1a;ssm 安卓框架&#xff1a…

C#,最小生成树(MST)普里姆(Prim)算法的源代码

Vojtěch Jarnk 一、Prim算法简史 Prim算法&#xff08;普里姆算法&#xff09;&#xff0c;是1930年捷克数学家算法沃伊捷赫亚尔尼克&#xff08;Vojtěch Jarnk&#xff09;最早设计&#xff1b; 1957年&#xff0c;由美国计算机科学家罗伯特普里姆独立实现&#xff1b; 19…

基础功能认识

文件传输方法 获取桌面文件 回传 3&#xff1a;FTP文件传输协议 进入和退出PYTHON界面 官方自带编译软件 设置中文 接下来安装C环境 安装Wiring库常见问题 终端窗口-------输入gpio -v-----------------输入gpio readall----可能报错&#xff0c;输入 输入gpio readall 可看…

uni-app 微信小程序之红包雨活动

文章目录 1. 页面效果2. 页面样式代码 1. 页面效果 GIF录屏有点卡&#xff0c;实际比较丝滑 每0.5s掉落一个红包控制4s后自动移除红包点击红包消除红包&#xff08;或者自行1&#xff0c;或者弹窗需求&#xff09; 2. 页面样式代码 <!-- 红包雨活动 --> <template>…

总结和考试

总结和考试 1. 代码规范1.1 名称1.2 注释1.3 todo1.4 条件嵌套1.5 简单逻辑先处理1.6 循环1.7 变量和值 2.知识补充2.1 pass2.2 is 比较2.3 位运算 3.阶段总结4.考试题 1. 代码规范 程序员写代码是有规范的&#xff0c;不只是实现功能而已。 1.1 名称 在Python开发过程中会创…

D55XT100-ASEMI整流桥D55XT100参数、封装、规格

编辑&#xff1a;ll D55XT100-ASEMI整流桥D55XT100参数、封装、规格 型号&#xff1a;D55XT100 品牌&#xff1a;ASEMI 正向电流&#xff08;Id&#xff09;&#xff1a;55A 反向耐压&#xff08;VRRM&#xff09;&#xff1a;1000V 正向浪涌电流&#xff1a;550A 正向…

shell脚本之循环语句

一 echo命令 echo -n 表示不换行输出 echo -e 表示输出转义符 常用的转义符&#xff1a;要举例为证 二 date date查看当前系统时间 -d 你描述的日期&#xff0c;显示指定字符串所描述的时间&#xff0c;而非当前时间 %F 完整日期格式&#xff0c;等价于 %Y…

跟着pink老师前端入门教程-day11

3、CSS 三角 网页中常见一些三角形&#xff0c;使用CSS直接画出来即可&#xff0c;不必做成图片或字体图标 4、CSS 用户界面样式 4.1 什么是界面样式 界面样式&#xff1a;更改一些用户操作样式&#xff0c;以便提高更好的用户体验&#xff08;更改用户的鼠标样式、表单轮廓…