1. 背景说明
链栈是指用单链表实现的栈,其存储结构为链式存储,实现类似于队列的链式实现,不过在插入元素时链栈在头部插入,而
链式队列在尾部插入,本示例中实现为带头结点的链栈,即栈顶元素为栈指针的下一个元素。
2. 示例代码
1) status.h
/* DataStructure 预定义常量和类型头文件 */
#ifndef STATUS_H
#define STATUS_H
/* 函数结果状态码 */
#define TRUE 1 /* 返回值为真 */
#define FALSE 0 /* 返回值为假 */
#define RET_OK 0 /* 返回值正确 */
#define INFEASIABLE 2 /* 返回值未知 */
#define ERR_MEMORY 3 /* 访问内存错 */
#define ERR_NULL_PTR 4 /* 空指针错误 */
#define ERR_MEMORY_ALLOCATE 5 /* 内存分配错 */
#define ERR_NULL_STACK 6 /* 栈元素为空 */
#define ERR_PARA 7 /* 函数参数错 */
#define ERR_OPEN_FILE 8 /* 打开文件错 */
#define ERR_NULL_QUEUE 9 /* 队列为空错 */
#define ERR_FULL_QUEUE 10 /* 队列为满错 */
typedef int Status; /* Status 是函数的类型,其值是函数结果状态代码,如 RET_OK 等 */
typedef int Bollean; /* Boolean 是布尔类型,其值是 TRUE 或 FALSE */
#endif // !STATUS_H
2) linkStack.h
/* 链栈定义头文件 */
#ifndef LINKSTACK_H
#define LINKSTACK_H
#include "status.h"
typedef int SElemType;
typedef struct LNode {
SElemType data;
struct LNode *next;
} *LinkStack;
/* 辅助函数,创建一个新的节点 */
LinkStack MakeNewLNode(SElemType e);
/* 操作结果:构造一个空栈 */
Status InitStack(LinkStack *S);
/* 初始条件:链栈 S 已存在。操作结果:销毁链栈 S */
Status DestroyStack(LinkStack *S);
/* 初始条件:链栈 S 已存在。操作结果:将 S 重置为空表 */
Status ClearStack(LinkStack S);
/* 初始条件:链栈 S 已存在。操作结果:若 S 为空表,则返回 TRUE,否则返回 FALSE */
Bollean StackEmpty(LinkStack S);
/* 初始条件:链栈 S 已存在。操作结果:返回 S 中数据元素个数 */
int StackLength(LinkStack S);
/* S 为带头结点的链栈的头指针。当第 1 个元素存在时, 其值赋给 e 并返回 OK,否则返回 ERROR */
Status GetTop(LinkStack S, SElemType *e);
/* 在带头结点的链栈 S 中第 1 个位置之前插入元素 e */
Status Push(LinkStack S, SElemType e);
/* 在带头结点的链栈 S 中,删除第 1 个元素,并由 e 返回其值 */
Status Pop(LinkStack S, SElemType *e);
/* 初始条件:链栈 S 已存在
操作结果:依次对 S 的每个数据元素调用函数 vi()。一旦 vi() 失败,则操作失败 */
Status StackTraverse(LinkStack S, void(*vi)(SElemType));
#endif // !LINKSTACK_H
3) linkStack.c
/* 链栈实现源文件 */
#include "linkStack.h"
#include <stdio.h>
#include <stdlib.h>
/* 辅助函数,创建一个新的节点 */
LinkStack MakeNewLNode(SElemType e)
{
LinkStack newLNode = (LinkStack)malloc(sizeof(struct LNode));
if (!newLNode) {
printf("FuncName: %-15s Line: %-5d ErrorCode: %-3d\n", __func__, __LINE__, ERR_MEMORY_ALLOCATE);
return NULL;
}
newLNode->data = e;
newLNode->next = NULL;
return newLNode;
}
/* 操作结果:构造一个空栈 */
Status InitStack(LinkStack *S)
{
*S = (LinkStack)malloc(sizeof(struct LNode));
if (!(*S)) {
printf("FuncName: %-15s Line: %-5d ErrorCode: %-3d\n", __func__, __LINE__, ERR_MEMORY_ALLOCATE);
return ERR_MEMORY_ALLOCATE;
}
(*S)->next = NULL;
return RET_OK;
}
/* 初始条件:链栈 S 已存在。操作结果:销毁链栈 S */
Status DestroyStack(LinkStack *S)
{
LinkStack p;
while (*S) {
p = (*S)->next;
free(*S);
*S = p;
}
return RET_OK;
}
/* 初始条件:链栈 S 已存在。操作结果:将 S 重置为空表 */
Status ClearStack(LinkStack S)
{
LinkStack p = S->next, q;
while (p) {
q = p->next;
free(p);
p = q;
}
S->next = NULL;
return RET_OK;
}
/* 初始条件:链栈 S 已存在。操作结果:若 S 为空表,则返回 TRUE,否则返回 FALSE */
Bollean StackEmpty(LinkStack S)
{
return (S->next == NULL) ? TRUE : FALSE;
}
/* 初始条件:链栈 S 已存在。操作结果:返回 S 中数据元素个数 */
int StackLength(LinkStack S)
{
int length = 0;
LinkStack p = S->next;
while (p) {
++length;
p = p->next;
}
return length;
}
/* S 为带头结点的链栈的头指针。当第 1 个元素存在时, 其值赋给 e 并返回 OK,否则返回 ERROR */
Status GetTop(LinkStack S, SElemType *e)
{
if (!S) {
printf("FuncName: %-15s Line: %-5d ErrorCode: %-3d\n", __func__, __LINE__, ERR_NULL_PTR);
return ERR_NULL_PTR;
}
if (!S->next) {
printf("FuncName: %-15s Line: %-5d ErrorCode: %-3d\n", __func__, __LINE__, ERR_NULL_STACK);
return ERR_NULL_STACK;
}
*e = S->next->data;
return RET_OK;
}
/* 在带头结点的链栈 S 中第 1 个位置之前插入元素 e */
Status Push(LinkStack S, SElemType e)
{
if (!S) {
printf("FuncName: %-15s Line: %-5d ErrorCode: %-3d\n", __func__, __LINE__, ERR_NULL_PTR);
return ERR_NULL_PTR;
}
LinkStack newNode = MakeNewLNode(e);
if (!newNode) {
printf("FuncName: %-15s Line: %-5d ErrorCode: %-3d\n", __func__, __LINE__, ERR_NULL_PTR);
return ERR_NULL_PTR;
}
newNode->next = S->next;
S->next = newNode;
return RET_OK;
}
/* 在带头结点的链栈 S 中,删除第 1 个元素,并由 e 返回其值 */
Status Pop(LinkStack S, SElemType *e)
{
if (!S) {
printf("FuncName: %-15s Line: %-5d ErrorCode: %-3d\n", __func__, __LINE__, ERR_NULL_PTR);
return ERR_NULL_PTR;
}
if (!S->next) {
printf("FuncName: %-15s Line: %-5d ErrorCode: %-3d\n", __func__, __LINE__, ERR_NULL_STACK);
return ERR_NULL_STACK;
}
LinkStack p = S->next;
S->next = p->next;
*e = p->data;
free(p);
return RET_OK;
}
/* 初始条件:链栈 S 已存在
操作结果:依次对 S 的每个数据元素调用函数 vi()。一旦 vi() 失败,则操作失败 */
Status StackTraverse(LinkStack S, void(*vi)(SElemType))
{
LinkStack p = S->next;
while (p) {
vi(p->data);
p = p->next;
}
return RET_OK;
}
4) auxiliary.h
/* 辅助函数头文件 */
#ifndef AUXILIARY_H
#define AUXILIARY_H
#include "linkStack.h"
/* 打印栈元素 */
void Print(SElemType e);
#endif // !AUXILIARY_H
5) auxiliary.c
/* 辅助函数实现源文件 */
#include "auxiliary.h"
#include <stdio.h>
/* 打印栈元素 */
void Print(SElemType e)
{
printf("%d ", e);
}
6) main.c
/* 入口程序源文件 */
#include "auxiliary.h"
#include "linkStack.h"
#include "status.h"
int main(void)
{
LinkStack S;
Status ret = InitStack(&S);
if (ret != RET_OK) {
printf("FuncName: %-15s Line: %-5d ErrorCode: %-3d\n", __func__, __LINE__, ret);
return ret;
}
for (int i = 0; i < 5; ++i) {
Push(S, 2 * (i + 1));
}
printf("The element of the stack from top to bottom is: ");
StackTraverse(S, Print);
printf("\n");
SElemType e;
Pop(S, &e);
printf("The element of the top of the stack is %d\n", e);
printf("The stack is %s\n", StackEmpty(S) ? "empty" : "not empty");
ClearStack(S);
printf("After clear the stack, the stack is %s\n", StackEmpty(S) ? "empty" : "not empty");
ret = DestroyStack(&S);
if (ret == RET_OK) {
printf("Destroy stack success!\n");
}
return ret;
}
3. 输出示例