栈
定义:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作,故栈又称为后进先出的线性表。
栈上存什么?
- 在函数体内定义的变量以及函数调用时的实参;
- 基本类型(int,short,long,byte,float,double,boolean,char)变量存储在栈上;
- 对象的引用变量存储在栈上。
栈的特殊性
栈区的变量由编译器自动分配释放内存
存在栈中的数据可以共享
栈的分类
- 1 顺序栈
顺序栈和顺序表数据成员相同,但顺序栈只能在栈顶进行入栈和出栈操作
缺陷:必须事先确定存储空间的大小 - 2 共享栈
原理:两个栈共享一段空间向中间靠拢
缺陷:空间利用率低 - 3 链式栈
原理:使用链表来实现栈,栈顶在链头
优点:空间利用率高
缺点:需要为每个栈元素分配额外的指针空间存放指针域
栈应用
用两个栈模拟实现一个队列
#include<iostream>
#include<stack>
using namespace std;
template<class T>
class Queue
{
public:
Queue()
{}
void appendTail(const T& element)
{
stack1.push(element);
}
T deleteHead()
{
if (stack2.size() <= 0)
{
while (stack1.size() > 0)
{
T& data = stack1.top();
stack1.pop();
stack2.push(data);
}
}
if (stack2.size() == 0)
cout << "queue is empty" << endl;
T head = stack2.top();
stack2.pop();
return head;
}
private:
stack<T> stack1;
stack<T> stack2;
};
队列
定义:只允许在一端(队尾)进行插入数据操作,在另一端(队头)进行删除数据操作的特殊线性表。
特征:队列具有先进先出的特性
队列的分类
- 1 顺序队列
队头不动,出栈时队头后的所有元素向前移动
缺陷:会发生假溢出
顺序队列因多次入队列和出队列操作后出现的尚有存储空间但不能再进行入队列操作的溢出称为假溢出,如下图所示
- 2 循环队列
解决“假溢出”的办法就是后面满了,就从头在开始,也就是头尾相接的循环
定义:将头尾相接的顺序存储队列称为循环队列
- 3 链式队列
队列的链式存储结构,也就是线性表的单链表,但是它只能进行尾插和头删
- 4 优先级队列
带有优先级的队列称为优先级队列
有时需要把进入队列中的元素分优先级,出队列时首先选择优先级最高的元素出队列,对于优先级相同的元素则按照先进先出的原则出队列。
队列的应用
用两个队列实现一个栈
1.把a,b,c三个元素依次插入queue1,这时候queue1包含3个元素a,b,c,其中a位于队列的头部,c位于队列的尾部。
2.考虑从栈内弹出一个元素,根据栈的后入先出原则,最后被压入栈的c应该最先被弹出。由于c位于queue1的尾部而我们每次只能从队列的头部删除元素,所以可以先从queue1中依次删除元素a,b并插入到queue2中,再从queue1中删除元素c。这就相当于从栈中弹出元素c了,可以用同样的方法弹出b,再插入一个元素d时和上述的方法相同,如下图所示
#include<iostream>
#include<queue>
using namespace std;
template<class T>
class Stack
{
public:
Stack()
{}
~Stack()
{}
void appendTail(const T& element)
{
queue1.push(element);
}
T deleteHead()
{
T head = 0;
if (queue2.empty())
{
int size = queue1.size();
while (size > 1)
{
T& data = queue1.front();
queue1.pop();
queue2.push(data);
--size;
}
head = queue1.front();
queue1.pop();
}
else
{
int size = queue2.size();
while (size > 1)
{
T& data = queue2.front();
queue2.pop();
queue1.push(data);
--size;
}
head = queue2.front();
queue2.pop();
}
return head;
}
private:
queue<int> queue1;
queue<int> queue2;
};
void test()
{
Stack<int> s;
s.appendTail(1);
s.appendTail(2);
s.appendTail(3);
s.deleteHead();
}
int main()
{
test();
system("pause");
return 0;
}