1>>导言
随着顺序表和链表的学习深入,我们开始步入新的章节,它的名字是"栈",是不是很可爱,就一个字,它的结构内容也很可爱,不像链表那么复杂的代码不可爱,像是顺序表的精简版本,那么接下来就来学习栈的内容。
本篇文章重点:了解新的数据结构栈,手动模拟实现数据结构栈
2>>栈介绍
栈属于一种特殊的线性表,没错它也是线性表,之前我们讲过,线性表是逻辑结构相连,物理结构不一定相连,而栈的结构,根据我们所选择的底层结构来判断结构,可以是顺序表,也可以是链表,那这里因为栈是只允许在一端插入或删除元素, **进行数据插入和删除的叫栈顶,另一端则为栈底。它只遵循后进先出的原则,**因此这里使用顺序表作为底层结构,因此它的物理结构也是线性的。
栈的插入叫做 入栈/压栈/进栈,入数据在栈顶部分
栈的删除叫做 出栈,出数据也在栈顶
这里借助这张图来帮助大家理解,整个栈好比一个水杯,入栈好比往栈顶加水,而出栈则表示喝水,我们喝水也是从上面喝,因此栈的概念也就非常好理解了。
结构跟顺序表差不多,唯一差别就是将size表示有效数据个数 改名为top表示栈顶位置(其实一样) 。arr表示栈(水杯)不知道需要多大,所以用指针类型,方便后面使用动态内存管理realloc进行更改,capacity表示容量。
代码实现如上。
3>>入栈
入栈跟顺序表尾插代码大差不差,当空间不足时都需要进行相应的补充,那么什么时候空间不足呢?当top等于capacity的时候,我们就会发现它的空间不足需要补充,这里需要注意一开始我们给capacity赋值为0,因此,这里需要用三目操作符,判断是否0,为0则改为4,否则改为原来大小的2倍。当全部结束时,将新的指针传给arr,新空间大小传给原来的空间大小。
最后实现入栈的操作即可。
4>>出栈
假设我们原来是这样的栈,出栈只需要将top--即可实现,后续如果有新的数据,会把3覆盖的
代码也很简单,需要先判断top是否为0,为0则删除不了,会报错,错误类型是对空指针解引用。
5>>取栈顶元素
这个也比较简单,只需要将top--就是栈顶元素,返回这个值就好,注意返回类型是data也就是我们最开始定义的可变数据类型。
其他的打印初始化销毁就不过多介绍啦,跟顺序表都差不多这里是博客链接:顺序表各项功能的实现-CSDN博客
现在附上代码,感兴趣的宝子下来可以自己试试喔~
6>>代码
stack.h
cpp
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<assert.h>
typedef int data;
typedef struct stack {
data* arr;
int top;
int capacity;
}stack;
void stinit(stack* pf); //初始化
void struin(stack* pf);//销毁
void stprint(stack* pf);//打印
void stenter(stack* pf, data x);//入栈
data stackpop(stack* pf);//出栈
data stackTop(stack* pf);//取栈顶元素
stack.c
cpp
#include"stack.h"
void stinit(stack* pf) {
pf->arr = NULL;
pf->capacity = pf->top = 0;
}
void struin(stack* pf) {
if (pf->arr != NULL);
free(pf->arr);
pf->arr = NULL;
pf->capacity = pf->top = 0;
}
void stprint(stack* pf) {
for (int i = 0; i < pf->top; i++) {
printf("%d ", pf->arr[i]);
}
printf("\n");
}
void stenter(stack* pf, data x) {
//空间不足
assert(pf);
if (pf->top == pf->capacity) {
int newcapacity = pf->capacity == 0 ? 4 : pf->capacity * 2;
data* tmp = (data*)realloc(pf->arr, newcapacity * sizeof(data));
if (tmp == NULL) {
perror("realloc");
exit(1);
}
pf->arr = tmp;
pf->capacity = newcapacity;
}
//入栈
pf->arr[pf->top++] = x;
}
bool stackempty(stack* pf) {
assert(pf);
return pf->top != 0;
}
data stackpop(stack* pf) {
assert(stackempty(pf));
return --pf->top;
}
data stackTop(stack* pf)
{
assert(StackEmpty(pf));
return pf->arr[pf->top - 1];
}
test.c
cpp
#include"stack.h"
void test()
{
stack list;
stinit(&list);
stenter(&list, 1);
stprint(&list);
stenter(&list, 2);
stprint(&list);
stenter(&list, 3);
stprint(&list);
stenter(&list, 4);
stprint(&list);
data a=stleave(&list);
printf("%d", a); a=stleave(&list);
printf("%d", a); a=stleave(&list);
printf("%d", a); a=stleave(&list);
printf("%d", a);
}
int main()
{
test();
return 0;
}
6>>结语
栈的内容在学习了顺序表之后是不是感觉易如反掌哩,很可爱吧代码很少,用的地方可不少,如回文数,判断对称性的题目就很好用,谢谢大家的观看,期待下一篇与你相见!