链栈的表示与实现
栈也是线性表,是操作受限的线性表。栈的操作是线性表操作的子集。因此,也可以将线性表的结构作为栈的结构。
下面,就是把带头结点的线性单链表结构作为链栈的结构,这样,线性单链表的一些基本操作就可以直接用于链栈的操作了。
例如,初始化链表和初始化链栈的操作是一样的。需要注意的是,由于栈的操作被限定仅在栈顶进行,显然,令表头为栈顶可简化栈的操作。
typedef int Status; /* Status是函数的类型,其值是函数结果状态代码,如OK等 */
typedef int Boolean; /* Boolean是布尔类型,其值是TRUE或FALSE */
typedef int SElemType; /* 定义栈元素的类型 */
#include<malloc.h> /* malloc()等 */
#include<stdio.h> /* EOF(=^Z或F6),NULL */
#include<process.h> /* exit() */
/* 函数结果状态代码 */
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
/* -------------------------- 链栈存储表示 -----------------------------*/
/* 栈结点类型和链表结点类型一致 */
struct LNode
{
SElemType data;
struct LNode *next;
};
typedef struct LNode *LinkStack; /* LinkStack是指向栈结点的指针类型 */
/* ----------------------------------------------------------------------------*/
void print(SElemType c)
{
printf("%d ", c);
}
/* 链栈的基本操作(9个) */
/* -------------------- 基本操作的函数原型说明 ---------------------*/
Status InitStack(LinkStack *S);
Status DestroyStack(LinkStack *S);
Status ClearStack(LinkStack S);
Status StackEmpty(LinkStack S);
int StackLength(LinkStack S);
Status Push(LinkStack S, SElemType e);
Status Pop(LinkStack S, SElemType *e);
Status GetTop(LinkStack S, SElemType *e);
Status StackTraverse(LinkStack S, Status(*visit)(SElemType));
/* --------------------------------- 基本操作的实现 ------------------------------------*/
Status InitStack(LinkStack *S)
{ /* 操作结果:构造一个空链栈S */
*S = (LinkStack)malloc(sizeof(struct LNode)); /* 产生头结点,并使S指向此头结点 */
if (!*S) /* 存储分配失败 */
exit(OVERFLOW);
(*S)->next = NULL; /* 指针域为空 */
return OK;
}
Status DestroyStack(LinkStack *S)
{ /* 初始条件:链栈S已存在。操作结果:销毁链栈S */
LinkStack q;
while (*S)
{
q = (*S)->next;
free(*S);
*S = q;
}
return OK;
}
Status ClearStack(LinkStack S) /* 不改变S */
{ /* 初始条件:链栈S已存在。操作结果:将S重置为空栈 */
LinkStack p, q;
p = S->next; /* p指向第一个结点 */
while (p) /* 没到栈底 */
{
q = p->next;
free(p);
p = q;
}
S->next = NULL; /* 头结点指针域为空 */
return OK;
}
Status StackEmpty(LinkStack S)
{ /* 初始条件:链栈S已存在。操作结果:若S为空表,则返回TRUE,否则返回FALSE */
if (S->next) /* 非空 */
return FALSE;
else
return TRUE;
}
int StackLength(LinkStack S)
{ /* 初始条件:链栈S已存在。操作结果:返回S中数据元素个数 */
int i = 0;
LinkStack p = S->next; /* p指向第一个结点 */
while (p) /* 没到表尾 */
{
i++;
p = p->next;
}
return i;
}
Status Push(LinkStack S, SElemType e)
{ /* 初始条件:链栈S已存在。操作结果:在S的栈顶插入新的数据元素e,作为栈顶的第一个元素 */
LinkStack s;
s = (LinkStack)malloc(sizeof(struct LNode)); /* 生成新结点 */
s->data = e; /* 给结点赋值 */
s->next = S->next; /* 插在表头 */
S->next = s;
return OK;
}
Status Pop(LinkStack S, SElemType *e)
{ /* 初始条件:链栈S已存在,且有不少于1个元素 */
/* 操作结果:删除S的栈顶数据元素,并由e返回其值 */
LinkStack p = S->next;
if (p)
{
*e = p->data;
S->next = p->next;
free(p);
return OK;
}
else
return ERROR;
}
Status GetTop(LinkStack S, SElemType *e)
{ /* 返回栈顶元素的值 */
LinkStack p = S->next;
if (!p) /* 空表 */
return ERROR;
else /* 非空表 */
*e = p->data;
return OK;
}
Status StackTraverse(LinkStack S, Status(*visit)(SElemType))
{ //从栈底到栈顶依次对栈中每个元素调用函数visit()。
SElemType e;
LinkStack temp, p = S;
InitStack(&temp); //初始化temp栈
while (p->next)
{
GetTop(p, &e);
Push(temp, e);
p = p->next;
}
p = temp->next;
while (p)
{
visit(p->data);
p = p->next;
}
printf("\n");
return OK;
}
/* 检验以上操作的主程序 */
void main()
{
int j;
LinkStack s;
SElemType e;
if (InitStack(&s))
for (j = 1; j <= 5; j++)
Push(s, 2 * j);
printf("栈中的元素从栈底到栈顶依次为: ");
StackTraverse(s, print);
Pop(s, &e);
printf("弹出的栈顶元素为%d\n", e);
printf("栈空否: %d(1:空 0:否)\n", StackEmpty(s));
GetTop(s, &e);
printf("当前栈顶元素为%d,栈的长度为%d\n", e, StackLength(s));
ClearStack(s);
printf("清空栈后,栈空否: %d(1:空 0:否),栈的长度为%d\n", StackEmpty(s), StackLength(s));
printf("是否销毁栈了: %d(1:是 0:否)\n", DestroyStack(&s));
}
运行结果: