stack和queue详解
一、stack
stack是一种先进后出的的数据结构(FILO),它只有一个出口点,同时也是进口点,stack它允许新增元素,移除元素,取得最顶端元素 ,但是除了最顶端之外没有任何方法取得最顶端元素,换言之,stack不支持遍历行为。
在c++库里面,stack的底部结构是deque,deque是双端开口的数据结构,stack是将deque作为底部结构,并封装了其头端开口形成stack。
因为stack是以底部容器完成其所有功能,而这种具有“修改容器接口而形成另一种风格者,成为adapter(适配器),在STL不称为container(容器),被归类为container adapter(容器适配器)”
二、stack模拟实现
//因为stack是靠着其它2容器实现成功的,所以它实现提别简单
namespace bit
{
template<class T, class container = vector<T>>
class stack
{
container _con;
public:
void push(T x)
{
_con.push_back(x);
}
void pop()
{
_con.pop_back();
}
bool empty()
{
return _con.empty();
}
T& top()
{
return _con.back();
}
size_t size()
{
return _con.size();
}
};
vector和list在库里面都有相关函数,比如尾插,尾删,empty,size,等等。
那有疑问了,为什么这里不需要写构造函数和析构函数?
原因是,编译器会自动调用list或者vector的构造函数和析构函数,所以这里就不用写了
测试:
#pragma once
#include<vector>
#include<iostream>
using namespace std;
namespace bit
{
template<class T, class container = vector<T>>
class stack
{
container _con;
public:
void push(T x)
{
_con.push_back(x);
}
void pop()
{
_con.pop_back();
}
bool empty()
{
return _con.empty();
}
T& top()
{
return _con.back();
}
size_t size()
{
return _con.size();
}
};
void test()
{
stack<int> q;
q.push(1);
q.push(2);
q.push(7);
q.push(0);
q.push(5);
while (!q.empty())
{
cout << q.top() << " ";
q.pop();
}
}
}
int main()
{
bit::test();
return 0;
}
在测试的时候,我在初始化的时候写了一个超级大的错误,
初始化的时候我写成了stack<vector< int>> q ,这样写的话会发生如下错误
正确初始化应该是 stack< int> q,这个等价于stack< int,<vector < int >> q
因为有模板的缘故,可以帮助我们省掉后一部分。
要是底层想用list实现, 初始化就得是 stack< int,<list< int >> q
三、queue(队列)
queue是一种先进先出的数据结构,(FIFO),它有两个出口。queue允许新增元素,移除元素,从最低端加入元素,取得最顶端元素,但除了从最低端加入元素,最顶端取出元素之外,它没有任何方法访问其他元素,换言之,queue不允许有其他的遍历行为
在库里面实现queue是将deque作为底部结构,并封闭其底端出口和前端入口,queue没有迭代器,只有顶端元素才能被访问,也不支持遍历访问
四、queue的模拟实现
#pragma once
#include<list>
#include<iostream>
using namespace std;
namespace bit
{
template<class T,class container = list<int>>
class queue
{
container _con;
public:
void push(T x)
{
_con.push_back(x);
}
void pop()
{
_con.pop_front();
}
bool empty()
{
return _con.empty();
}
T& front()
{
return _con.front();
}
size_t size()
{
return _con.size();
}
};
void test1()
{
queue<int> q;
q.push(1);
q.push(2);
q.push(7);
q.push(0);
q.push(5);
while (!q.empty())
{
cout << q.front() << " ";
q.pop();
}
}
}
int main()
{
bit::test1();
return 0;
}
这里为什么没有构造函数和析构函数理由与stack一样
五、经典例题
思路:
用一个int levelSize变量记录每一层的个数,用一个队列记录每一层的数据,在将每一层的数据加进vector里面,当这一层数据全部记录后,将vector里面的数据加进vector<vector>里面
class Solution {
public:
vector<vector<int>> levelOrder(TreeNode* root)
{
vector<vector<int>> vv;//需要返回的vector
int levelSize = 0;//记录每一层元素的个数
queue<TreeNode*> q;
if(root)
{
levelSize = 1;
q.push(root);
}
while(!q.empty())
{
vector<int> v;
for(int i = 0;i < levelSize;i++)
{
TreeNode* front = q.front();
v.push_back(front->val);
q.pop();
if(front->left)
{
q.push(front->left);
}
if(front->right)
{
q.push(front->right);
}
}//该for结束后,v里面记录该一层的所有数据,q里面是下一层的所有数据
vv.push_back(v);
levelSize = q.size();//更新levelSize,使得levelSize的值变为下一层数据的个数
}
return vv;
}
};