一、栈的定义
栈(stack) 是限定仅在表尾进行插入或删除操作的线性表。因此,对栈来说,表尾端有其特殊含义,称为栈顶(top) ,相应地,表头端称为栈底(bottom) 。不含元素的空表称为空栈。
假设栈 S = ( a 1 , a 2 , . . . , a n ) S=(a_1,a_2,...,a_n) S=(a1,a2,...,an) ,则称 a 1 a_1 a1 为栈底元素, a n a_n an 为栈顶元素。栈中元素按 a 1 , a 2 , . . . , a n a_1,a_2,...,a_n a1,a2,...,an 的次序进栈,退栈的第一个元素应为栈顶元素。换句话说,栈的修改是按后进先出的原则进行的。因此,栈又称为后进先出(last in first out) 的线性表(简称 LIFO 结构)
二、栈的表示和实现
和线性表类似,栈也有两种存储表示方法。
1、顺序栈
顺序栈 ,即栈的书序存储结构是利用一组地址连续的存储单元依次存放自栈底到栈顶的数据元素,同时附设指针top指示栈顶元素在顺序栈中的位置。一个常用的方法是,先为栈分配一个基本容量,然后在应用过程中,当栈的空间不够使用时再逐段扩大。为此,可以设定两个常量:STACK_INIT_SIZE(存储空间初始分配量) 和STACKINCREMENT(存储空间分配增量),并以下述类型说明作为顺序栈的定义。
typedef struct
{
SElemType *base; // 在栈构造之前和销毁之后,base的值为NULL
SElemType *top; // 栈顶指针
int stacksize; // 栈的当前可使用的最大容量,以元素为单位。
} SqStack;
栈的初始化操作为:按设定的初始分配量进行第一次存储分配,1)base 可称为栈底指针,在顺序栈中,它始终指向栈底的位置,若base的值为NULL,则表明栈结构不存在。2)top 为栈顶指针,其初值指向栈底,即top=base 可作为栈空的标记,没当插入新的栈顶元素时,指针top增1,删除栈顶元素时,指针top减1。因此 ,非空栈中的栈顶指针始终在栈顶元素的下一个位置上。
基本操作的算法描述(部分):
(1)、构造一个空栈
InitStack(&S) 操作结果:构造一个空栈S。
Status Init(SqStack s) // Status(void)
{
s.base=(SElemType *)malloc(STACK_INIT_SIZE*sizeof(SElemType)); // SElemType(int)
if(!s.base) exit(OVERFLOW); // 存储分配失败
s.top = s.base;
s.stacksize = STACK_INIT_SIZE;
}
(2)、插入一个元素
Push(&S, e) :插入一个元素e
初始条件:栈s已存在
操作结果:插入元素e为新的栈顶元素。
Status push(SqStack &s, SElemType e)
{ // 插入元素e为新的栈顶元素
if(s.top-s.base >= s.stacksize) // 栈满,追加存储空间
{
s.base = (SElemType *)realloc(s.base, (s.stacksize + STACKINCREMENT)*sizeof(SElemType));
if(!s.base) exit(OVERFLOW); // 存储分配失败
s.top = s.base + s.stacksize;
s.stacksize += STACKINCREMENT;
}
*s.top++ = e;
}
(3)、返回一个元素(出栈)并删除其值
pop(&s, &e) : 返回一个元素并删除其值。
初始条件:栈S已存在且非空。
操作结果:删除S的栈顶元素,并用e返回其值。
Status pop(SqStack &s, SElemType &e)
{ // 若栈不空,则删除s的栈顶元素,用e返回其值,并返回OK;
// 否则返回ERROR
if(s.top == s.base) return ERROR;
e = *(--s.top);
return OK;
}
(4)、得到top的元素,且不删除top对应的值
只是单纯的返回栈顶对应的元素,不删除对应栈顶的值。
Status GetTop(SqStack s, SElemType &e){
// 若栈不空,则用e返回s的栈顶元素,并返回OK,否则返回ERROR
if(s.top == s.base) return ERROR;
e = *(s.top - 1);
return OK;
}
(5)、打印函数
打印这个栈所有元素的操作
Status print(SqStack *s)
{
int *temp;
temp = s->top;
while(temp != s->base)
{
temp--;
printf("%d", *temp);
}
}
2、栈的链式表达
栈的链式表示如下图所示。
栈的链式表达部分描述:
(1)、定义链栈结构体
typedef struct Stack_Node
{
ElemType data ;
struct Stack_Node *next ;
} Stack_Node ;
(2)、栈的初始化
Stack_Node * Init_Link_Stack(void)
{
Stack_Node *top;
top = (Stack_Node *)malloc(sizeof(Stack_Node));
top->next = NULL;
return(top);
}
(3)、进栈
Status push(Stack_Node *top, ElemType e)
{
Stack_Node *p;
p = (Stack_Node *)malloc(sizeof(Stack_Node));
if(!p) return ERROR; // 申请新结点失败,返回错误标志
p->data = e;
p->next = top-next;
top->next = p;
return OK;
}
(4)、出栈
Status pop(Stack_Node *top, ElemType &e) // 将栈顶元素出栈
{
Stack_Node *p;
ElemType e;
if(top->next == NULL) return ERROR; // 栈空,返回错误标志
p = top->next;
e= top->data;
top->next = p->next; // 修改栈顶指针
free(p);
return OK;
}