stack 容器(栈)
只支持在栈顶 存取 元素
后进先出
queue容器(队列)
从容器尾部插入元素,从容器头部取元素
先进先出
// C++学习笔记_19 适配器容器-stack queue
#include <iostream>
#include<string>
#include<vector>
#include<list>
#include<stack> //STL 中栈的头文件
#include<queue>
using namespace std;
void TestStack()
{
stack<int> iStack1;
//事实上,就是把 deque 封装了一下,限制了一些函数的使用,而且不提供迭代器。
//push 调用 deque.push_back(); pop 调用 deque.pop_back(); 等等
//这里,deque 我们称之为 底层容器 (默认使用deque做底层容器)
//能不能用 list, vector 做底层容器呢?
stack<int> iStack2(iStack1);
stack<int> iStack3({ 1, 2, 3, 4, 5 });
stack<int, list<int>> iStack4; //可以使用 list 做底层容器
stack<int, vector<int>> iStack5; //可以使用 vector 做底层容器
//区别就是 list 和 deque 的区别,vector 和 deque 的区别 ---》 数据的存储方式不同
//所用容器都有的函数
//empty()
//size()
cout << "压栈:";
for (int i = 0; i < 10; i++){
cout << i << " ";
iStack1.push(i);
iStack4.push(i);
iStack5.push(i);
}
cout << endl;
cout << "弹栈:";
while (!iStack1.empty()) {
cout << iStack1.top() << " "; //取栈顶元素
//注意一点 iStack1.top()
//返回值是引用:意味着可以通过复制来修改栈顶元素
// iStack1.top() = xxx;
iStack1.pop();//删除栈顶元素
}
cout << endl;
cout << "弹栈:";
while (!iStack4.empty()){
cout << iStack4.top() << " "; //取栈顶元素
iStack4.pop();//删除栈顶元素
}
cout << endl;
cout << "弹栈:";
while (!iStack5.empty()){
cout << iStack5.top() << " "; //取栈顶元素
iStack5.pop();//删除栈顶元素
}
cout << endl;
}
void TestQueue()
{
queue<int> iQue1;
queue<int> iQue2(iQue1);
queue<int> iQue3({ 1, 2, 3, 4, 5 });
//队列的底层容器也是 deque
//能不能用 vector 和 list ?
//queue<int, vector<int>> iQue4;
//queue.pop() 弹出元素,调用的是底层容器的 pop_front()
//vector 容器没有这个方法,所以,queue 不能是用 vector做底层容器
queue<int, list<int>> iQue5;
//empty(); size()
cout << "入队列:";
for (int i = 0; i < 10; i++){
cout << i << " ";
iQue1.push(i);
//iQue4.push(i);
iQue5.push(i);
}
cout << endl;
//O(N^2) , O(2^N)
//可以取队头和队尾元素
cout << "队头元素:" << iQue1.front() << endl;
cout << "队尾元素:" << iQue1.back() << endl;
//这里 front() 和 back() 都返回引用 ---》可以直接赋值,修改队头和队尾元素
cout << "出队列:";
while (!iQue1.empty()){
cout << iQue1.front() << " ";
iQue1.pop(); //删除队头元素
}
cout << endl;
/*
cout << "出队列:";
while (!iQue4.empty()){
cout << iQue4.front() << " ";
//error C2039: “pop_front”: 不是“std::vector<int,std::allocator<_Ty>>”的成员
iQue4.pop(); //删除队头元素
}
cout << endl;
*/
cout << "出队列:";
while (!iQue5.empty()){
cout << iQue5.front() << " ";
iQue5.pop(); //删除队头元素
}
cout << endl;
}
int main()
{
TestStack();
TestQueue();
system("pause");
return 0;
}
//C 语言的 栈实现
#include <iostream>
using namespace std;
//创建栈结构体
typedef struct tagStack
{
int *pBase; //栈内存起始地址
int *pTop; //栈顶指针 (下一个元素存在这里)
int size; //栈的长度
} MyStack;
//申请栈
int InitStack(MyStack *pStack, int sz)
{
pStack->pBase = (int*)malloc(sz*sizeof(int));
if (pStack->pBase == NULL) return -1;
pStack->pTop = NULL; //表示空栈
pStack->size = sz;
return 0;
}
//进栈
int push(MyStack *pStack, int data)
{
//1: 空间不够
if (pStack->pTop == pStack->pBase + pStack->size - 1) return -1;
//栈顶上移
if (pStack->pTop == NULL) pStack->pTop = pStack->pBase;
else (pStack->pTop)++;
//存元素到栈顶
*(pStack->pTop) = data;
return 0;
}
//出栈, 直接删除栈顶,返回成功或者失败
int pop(MyStack *pStack)
{
//空栈
if (pStack->pTop == NULL) return -1;
(pStack->pTop)--;
//并没有做删除元素的操作 (指针下移,把元素位置置为不可用)
return 0;
}
//取栈顶元素, 返回栈顶元素
int top(MyStack *pStack)
{
//考虑一个问题:空栈?
//if (pStack->pTop == NULL)
//{
//写断言,抛出异常,....
//也可以不写,有使用者保证空栈的时候,不调用它
//}
return *(pStack->pTop);
}
bool empty(MyStack *pStack)
{
return !(pStack->pTop == NULL);
}
//获取栈中元素个数 (不是栈的大小)
int size(MyStack *pStack)
{
if (pStack->pTop == NULL) return 0;
else
return pStack->pTop - pStack->pBase + 1;
}
//释放栈内存
void DestroyStack(MyStack *pStack)
{
if (pStack->pBase){
free(pStack->pBase);
pStack->pBase = NULL;
pStack->pTop = NULL;
pStack->size = 0;
}
}
void Test_MyStack()
{
MyStack *pStack;
InitStack(pStack, 5);
for(int i=0;i<5;i++)
push(pStack, i+1);
cout<<top(pStack)<<endl;
cout<<pop(pStack)<<endl;
cout<<top(pStack)<<endl;
cout<<empty(pStack)<<endl;
cout<<size(pStack)<<endl;
DestroyStack(pStack);
cout<<size(pStack)<<endl;
}
int main()
{
Test_MyStack();
return 0;
}
typedef struct tagQueue
{
int *pBase; //指定内存起始位置
int *pHead;
int *pTail;
int size;
}MyQueue;
//pBase 基址
//pTail 指向队尾元素
//为了不移动元素,我们再定义一个 pHead 指针,指向队头元素 (做成一个循环形式)
//1:一个元素出队 --》把 pHead 后移
//2:pTail 到了末尾位置? --》判断 pHead 是不是在 pBase
// 是的话,表示存满了,不是的话,存到 pBase 位置来 (跳转到起始位置)
//3:同样的 pHead 到了末尾,移动到 pBase 位置
// 这个时候 如果 pTail 也在这个位置,表示队列是空的了
//4:事实上:pHead == pTail 表示队列是空的
// pTail 的后一个位置(末尾的后一个位置就跳到了队头),是 pHead 表示队列满了
//5:所以我们要注意一点:N 个长度的队列,只能插入 N-1 个元素
// 有个位置留白,用于区分到底是空队列还是满队列
//作业:自己实现队列 InitQueue push pop front back empty size destroy