这里说的栈是指数据结构中的栈,而不是只内存布局中的栈。栈也是一种线性表,只不过栈是限定在表尾一端插入和删除操作。栈具有后进先出的特点,即Last In First Out。我们在许多应用中可以看到栈的影子,例如递归调用。我们把允许插入和删除的一端称为栈顶,另外一端则称为栈底。没有元素的栈称为空栈。栈对应的主要操作有:初始化一个栈initStack、判断一个栈是否为空栈stackEmpty、压入一个元素入栈push、弹出一个元素出栈pop以及返回栈顶元素getTop等操作。由于栈也是一种线性表,所以也有两种实现方式:一种是数组实现,即顺序存储方式实现;另外一种是用链式存储方式实现;
栈的数组实现如下所示:
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
typedef int Status;
//栈的顺序存储设计
#define MAXSIZE 20 //栈的容量
typedef int ElemType;
typedef struct{
ElemType data[MAXSIZE];
int top;//栈顶位置
}Sqstack;
/* *初始化堆栈,建立一个空栈
* 用top = -1 来表示空栈
* */
void initStack(Sqstack *S){
S->top = -1;//top == -1表示空栈
}
/* *
* 压入一个元素到堆栈中,并让top增1
* 成功返回1,失败返回0
* */
Status push(Sqstack *S,ElemType e)
{
if(S->top == MAXSIZE - 1)
{
return ERROR;//栈满,返回错误
}
S->top++;//top值加1
S->data[S->top] = e;
return OK;
}
/* *
* 从栈中弹出一个元素
* 成功返回1,并把元素值返回
* 失败返回0*/
Status pop(Sqstack *S,ElemType *e)
{
if(S->top == -1){
return ERROR;//栈为空,没有元素可以弹出
}
*e = S->data[S->top];
S->top--;//栈顶指针下移一个单位
return OK;
}
/* *
* 返回栈顶元素
* 成功返回1,并把元素存储在e中
* 失败返回0
* */
Status getTop(Sqstack *S,ElemType *e){
if(S->top == -1){
return ERROR;//没有元素
}
*e = S->data[S->top];
return OK;
}
/* *
* 判断一个栈是否为空
* 如果为空的话,则返回TRUE,否则返回FALSE
* */
Status stackEmpty(Sqstack S){
if(S.top == -1)
return TRUE;
else
return FALSE;
}
同样也可以用链表来实现栈,栈的链表实现如下:
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
typedef int Status;
//栈的链式存储设计
typedef struct StackNode{
ElemType data;
struct StackNode *next;
}StackNode,*LinkStackPtr;
typedef struct LinkStack{
LinkStackPtr top;//栈顶指针
int count;//链表节点数目
}LinkStack;
/* *
* 初始化栈,使栈为空栈,栈顶指针为NULL
* */
void initStack(LinkStack *S){
S->top = NULL;
S->count = 0;
}
/* *
* 判断一个栈是否为空,
* 如果为空则返回TRUE
* 不为空则返回FALSE
* */
Status stackEmpty(LinkStack *S){
if(S->top == NULL)
return TRUE;
else
return FALSE;
}
/* *
* 将一个元素压入栈中,
* 成功返回1
* */
Status push(LinkStack *S,ElemType e){
LinkStackPtr m = (LinkStackPtr)malloc(sizeof(StackNode));
m->data = e;
m->next = S->top;
S->top = m;
S->count++;
return OK;
}
/* *
* 从栈顶弹出一个元素
* 成功返回1,并将元素返回给e
* 失败返回0
* */
Status pop(LinkStack *S,ElemType *e){
if(S->top == NULL)
return ERROR;//空栈,没有元素可以弹出
LinkStackPtr p;
*e = S->top->data;
p = S->top;
S->top = S->top->next;
free(p);
S->count--;
return OK;
}
/* *
* 返回栈顶元素
* 成功返回1,并把元素返回
* 失败返回0
* */
Status getTop(LinkStack *S,ElemType *e){
if(S->top == NULL)
return ERROR;//空栈,没有元素返回
*e = S->top->data;
return OK;
}
不管栈是数组实现还是用链表实现,他们插入和删除一个元素所需要的时间都是O(1)。他们的实现都有各自的优缺点,就像是顺序存储线性表与链式存储线性表的优缺点一样。