用栈实现队列

前言

今天我的任务是首先利用一个小时完成用栈实现队列以及用队列实现栈的代码整理,并保证能够独立写出来,然后利用半小时的时间,完成串的概念以及代码的学习,然后去健身一个小时到一个半小时,然后利用半小时吃个饭,然后晚上七点半回来做牛客周赛,比赛结束后,利用一个小时学习概数。

代码

cpp 复制代码
#include<iostream>
#include<stdexcept>
using namespace std;
template<typename T>
class Stack {
private: 
	T* data;
	int size;
	int capacity;
	void resize();
public:
	Stack() :data(new T[10]), size(0), capacity(10){}
	~Stack();
	void push(T x);
	T pop();
	T top() const;//必须加const
	int getSize() const;//必须加const
	bool empty() const;//添加判断是否为空的接口
};
template<typename T>
void Stack<T>::resize() {
	T* newData = new T[capacity * 2];
	for (int i = 0; i < size; i++) {
		newData[i] = data[i];
	}
	delete[] data;
	data = newData;
	capacity *= 2;
}
template<typename T>
Stack<T>::~Stack() {
	delete[] data;
}
template<typename T>
void Stack<T>::push(T x) {
	if (size == capacity) {
		resize();
	}
	data[size++] = x;
}
template<typename T>
T Stack<T>::pop() {
	if (size == 0) {
		throw underflow_error("Stack is empty!");
	}
	return data[--size];
}
template<typename T>
T Stack<T>::top() const{
	if (size == 0) {
		throw underflow_error("Stack is empty!");
	}
	return data[size - 1];
}
template<typename T>
int Stack<T>::getSize() const{
	return size;
}
template<typename T>
bool Stack<T>::empty() const {
	return size == 0;
}
//template<typename T>不用写这个
class Queue {
private:
	Stack<int> s1;//直接大小于号套数据类型
	Stack<int> s2;//辅助栈
public:
	Queue(){} 
	void push(int x) {//这里为什么不先声明然后再实现函数呢
		s1.push(x);
	}
	int pop() {//这个接口的实现逻辑有点看不懂
		if (s2.empty()) {
			while (s1.getSize()) {
				s2.push(s1.pop());
			}
		}
		return s2.pop();
	}
	int peek() {//返回队首元素
		if (s2.empty()) {
			while (s1.getSize()) {
				s2.push(s1.pop());
			}
		}
		return s2.top();
	}
	bool empty() {
		/*if (s1.empty() && s2.empty()) {
			return true;
		}
		else {
			return false;
		}*/
		return s1.empty() && s2.empty();
	}
};
int main() {
	Queue q;
	q.push(1);
	q.push(2);
	q.push(3);
	q.push(4);
	cout << q.pop();
	return 0;
}

解释

按照以往的传统,我们依然采用逐字逐句去剖析的方法,

首先是栈部分代码的实现,这里我们首先是利用顺序表来实现这个栈,这部分的代码我们之前已经讲过啦,请看这个顺序表实现栈:具体函数实现​​​​​​,然后这里主要说一下相比以前添加的部分,这是判断栈为空的函数,后续需要配合实现队列的过程使用。

cpp 复制代码
template<typename T>
bool Stack<T>::empty() const {
	return size == 0;
}

然后就是队列的类的实现啦,前面栈的类的实现部分使用了这一行语句template<typename T>,这里使用模板将Stack类作为通用型栈容器,可以支持任何的数据类型,而下面这个队列被设计为存储int类型的队列,所以不需要模板的声明,其中作为成员变量的两个栈,数据类型也是用通用栈的类名加上对应的数据类型来使用的。

cpp 复制代码
//template<typename T>不用写这个
class Queue {
private:
	Stack<int> s1;//直接大小于号套数据类型
	Stack<int> s2;//辅助栈

还有后面的具体函数实现部分,与前面栈的类的实现不同,队列这里的函数是直接在类内实现的,而前面通用型栈的类的实现中,函数都是在类外进行实现的,其实两者实现方式都是可以的,只不过模板类的要加上全模板声明(比如template<typename T> void Stack<T>::push(T x))。

还有就是,在队列的类的实现中,构造函数中没有任何内容,这是因为实现队列的两个栈已经在栈的类中完成了初始化,所以说在队列中就不需要啦。

cpp 复制代码
public:
	Queue(){} 
	void push(int x) {//这里为什么不先声明然后再实现函数呢
		s1.push(x);
	}
	int pop() {//这个接口的实现逻辑有点看不懂
		if (s2.empty()) {
			while (s1.getSize()) {
				s2.push(s1.pop());
			}
		}
		return s2.pop();
	}
	int peek() {//返回队首元素
		if (s2.empty()) {
			while (s1.getSize()) {
				s2.push(s1.pop());
			}
		}
		return s2.top();
	}
	bool empty() {
		/*if (s1.empty() && s2.empty()) {
			return true;
		}
		else {
			return false;
		}*/
		return s1.empty() && s2.empty();
	}
};

反思

对于获取长度,获取栈顶元素,判断是否为空等函数,不要忘记添加const关键字

相关推荐
CSharp精选营2 天前
关系型 vs 非关系型:从原理到选型,一文搞定数据库核心分类
数据结构·nosql·关系型数据库·非关系型数据库·技术选型
用户805533698032 天前
不止三件套:QObject 属性系统全关键字与运行时反射!
c++·qt
BadBadBad__AK2 天前
线段树维护区间 k 次方和
c++·数学·算法·stl
卷无止境3 天前
Eigen 库如何借助 OpenMP 加速计算
c++·后端
卷无止境3 天前
OpenMPI、MPICH 与 OpenMP:关系、核心概念与架构全解
c++·后端
郝学胜_神的一滴4 天前
CMake 30:循环语法全解|foreach_while双循环精讲、迭代技巧与实战避坑指南
c++·cmake
刘马想放假5 天前
Modbus 全栈技术解析:TCP、RTU、ASCII、RTU over TCP
数据结构·网络协议
北域码匠6 天前
冒泡排序太慢?鸡尾酒排序双向优化,原生 C# 零第三方库完整代码
数据结构·排序算法·泛型·c# 算法·鸡尾酒排序·原生 c# 开发·冒泡排序优化·嵌入式算法
卷无止境6 天前
C++ 的Eigen 库全解析
c++
卷无止境6 天前
现代 C++特性大盘点:一门脱胎换骨的老语言
c++·后端