一、什么是栈
栈是只能在表尾进行插入和删除的线性表,又称后进先出线性表,简称LIFO结构。在软件应用中,比如浏览器的后退键、文档的撤销操作,都是通过栈来实现的。
下面是有关栈的几个概念:
1.栈顶: 允许进行插入和删除操作的一段称为栈顶
2.栈底: 与栈顶相对应的,不允许进行插入和删除操作的一段称为栈底
3.空栈: 不含任何数据元素的栈
4.栈的操作
在栈中插入一个元素,称为进栈,又称压栈。
从栈中删除一个元素,称为出栈,又称弹栈。
需要注意的是最先进栈的元素,并非只能最后出栈,而是只要保证一个元素位于栈顶,就能最先出栈。
二、栈的顺序存储结构——顺序栈
1.定义及初始化
在C语言中,我们使用结构体定义栈。而C++使用类模板。相较而言,C++的代码复杂性更高,空间使用也更加灵活。
//C
#define STACKSIZE 100
typedef int DataType;
typedef struct
{
DataType data[STACKSIZE]; //用数组表示栈的空间
int top; //栈顶指针
}SeqStack;
void initstakk(SeqStack* s) //栈的初始化操作
{
s->top = -1;
}
//C++
template<typename Type> class Stack {
private:
Type *elements; //指向栈申请的空间
int max_size,top; //栈中元素个数,栈顶元素位置(栈顶指针)
public:
Stack(int length){ //参数为栈中元素个数
elements = new Type[length];
max_size = length;
top = -1; //栈顶指针初始化
}
~Stack()
{
delete[] elements;
}
};
2.删除栈中所有元素
//C
void clearstack(SeqStack* s)
{
s->top = -1;
}
3.判断栈是否为空
//C
bool stackempty(SeqStack* s)
{
return s->top == -1; //s->top == -1时为空,返回true,非空返回false
}
C语言中,可以不使用结构体指针为形参,但结构体变量为形参是将结构体拷贝过来,需要404个字节的空间,而指针只需要8个字节的空间。拷贝和释放都会降低效率。
4.判断栈是否为满
//C
bool stackfull(SeqStack* s)
{
return s->top == STACKSIZE-1; //检查栈顶指针是否位于最大下标
}
5.进栈
//C
#define ERROR 1
#define OK 1
Status push(SeqStack* s,DataType e) //Status是一种函数类型,函数返回值为函数结果状态代码
{
if(stackfull(s)) //判断栈受否为满,返回一个结果状态码
{
return ERROR;
}
++s->top; //top由-1指向0
s->data[s->top] = e; //即s->data[0] = e
return OK;
}
//C++
bool push(const Type &ele)
{
if(top >= max_size-1)
{
return false;
}
top++; //栈顶指针由-1指向0
elements[top] = ele; //将元素ele加入栈中
return true;
}
6.获取栈顶元素
//C
Status getTop(SeqStack* s,DataType* e)
if(stackempty(s))
{
return ERROR;
}
*e= s->data[s->top];
return OK;
}
//C++
Type top()
{
//判断栈是否为空,使用宏断言,如果表达式返回false,则终止程序
assert(top >= 0);
return elements[top]; //返回栈顶元素
}
7.出栈
//C
Status pop(SeqStack* s,DataType* e) //栈顶指针top会移动
{
if(s->top == -1) //栈为空返回状态码
{
return ERROR;
}
*e= s->data[s->top--];
return OK;
}
//C++
bool pop()
{
if(top < 0)
{
return false;
}
top--; //栈顶指针减1就可以删除栈顶元素
return true;
}
8.获取栈中存储元素个数
//C
int stackLength(SeqStack* s)
{
return s->top + 1;
}