栈的特点:
栈:仅限尾部插入或删除的线性表
表尾:栈顶
表头:栈底
特性:后进先出
顺序栈:用数组实现
结构为:
template <class T>
class stack
{
public:
stack();//初始化
~stack();//析构
void push(T x);//插入元素
void pop();//删除元素
T top(); //查看栈顶元素
int size();//元素个数
bool empty();//判空
private:
int _size; //计算数据数量
T *p; //创建一个指针
};
#include<iostream>
#include<vector>
using namespace std;
const int MAX_size = 500;
template <class T>
class stack
{
public:
stack();//初始化
~stack();//析构
void push(T x);//插入元素
void pop();//删除元素
T top(); //查看栈顶元素
int size();//元素个数
bool empty();//判空
private:
int _size; //计算数据数量
T *p; //创建一个指针
};
//初始化
template <class T>
stack<T>::stack() {
_size = 0; //个数为0
p = new T[MAX_size];//开辟500个空间
}
//析构
template <class T>
stack<T>::~stack() {
if (p != nullptr)//当p不为空指针时释放内存,并把p变为空指针
{
delete[]p;
p = nullptr;
}
}
//插入数据
template <class T>
void stack<T>::push(T x)
{
if (_size == MAX_size)//容量不足 退出
{
exit(1);
}
p[_size]=x;//容量未满,插入数据
_size++;
}
//查看栈顶元素
template <class T>
T stack<T>::top()
{
if (_size == 0)//没有元素的话 返回0
{
exit(1);
}
return p[_size-1];///返回栈顶数据
}
//删除元素
template <class T>
void stack<T>::pop()
{
if (_size == 0)
{
exit(1)
}
_size--;//元素个数减一
}
//返回元素个数
template <class T>
int stack<T>::size()
{
return _size;//返会元素个数
}
//判空
template <class T>
bool stack<T>::empty()
{
if (_size == 0)
{
return true;
}
return false;
}
int main()
{
stack<int> P;
P.push(5);
cout << P.top() << endl;
system("pause");
return 0;
}
链栈:
push的实现:
- 先生成一个新结点
- 用新结点的指针指向 top节点
- top指针指向新节点
pop的实现:
- 先生成一个新节点指向top的内部节点
- 删除top节点
- top指向新节点
#include<iostream>
using namespace std;
template<class T>//让栈元素节点类提前知道有栈
class Stack;
//定义一个栈元素节点类
template<class T>
class StackNode
{
friend class Stack<T>;//声明栈类为节点类的友元,以便访问其私有数据
public:
StackNode() {};
StackNode(T _data) :data(_data), base(nullptr) {};
~StackNode() {};
private:
T data;
StackNode<T>* base;
};
//栈
template<class T>
class Stack
{
public:
Stack();
~Stack();
void Push(const T p);//插入元素
void Pop();//删除元素
T Top();//返回栈顶元素
bool Empty();//判空
int Size();//元素个数
private:
int size;
StackNode<T>* top;
};
//初始化
template<class T>
Stack<T>::Stack()
{
size = 0;//初始个数为0
top = nullptr;//把头指针设为空指针
}
//析构函数
template<class T>
Stack<T>::~Stack()
{
while (!Empty())//不为空就一直删除栈顶元素
{
Pop();
}
}
//添加数据
template<class T>
void Stack<T>::Push(const T p)
{
StackNode<T>* P = new StackNode<T>(p);
P->base = top;//p的base指向 top
top = P;//top指向P节点
size++;//节点数加一
}
//删除数据
template<class T>
void Stack<T>::Pop()
{
if (size == 0)//个数为0,结束
{
exit(1);
}
StackNode<T>* P = top->base;//新建一个指针指向top内部节点(下一个节点)
delete top;//释放top的内存
top = P;//top指向栈顶下一个节点
size--;//个数减一
}
//查看数据
template<class T>
T Stack<T>::Top()
{
if (size == 0)//为空,结束
{
exit(1);
}
return top->data;//不为空,返回数据
}
//返回个数
template<class T>
int Stack<T>::Size()
{
return size;
}
//判空
template<class T>
bool Stack<T>::Empty()
{
if (size == 0)
{
return true;
}
return false;
}
int main()
{
Stack<int>m;
m.Push(6);
cout<<m.Top()<<endl;
cout << m.Size() << endl;
system("pause");
return 0;
}
栈的应用:
前中后缀表达式:
- 前缀表达式:(波兰式)把运算符放在前面,把数据放在后面。
- 中缀表达式:正常的表达式
- 后缀表达式:(逆波兰式),指不包含括号,运算符放在两个运算对象的后面,所有的计算运算符出现的顺序严格按照从左到右运行(不在考虑运算符的优先规则)
前缀表达式的运算过程:
从右至左扫描表达式,遇到数字时,将数字压入堆栈,遇到运算符时,弹出栈顶的两个数,用运算符对它们做相应的计算,并将结果入栈;重复上述过程直到表达式最左端,最后运算得出的值即为表达式的结果。
后缀表达式的运算过程:
从左至右扫描表达式,遇到数字时,将数字压入堆栈,遇到运算符时,弹出栈顶的两个数,用运算符对它们做相应的计算,并将结果入栈;重复上述过程直到表达式最左端,最后运算得出的值即为表达式的结果。