1.栈定义
栈又称堆栈,是一种运算受限的线性表,限制是仅仅允许在表的另外一端进行插入和删除运算。
2.特点
后进先出、cpu缓存利用率相对较高、不允许随意访问
3.实现方式
栈有两种实现方式,一种是顺序存储,和数组类似。一种是链式存储,和单链表类似。
(这是在2013编译器下)
栈里面有以下几种函数:
void Push(const T& x);
void Pop();
T& Top();
bool Empty();
size_t Size();
栈函数定义和实现:
template<class T>
class Stack
{
public:
Stack()//构造函数
:_a(NULL)
, _size(0)
, _capacity(0)
{}
Stack(const Stack<T> & s)//拷贝构造函数
{
_capacity = s._capacity;
_size = s._size;
_a = new T[_capacity];
for (size_t i = 0; i < _size; i++)//非内置类型例如String类型时,用for循环赋值
{
_a[i] = s._a[i];
}
}
Stack<T>& operator=(const Stack<T> &s)//赋值运算符重载
{
if (_capacity < s._capacity)
{
_capacity = s._capacity;
_a = new T[_capacity];
}
_size = s._size;
for (size_t i = 0; i < _size; i++)
{
_a[i] = s._a[i];
}
return *this;
}
~Stack()//析构函数
{
if (_a)
{
delete _a;
}
}
//接口函数实现
void Push(const T& x)//入栈,插入数据
{
_CheckCapacity();
_a[_size++] = x;
}
void Pop()//删除数据
{
assert(_size);
--_size;
}
T& Top()//返回栈顶元素
{
assert(_size);
return _a[_size - 1];
}
bool Empty()//判空
{
return _a == 0;
}
size_t Size()//元素个数
{
return _size;
}
protected:
void _CheckCapacity()//判断容量
{
if (_size >= _capacity)
{
T* tmp = new T[_capacity * 2 + 10];
for (size_t i = 0; i < _size; i++)
{
tmp[i] = _a[i];
}
delete _a;
_a = tmp;
_capacity = _capacity * 2 + 10;
}
}
protected:
T * _a;//存储数据的指针
size_t _size;//存储数据个数
size_t _capacity;//容量
};
测试函数:
void TestStack()
{
Stack<int> s;
s.Push(1);
s.Push(2);
s.Push(3);
s.Push(4);
cout << s.Size() << endl;
s.Pop();
cout << s.Size() << endl;
cout << s.Empty() << endl;
cout << s.Top() << endl;
}
结果:
关于栈的一个小应用,其中有一个后缀表达式的计算,也叫做逆波兰表达式,参加运算的操作数总在操作符前面。
后缀表达式求值过程:顺序扫描表达式的每一项,如果该项是操作数,则将其压入栈中,如果是操作符,则从栈中退出两个操作数,形成运算指令,并将运算结果再压入栈中。
下面简单的模拟实现一下后缀表达式:
#include<iostream>
using namespace std;
#include<assert.h>
#include <stack>
enum Type
{
OP_SYMBOL, //操作符
OP_NUM, //操作数
ADD,
SUB,
MUL,
DIV,
};
struct Cell //cell单元存储里面的枚举类型和所push的操作数
{
Type _type;
int _value;
};
int CountPRN(Cell* rpn, size_t n)
{
assert(rpn);
stack<int> s;
for (size_t i = 0; i < n; ++i)
{
if (rpn[i]._type == OP_NUM) //若数组中为操作数则压栈
{
s.push(rpn[i]._value);
}
else if (rpn[i]._type == OP_SYMBOL)//若为操作符则出栈运算
{
int right = s.top();
s.pop();
int left = s.top();
s.pop();
switch (rpn[i]._value)
{
case ADD:
s.push(left + right);
break;
case SUB:
s.push(left - right);
break;
case MUL:
s.push(left * right);
break;
case DIV:
s.push(left / right);
break;
default:
assert(false);
}
}
}
return s.top();
}
void TestRPN()
{
Cell RPN[] = {
{ OP_NUM, 8 },
{ OP_NUM, 2 },
{ OP_SYMBOL, MUL }
};
cout << CountPRN(RPN, sizeof(RPN) / sizeof(RPN[0]));
}
int main()
{
TestRPN();
system("pause");
return 0;
}
结果: