栈和队列是两种重要的线性结构。从数据结构的角度看,栈和队列也是线性表,其特殊性在于栈和队列的操作位置都在特定的位置。
引用自严蔚敏的数据结构与算法教材
栈的结构体定义:
typedef struct Stack
{
int *base; //栈底指针
int *top; //栈顶指针
int stack_size; //栈的大小 也就是占用的空间sizeof(ElemType) * size;
}SqStack;
和链表类似 我们首先要初始化顺序栈:
SqStack initSqStack(int n)
{
SqStack S;
S.base = (int *)malloc(sizeof(int) * MAX_INIT_SIZE); //为顺序栈申请一块内存空间 内存空间大小 = sizeof(int) * S.stack_size
//验证内存空间是否申请成功
if (S.base == NULL)
{
printf("申请内存空间失败!\n");
exit(1);
}
S.top = S.base; //此时栈底指针base 和 栈顶指针top指向内存中的用一块内存空间
S.stack_size = MAX_INIT_SIZE;
for (int i = 0; i < 5; i++)
{
printf("请输入第%d个数据:", i + 1);
scanf("%d", S.top);
S.top++;
S.stack_size--;
}
return S;
}
但是 与链表相同 在初始化的同时为栈的元素赋值(应该这么说吧 emmmm^ _ ^)
下面画图解释一下为什么在最开始栈底指针base 和 栈顶指针top处在同一位置
在最开始的时候即栈为空栈时 top 和 base指向同一个地方 当顺序栈中读入了一个数据之后 top指针后移并且顺序栈大小减少1即Size-1 即如图所示
接下来介绍几个基本的操作函数:
//验证是否为空栈
void isEmpty(SqStack S)
{
if (S.top == S.base)
{
printf("栈为空!\n");
}
else printf("栈非空!\n");
}
这里稍微重点介绍一下插入元素这个操作:
//向栈中插入元素
SqStack pushElemToStack(SqStack S, int e)
{
//首先验证栈是否存满元素 如果栈慢就需要增加空间
if (S.top - S.base >= S.stack_size)
{
int *temp = S.base;
temp = (int *)realloc(S.base, sizeof(int) * (S.stack_size + MAX_CREATE_SIZE));
if (!temp)
{
printf("ERROR!\n");
exit(1);
}
S.base = temp;
S.top = S.base + S.stack_size;
S.stack_size += MAX_CREATE_SIZE;
}
*S.top = e;
S.top++; //以上两句可以合并为:*S.Top++ = e;
return S;
}
我们将代码拆分 具体介绍:
int *temp = S.base;
temp = (int *)realloc(S.base, sizeof(int) * (S.stack_size + MAX_CREATE_SIZE));
这两句代码 都来自于插入操作 之所以要将S.base重新保存 是因为 在下面的申请内存空间的代码中 会改变base的值 但是申请内存空间不一定会成功 所以要将base的值保存到temp中 这样即使申请内存空间失败 原来的栈依然不会受到任何影响
其中realloc()函数和malloc函数的功能类似 但是realloc()函数是重新分配空间 函数的第一个参数就是要改变大小的原内存地址
如果申请内存空间成功的话返回地址 失败则返回NULL 这也是为什么上面要将S.base保存起来的原因
在这里给出realloc函数的函数原型:extern void *realloc(void mem_address, unsigned int newsize);
realloc()函数在<stdlib.h>中(部分编译器还需要<malloc.h>),
用法:指针名=(数据类型)realloc(要改变内存大小的指针名,新的大小)
S.base = temp;
S.top = S.base + S.stack_size;
S.stack_size += MAX_CREATE_SIZE;
由于realloc函数改变了地址 即栈顶指针的指向也会随之改变:S.top = S.base + S.stack_size;
改变之后的栈大小为原大小+新增大小即:S.stack_size += MAX_CREATE_SIZE;
有了push操作(插入) 也应该有与之对应的pop操作(读取栈顶元素):
//读取栈顶元素
int popElem(SqStack *S)
{
//首先验证顺序栈是否为空
if (isEmpty(*S))
{
printf("栈为空!\n");
exit(1);
}
--(S->top);
return *S->top;
}
上最后两句可以合并为一句return * -- S->top
画图描述最后两句核心代码:
顺序栈的基本操作大概就是这些 如果各位看官觉得有帮助请帮我点赞转发 欢迎理性讨论:1781516638(qq)