当前位置: 首页 > news >正文

15、stack、queue、deque的模拟实现

一、stack

1、stack的使用

请看这篇文章

2、stack的原理

在这里插入图片描述
这篇文章的栈原理讲的不错,并且有链式栈和顺序栈的创建,还有栈常使用的场景,没有数据结构基础的可以看,并且实现一下他的2种栈。

3、stack的实现

3.1、成员变量

  • 这里使用的deque<typename>类型的底层容器来实现栈。
template <class T,class container = deque<T>>private://定义一个deque<T>data容器container data;

3.2、压栈

  • 向栈放入元素
//压入栈顶void push(const T&value){data.push_back(value);}

3.3、弹栈

  • 从栈中,拿出栈顶元素
//弹出栈顶void pop(){if (!empty()) {data.pop_back();} else {throw std::runtime_error("Stack is empty.");}}

3.4、获取栈顶元素

  • top只能获取栈顶元素值
    T& top(){if (!empty()) {return data.back();} else {throw std::runtime_error("Stack is empty.");}}

3.5、判断是否为空

  • 如果为空就是true,否则为false
//判断是否为空bool empty() const {return data.empty();}

3.6、大小

  • 直接返回size
    //返回大小size_t size() const {return data.size();}

3.7、完整过程

#include<stdexcept>
#include<iostream>
#include<sstream>
#include<list>
#include<deque>
#include<vector>
using namespace std;
template <class T,class container = deque<T>>
//deque 作为底层容器
class Stack{
public://压入栈顶void push(const T&value){data.push_back(value);}//弹出栈顶void pop(){if (!empty()) {data.pop_back();} else {throw std::runtime_error("Stack is empty.");}}//获取栈顶T& top(){if (!empty()) {return data.back();} else {throw std::runtime_error("Stack is empty.");}}//判断是否为空bool empty() const {return data.empty();}//返回大小size_t size() const {return data.size();}
private://定义一个deque<T>data容器container data;
};

二、queue

1、queue的使用

queue的使用,看这个文章。

2、queue的原理

queu的原理,推荐看这篇文章,讲的很详细

3、queue的实现

  • 这里使用的deque<typename>类型的底层容器来实现单向队列。

3.1、出队

  • 出队就是从队头删除元素
  void pop() {if (!empty()) {data.pop_front();} else {throw runtime_error("Queue is empty.");}}

3.2、入队

  • 从队尾插入元素
void push(const T &value) { data.push_back(value); }

3.3、大小

  • 返回数据数量
  size_t size() { return data.size(); }

3.4、判断为空

  • data数组为空就是true
  • 反之,为 false
  bool empty() { return data.empty(); }

3.5、访问队头

  • 先判断是否为空,为空就不能访问了。
  • runtime_error是运行时错误。
  • 返回队头的元素
  T &front() {if (!empty()) {return data.front();} else {throw runtime_error("Queue is empty.");}}

3.6、访问队尾

  • 先判断是否为空,为空就不能访问了。
  • runtime_error是运行时错误。
  • 返回队尾的元素
  T &back() {if (!empty()) {return data.back();} else {throw runtime_error("Queue is empty.");}}

3.7、完整过程

#include <deque>
#include <iostream>
#include <sstream>
#include <stdexcept>
#include <string>
using namespace std;
template <class T, typename container = deque<T>> 
class queue {
public:void push(const T &value) { data.push_back(value); }void pop() {if (!empty()) {data.pop_front();} else {throw runtime_error("Queue is empty.");}}T &front() {if (!empty()) {return data.front();} else {throw runtime_error("Queue is empty.");}}T &back() {if (!empty()) {return data.back();} else {throw runtime_error("Queue is empty.");}}bool empty() { return data.empty(); }size_t size() { return data.size(); }private:container data; 
};
int main(int argc, char *argv[]) {queue<int, deque<int>> queue;int N;cin >> N;getchar();string line;for (int i = 0; i < N; i++) {std::getline(std::cin, line);std::istringstream iss(line);std::string command;iss >> command;int element;if (command == "push") {iss >> element;queue.push(element);}if (command == "pop") {try {queue.pop();} catch (const std::runtime_error &e) {// 涓嶅仛浠讳綍澶勭悊continue;}}if (command == "front") {try {std::cout << queue.front() << std::endl;} catch (const std::runtime_error &e) {std::cout << "null" << std::endl;}}if (command == "back") {try {std::cout << queue.back() << std::endl;} catch (const std::runtime_error &e) {std::cout << "null" << std::endl;}}if (command == "size") {std::cout << queue.size() << std::endl;}if (command == "empty") {std::cout << (queue.empty() ? "true" : "false") << std::endl;}}return 0;
}

三、deque

1、deque的使用

deque的使用看这篇文章。

2、deque的原理

deque的原理看这篇文章

3、deque的实现

3.1、成员变量

  • 这里需要的成员
    • capacity:容器容量
    • backIndex:指向尾的索引指针
    • frontIndex:指向头的索引指针
    • size:数据的数量
	T* elements;size_t capacity;size_t frontIndex;size_t backIndex;size_t size;

在这里插入图片描述

3.2、入队

  • 先移动到前一个位置
  • 再存值
3.2.1、头部
//在deque的前端插入元素void push_front(const T&value){if(size==capacity){resize();}//计算新的前端位置插入元素frontIndex = (frontIndex-1+capacity)%capacity;//在新的前端位置插入元素 elements[frontIndex] = value;//增加size++size; } 
3.2.2、尾部
  • 先在当前位置存值
  • 再移动到下一个位置
//在尾部插入元素 void push_back(const T&value){if(size==capacity){resize();}elements[backIndex]=value;//计算新的后端索引 backIndex=(backIndex+1)%capacity;//增加deque的元素数量++size; }

3.3、出队

3.3.1、头部
  • 在头部删除元素
  • 如果没有元素就用out_of_range()告知。
  • 先移动索引,再size减一。
void pop_front(){//检查deque是否为空if(size==0){throw out_of_range("deque is empty");} //删除不需要显示地删除,以后新追加元素会自动覆盖frontIndex = (frontIndex+1)%capacity;//减少deque的数量--size; }
3.3.2、尾部
  • 在尾部删除元素
  • 如果没有元素就用out_of_range()告知。
  • 先移动索引,再size减一。
void pop_back(){if(size==0){throw out_of_range("deque is empty");}backIndex = (backIndex+capacity-1)%capacity;--size;	} 
举例表示front和back的移动过程
1、开始的时候(假设容量为5)
索引: [0] [1] [2] [3] [4] [5] [6] [7]:   空  空  空  空  空  空  空  空  
指针: front=0, back=0, size=02、操作1:push_back(10)
[0]=10, [1-7]=空  
指针: front=0, back=1, size=13、操作2:push_front(20)
[7]=20, [0]=10, [1-6]=空  
指针: front=7, back=1, size=24、操作3:push_back(30)
[7]=20, [0]=10, [1]=30, [2-6]=空  
指针: front=7, back=2, size=35、操作4push_front(40)
[6]=40, [7]=20, [0]=10, [1]=30, [2-5]=空  
指针: front=6, back=2, size=46、操作5pop_back()
[6]=40, [7]=20, [0]=10, [1-5]=空  
指针: front=6, back=1, size=37、操作6pop_front()
[7]=20, [0]=10, [1-5]=空  
指针: front=7, back=1, size=2

在这里插入图片描述

3.4、清空

  • 直接修改成员变量。
	//清空void clear() {// 更高效的清空方式frontIndex = 0;backIndex = 0;size = 0;}

3.5、随机访问

  • 需要运算符重载 [ ]
	//随机访问[]T& operator[](int index){if(index<0||index>=size){throw out_of_range("index is invalid");}return elements[(frontIndex+index)%capacity];} size_t get_size()const{return size;}

3.6、大小

  • 返回数据数量
	size_t get_size()const{return size;}

3.7、完整过程


#include <iostream>
#include <sstream>
#include <stdexcept>
#include <string>
using namespace std;
template <class T> 
class deque{
private:T* elements;size_t capacity;size_t frontIndex;size_t backIndex;size_t size;
public://构造函数deque():elements(NULL),capacity(0),frontIndex(0),backIndex(0),size(0){}//析构 ~deque(){clear();delete[] elements;}//在deque的前端插入元素void push_front(const T&value){if(size==capacity){resize();}//计算新的前端位置插入元素frontIndex = (frontIndex-1+capacity)%capacity;//在新的前端位置插入元素 elements[frontIndex] = value;//增加size++size; } //在尾部插入元素 void push_back(const T&value){if(size==capacity){resize();}elements[backIndex]=value;//计算新的后端索引 backIndex=(backIndex+1)%capacity;//增加deque的元素数量++size; }//从deque的前端移除元素void pop_front(){//检查deque是否为空if(size==0){throw out_of_range("deque is empty");} //删除不需要显示地删除,以后新追加元素会自动覆盖frontIndex = (frontIndex+1)%capacity;//减少deque的数量--size; }//从deque的后端删除void pop_back(){if(size==0){throw out_of_range("deque is empty");}backIndex = (backIndex+capacity-1)%capacity;--size;	} //随机访问[]T& operator[](int index){if(index<0||index>=size){throw out_of_range("index is invalid");}return elements[(frontIndex+index)%capacity];} //大小 size_t get_size()const{return size;}//清空void clear() {// 更高效的清空方式frontIndex = 0;backIndex = 0;size = 0;}//打印deque中的值void printElements()const{size_t index = frontIndex;for(size_t i =0;i<size;++i){cout<<elements[index]<<" ";index = (index+1)%capacity;}cout<<endl;} 
private:void resize(){size_t newCapacity = (capacity==0)?1:capacity *2;//创建新的数组T* newElements = new T[newCapacity];//复制元素到新的数组size_t index = frontIndex;for(size_t i =0;i<size;++i){newElements[i]=elements[index];index = (index+1)%capacity;} //释放旧内存 delete[] elements;//更新elements = newElements;capacity = newCapacity;frontIndex = 0;backIndex = size; }};
int main(int argc, char *argv[]) {deque<int>myDeque;int N;cin>>N;getchar();string line;for (int i = 0; i < N; i++) {std::getline(std::cin, line);std::istringstream iss(line);std::string command;iss >> command;int value;if (command == "push_back") {iss >> value;myDeque.push_back(value);}if (command == "push_front") {iss >> value;myDeque.push_front(value);}if (command == "pop_back") {if (myDeque.get_size() == 0) {continue;}myDeque.pop_back();}if (command == "pop_front") {if (myDeque.get_size() == 0) {continue;}myDeque.pop_front();}if (command == "clear") {myDeque.clear();}if (command == "size") {std::cout << myDeque.get_size() << std::endl;}if (command == "get") {iss >> value;std::cout << myDeque[value] << std::endl;}if (command == "print") {if (myDeque.get_size() == 0) {std::cout << "empty" << std::endl;} else {myDeque.printElements();}}}
}

相关文章:

  • windows使用docker-desktop安装milvus和可视化工具attu
  • TA学习之路——2.2 模型与材质基础
  • 冒泡与 qsort 排序策略集
  • #Linux内存管理# 为用户进程分配物理内存,分配掩码应该选用GFP_KERNEL,还是GFP_HIGHUSER_MOVABLE呢?
  • 蓝桥杯日期的题型
  • Ubuntu中snap
  • 【LangChain核心组件】Callbacks机制深度剖析与实战指南
  • WPF 使用 DI EF CORE SQLITE
  • H.265硬件视频编码器xk265代码阅读 - 帧内预测
  • K8S微服务部署及模拟故障观测
  • 优化IDEA2024.3大型项目启动慢
  • 网络安全与信息安全防护措施
  • 基于stm32的手机无线充电研究
  • iOS崩溃堆栈分析
  • 手机上的APN是什么,该怎么设置
  • MySQL事务详解:从5.7到8.0的变化
  • 用户管理(添加和删除,查询信息,切换用户,查看登录用户,用户组,配置文件)
  • LeetCode[28]找出字符串中第一个匹配项的下标(KMP版本)
  • prime-2 靶场笔记(vuInhub靶场)
  • 【含文档+PPT+源码】物联网车辆GPS定位管理系统【
  • 销售网站怎么做/软文标题和内容
  • 招商网站建设方案/网店运营怎么学
  • 有自己的网站如何做淘宝客/备案查询站长之家
  • 许昌做网站优化/国际新闻最新消息今天军事新闻
  • wordpress怎么屏蔽注册链接/百度seo运营工作内容
  • 网站建设外包行业/seo网站制作优化