目录
1.stack(栈)的使用
(1)栈的示意图
(2)栈的使用
[1]栈的常用函数
[2]栈的使用
2.stack的局部模拟实现
(1)模板参数与成员变量
[1]模板参数
[2]成员变量
(2)成员函数
[1]无参构造
[2]元素入栈
[3]元素出栈
[4]获取有效元素个数
[5]判断栈是否是空
[6]返回栈顶元素
3.stack的整体模拟实现
4.queue(队列)的使用
(1)队列的示意图
(2)队列的使用
[1]队列的常用函数
[2]队列的使用
5.queue的局部模拟实现
(1)模板参数与成员变量
[1]模板参数
[2]成员变量
(2)成员函数
[1]无参构造
[2]元素入队列
[3]队头元素出队列
[4]返回有效元素个数
[5]队列判空
[6]获取队头元素的引用
[7]获取队尾元素的引用
6.queue的整体模拟实现
本文主要介绍C++中的stack(栈)和queue(队列)的简单使用和模拟实现。stack和queue都是C++中的适配器。适配器就是对特定的类进行封装,作为适配器的底层容器,然后提供一组成员函数来访问其元素,stack和queue默认都使用deque作为底层容器。它们的用法比较简单,所以模拟实现也比较简洁(本文只实现了常用的函数)。在使用和模拟实现时只需要注意模板参数即可。
栈从栈顶插入和删除元素;队列从队尾插入元,从队头删除元素。很适合用动态数组vector来作为模拟实现时底层的结构。
本文代码均在win10系统的vs2019验证。
栈是先入后出的数据结构。C++中的栈可以存储多种类型的元素,因此它也是模板。
栈底封闭,不可以从栈底对元素进行操作,栈的插入元素和删除元素均在栈顶进行。
下表列举栈中常用的7个函数。
函数说明 | 功能说明 |
stack() | 构造空栈 |
push(T& val) | 将元素val压入栈中 |
size() | 返回栈中元素个数 |
empty() | 检测栈是否是空,如果是空返回true |
top() | 返回栈顶元素的引用 |
pop() | 将栈顶元素弹出栈 |
C++中的栈是模板,因此在构造空栈时就需要传入需要保存的元素类型。
top函数使用时需要注意,该函数返回的是栈顶元素的引用。
#include "iostream"
#include "stack"
using namespace std;
int main() {
//构造空栈
stack s;
//元素入栈
s.push(1);
s.push(2);
//获取栈中元素个数
int Size = s.size();
//获取栈顶元素的引用
int sTop = s.top();
//元素出栈
s.pop();
//判断栈是否为空
cout << s.empty();
}
模拟实现C++的栈时,应该要考虑用什么作为它的底层,目前来看,貌似动态数组vector是个不错的选择,因为栈只需要在栈顶插入和删除元素。
第二个模板参数的默认值给成vector
我们在这里为栈模板定义了两个模板参数:T是栈中存储的元素的类型,act是栈模板使用的底层结构,act的默认值是vector,如果你想要用别的,可以在这里进行设置。
template>
栈模板的成员变量很简单,只有act类型的变量arr。
class Stack {
private:
//如果没有显示给出act的类型
// act == vector
//创建act类型的变量arr
//如果act是类类型,那么arr是对象
act arr;
};
无参构造很简单,因为并没有存储元素,调用无参构造后,此时栈对象的内部只有一个空的arr变量。
//无参构造
Stack() {}
因为act就是vector,所以arr自然也就是vector的对象,那么只需要让arr调用vector类的尾插函数即可。
//元素入栈
void Push(const T& value = T()) {
arr.push_back(value);
}
与上同理,只需要调用vector类的尾删函数即可。
//元素出栈
void Pop() {
arr.pop_back();
}
复用vector类的函数即可获得有效元素的个数。
//返回栈中元素个数
size_t Size()const {
return arr.size();
}
复用vector类的判空函数。
//判断栈是否是空
bool Empty() const {
return arr.empty();
}
这里给出普通型和const型,因为const类型的对象只能调用const函数。
//普通栈 返回栈顶元素
T& Top() {
return arr.back();
}
//const栈 返回栈顶元素
const T& Top()const {
return arr.back();
}
#include "iostream"
#include "vector"
using namespace std;
template>
class Stack {
private:
//如果没有显示给出act的类型
// act == vector
//创建act类型的变量arr
//如果act是类类型,那么arr是对象
act arr;
public:
//无参构造
Stack() {}
//元素入栈
void Push(const T& value = T()) {
arr.push_back(value);
}
//元素出栈
void Pop() {
arr.pop_back();
}
//返回栈中元素个数
size_t Size()const {
return arr.size();
}
//判断栈是否是空
bool Empty() const {
return arr.empty();
}
//普通栈 返回栈顶元素
T& Top() {
return arr.back();
}
//const栈 返回栈顶元素
const T& Top()const {
return arr.back();
}
};
int main() {
Stack s;
s.Push(1);
s.Push(2);
cout << s.Top() << endl;
cout << s.Size() << endl;
s.Pop();
cout << s.Empty() << endl;
}
队列是先入先出的数据结构。C++中的队列可以存储多种类型的元素,因此它也是模板。
队列的插入元素在队尾进行,队列的删除元素在队头进行。
这里也是主要讲解最常用的几个函数:
函数说明 | 功能说明 |
queue() | 构造空的队列 |
push(T& val) | 将元素val压入队中 |
size() | 返回队列中有效元素的个数 |
empty() | 检查队列是否是空,如果是空返回true |
front() | 返回队头元素的引用 |
back() | 返回队尾元素的引用 |
pop() | 将队头元素出队列 |
C++中的队列是模板,因此在构造空队列时就需要传入需要保存的元素类型。
front函数和back函数使用时需要注意,函数返回的是元素的引用。
#include "iostream"
#include "queue"
using namespace std;
int main() {
//构造空队列
queue q;
//元素入队
q.push(1);
q.push(2);
//返回有效元素个数
int size = q.size();
//检查队列是否为空
cout << q.empty() << endl;
//获取队头元素的引用
int frNum = q.front();
//获取队尾元素的引用
int baNum = q.back();
//队头元素出队
q.pop();
}
C++的队列需要从队头删除元素,从队尾插入元素,所以vector类也可以用来作为队列的底层。而且其实队列和栈的模拟实现非常相似,因此在模拟实现时相同之处就不再赘述了。
我们在这里为栈模板定义了两个模板参数:T是栈中存储的元素的类型,act是栈模板使用的底层结构,act的默认值是vector。
template>
class Queue {
private:
act arr;
};
//无参构造
Queue() {}
//元素入队列
void Push(const T& value = T()) {
arr.push_back(value);
}
队头元素就是arr的第一个元素,也就是begin迭代器指向的位置,因此只需要删除begin迭代器指向的元素即可。
//队头元素出队列
void Pop() {
arr.erase(arr.begin());
}
//返回队列元素个数
size_t Size() const {
return arr.size();
}
//判断队列是否为空
bool Empty() {
return arr.empty();
}
//普通对象 返回队头元素的引用
T& Front() {
return arr.front();
}
//const对象 返回队头元素的引用
const T& Front() const{
return arr.front();
}
//普通对象 返回队尾元素的引用
T& Back() {
return arr.back();
}
//const对象 返回队尾元素的引用
const T& Back() const{
return arr.back();
}
#include "iostream"
#include "vector"
using namespace std;
template>
class Queue {
private:
act arr;
public:
//无参构造
Queue() {}
//元素入队列
void Push(const T& value = T()) {
arr.push_back(value);
}
//队头元素出队列
void Pop() {
arr.erase(arr.begin());
}
//返回队列元素个数
size_t Size() const {
return arr.size();
}
//判断队列是否为空
bool Empty() {
return arr.empty();
}
//普通对象 返回队头元素的引用
T& Front() {
return arr.front();
}
//const对象 返回队头元素的引用
const T& Front() const{
return arr.front();
}
//普通对象 返回队尾元素的引用
T& Back() {
return arr.back();
}
//const对象 返回队尾元素的引用
const T& Back() const{
return arr.back();
}
};
int main() {
Queue q;
q.Push(1);
q.Push(2);
cout << q.Size() << endl;
cout << q.Front() << endl;
cout << q.Back() << endl;
q.Pop();
cout << q.Empty() << endl;
}