第 3 章 栈和队列(链栈)

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 
#include 

/* 辅助函数,创建一个新的节点 */
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 

/* 打印栈元素 */
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. 输出示例

你可能感兴趣的:(#,数据结构(C语言版),数据结构,算法,c语言)