数据结构之顺序栈——C语言实现
- 一、代码注释
- 1.相关头文件
- 2.宏定义内容
- 3.可读性优化及栈类型声明
- 4.相关函数
- 1)`void InitStack(SqStack *S);`初始化顺序栈
- 2)`void DestroyStack(SqStack *S);`销毁栈
- 3)`void ClearStack(SqStack *S);`清空栈
- 4)`Status StackEmpty(SqStack S);`判断栈空
- 5)`Status StackFull(SqStack S);`判断栈满
- 6)`int StackLength(SqStack S);`返回栈长
- 7)`SElemType GetStackTop(SqStack S);`返回栈顶元素
- 8)`void Push(SqStack *S, SElemType e);`压栈
- 9)`void Pop(SqStack *S, SElemType *e);`弹栈
- 10)`void StackTraverse(SqStack S, void *visit(SElemType));`遍历栈元素
- 二、完整代码
- 三、总结
一、代码注释
1.相关头文件
#include <malloc.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
malloc.h
:malloc()
和realloc()
malloc()
用于初始化栈,realloc()
用于栈内存不足时扩容
stdlib.h
stdio.h
:
stdbool.h
:bool类型变量
2.宏定义内容
//根据使用的具体情况修改
#define SElemType int
#define SElemType_Flag "int"
#define SFormat "%d\t"
#define SPath ""
SElemType
:栈中元素类型
SElemType_Flag
:用于初始化告知栈中元素类型
SFormat "%d\t"
:用于遍历打印/追踪栈运行进程/写入文件的格式
SPath
:用于遍历栈中元素写入文件
#define STACK_INIT_SIZE 100
#define STACKINCREMENT 10
STACK_INIT_SIZE
:初始化栈的规模
STACKINCREMENT
:每次栈内存不足时扩容的规模
#define SDisplayFlag 1
DisplayFlag
:用于程序运行追踪
3.可读性优化及栈类型声明
typedef bool Status;
typedef struct SqStack
{
SElemType *base;
SElemType *top;
int stacksize;
} SqStack;
4.相关函数
1)void InitStack(SqStack *S);
初始化顺序栈
void InitStack(SqStack *S)
{
S->base = (SElemType *)malloc(STACK_INIT_SIZE * sizeof(SElemType));
if (!S->base)
{
printf("顺序栈初始化失败");
exit(1);
}
S->top = S->base;
S->stacksize = STACK_INIT_SIZE;
printf("顺序栈初始化完成\n");
printf("栈中元素为" SElemType_Flag "类型\n");
}
2)void DestroyStack(SqStack *S);
销毁栈
void DestroyStack(SqStack *S)
{
free(S->base);
S->stacksize = 0;
S->base = S->top = NULL;
}
3)void ClearStack(SqStack *S);
清空栈
void ClearStack(SqStack *S)
{
S->top = S->base;
}
4)Status StackEmpty(SqStack S);
判断栈空
Status StackEmpty(SqStack S)
{
if (S.top == S.base)
return true;
else
return false;
}
5)Status StackFull(SqStack S);
判断栈满
Status StackFull(SqStack S)
{
if (S.top - S.base == S.stacksize)
return true;
else
return false;
}
6)int StackLength(SqStack S);
返回栈长
int StackLength(SqStack S)
{
return S.top - S.base;
}
7)SElemType GetStackTop(SqStack S);
返回栈顶元素
SElemType GetStackTop(SqStack S)
{
if (StackEmpty(S)) // 栈空
{
printf("取栈顶元素错误:顺序栈为空");
exit(1);
}
else
{
if (SDisplayFlag)
printf("栈顶元素:" SFormat, *(S.top - 1));
return *(S.top - 1);
}
}
8)void Push(SqStack *S, SElemType e);
压栈
插入元素e为新的栈顶元素
void Push(SqStack *S, SElemType e)
{
if (StackFull(*S)) // 栈满
{
S->base = (SElemType *)realloc(S->base, (S->stacksize + STACKINCREMENT) * sizeof(SElemType));
if (!S->base)
{
printf("顺序栈增加容量错误");
exit(1);
}
S->top = S->base + S->stacksize;
S->stacksize += STACKINCREMENT;
}
*S->top++ = e; //=*(S->top)=e;S->top++;
if (SDisplayFlag)
printf("压栈:" SFormat, e);
}
9)void Pop(SqStack *S, SElemType *e);
弹栈
删除S的栈顶元素,并用e返回其值
void Pop(SqStack *S, SElemType *e)
{
if (StackEmpty(*S)) // 栈空
{
printf("弹栈错误:顺序栈为空");
exit(1);
}
else
*e = *--S->top; //=--S->top;e = *(S->top);
if (SDisplayFlag)
printf("弹栈:" SFormat, *e);
}
10)void StackTraverse(SqStack S, void *visit(SElemType));
遍历栈元素
从栈底到栈顶依次对S的每个元素调用函数
visit()
void StackTraverse(SqStack S, void visit(SElemType))
{
if (StackEmpty(S)) // 栈空
{
printf("栈遍历错误:顺序栈为空");
exit(1);
}
SElemType *temp = S.base;
printf("栈中共%d个元素:\n", StackLength(S));
while (temp != S.top)
{
visit(*temp);
temp++;
}
if (SPath == "")
printf("\n");
else
{
FILE *fp = fopen(SPath, "a");
fprintf(fp,"\n");
fclose(fp);
}
}
void PrintSElem(SElemType e)
{
printf(SFormat, e);
}
void FPrintSElem(SElemType e)
{
FILE *fp = fopen(SPath,"a");
fprintf(fp,SFormat,e);
fclose(fp);
}
二、完整代码
/*
名称:SqStack.h
内容:顺序栈相关操作
创建者:尘
最近更新时间:2023年10月26日16:04:36
修改:
#define SElemType
#define SElemType_Flag
#define Format
#define Path
*/
#include <malloc.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
// 根据使用的具体情况修改
// 栈中数据类型及打印格式
#ifndef SElemType
#define SElemType int
#endif
#ifndef SElemType_Flag
#define SElemType_Flag "int"
#endif
#ifndef SFormat
#define SFormat "%d\t"
#endif
#ifndef SPath
#define SPath ""
#endif
// 顺序栈的规模
#define STACK_INIT_SIZE 100
#define STACKINCREMENT 10
// 便于程序运行追踪
#define SDisplayFlag 0
#ifndef Status
typedef bool Status;
#endif
typedef struct SqStack
{
SElemType *base;
SElemType *top;
int stacksize;
} SqStack;
void InitStack(SqStack *S)
{
S->base = (SElemType *)malloc(STACK_INIT_SIZE * sizeof(SElemType));
if (!S->base)
{
printf("顺序栈初始化失败");
exit(1);
}
S->top = S->base;
S->stacksize = STACK_INIT_SIZE;
printf("顺序栈初始化完成\n");
printf("栈中元素为" SElemType_Flag "类型\n");
}
void DestroyStack(SqStack *S)
{
free(S->base);
S->stacksize = 0;
S->base = S->top = NULL;
}
void ClearStack(SqStack *S)
{
S->top = S->base;
}
Status StackEmpty(SqStack S)
{
if (S.top == S.base)
return true;
else
return false;
}
Status StackFull(SqStack S)
{
if (S.top - S.base == S.stacksize)
return true;
else
return false;
}
int StackLength(SqStack S)
{
return S.top - S.base;
}
SElemType GetStackTop(SqStack S)
{
if (StackEmpty(S)) // 栈空
{
printf("取栈顶元素错误:顺序栈为空");
exit(1);
}
else
{
if (SDisplayFlag)
printf("栈顶元素:" SFormat, *(S.top - 1));
return *(S.top - 1);
}
}
void Push(SqStack *S, SElemType e)
{
if (StackFull(*S)) // 栈满
{
S->base = (SElemType *)realloc(S->base, (S->stacksize + STACKINCREMENT) * sizeof(SElemType));
if (!S->base)
{
printf("顺序栈增加容量错误");
exit(1);
}
S->top = S->base + S->stacksize;
S->stacksize += STACKINCREMENT;
}
*S->top++ = e; //=*(S->top)=e;S->top++;
if (SDisplayFlag)
printf("压栈:" SFormat, e);
}
void Pop(SqStack *S, SElemType *e)
{
if (StackEmpty(*S)) // 栈空
{
printf("弹栈错误:顺序栈为空");
exit(1);
}
else
*e = *--S->top; //=--S->top;e = *(S->top);
if (SDisplayFlag)
printf("弹栈:" SFormat, *e);
}
void StackTraverse(SqStack S, void visit(SElemType))
{
if (StackEmpty(S)) // 栈空
{
printf("栈遍历错误:顺序栈为空");
exit(1);
}
SElemType *temp = S.base;
printf("栈中共%d个元素:\n", StackLength(S));
while (temp != S.top)
{
visit(*temp);
temp++;
}
if (SPath == "")
printf("\n");
else
{
FILE *fp = fopen(SPath, "a");
fprintf(fp, "\n");
fclose(fp);
}
}
void PrintSElem(SElemType e)
{
printf(SFormat, e);
}
void FPrintSElem(SElemType e)
{
FILE *fp = fopen(SPath, "a");
fprintf(fp, SFormat, e);
fclose(fp);
}
三、总结
学习过程中手敲的顺序栈相关操作,便于后续偷懒使用不是,如果大家发现有什么bug,欢迎评论指正。